Cloudflare - Version 4.7.0

Version Description

  • 2021-10-28 =

  • Merge cloudflare-plugin-backend into Cloudflare-WordPress repository

Download this release

Release Info

Developer manatarms
Plugin Icon 128x128 Cloudflare
Version 4.7.0
Comparing to
See all releases

Code changes from version 4.6.0 to 4.7.0

Files changed (245) hide show
  1. cloudflare.php +1 -1
  2. composer.json +4 -3
  3. composer.lock +241 -75
  4. config.json +1 -1
  5. output.log +14 -14
  6. readme.txt +8 -4
  7. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/APIInterface.php +0 -0
  8. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/AbstractAPIClient.php +0 -0
  9. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/AbstractPluginActions.php +1 -1
  10. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Client.php +7 -0
  11. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/DefaultHttpClient.php +4 -1
  12. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Exception/CloudFlareException.php +0 -0
  13. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Exception/ZoneSettingFailException.php +0 -0
  14. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Host.php +1 -1
  15. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/HttpClientInterface.php +0 -0
  16. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Plugin.php +0 -0
  17. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/PluginRoutes.php +0 -0
  18. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Request.php +0 -0
  19. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/DNSRecord.php +0 -0
  20. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/ConfigInterface.php +0 -0
  21. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DataStoreInterface.php +0 -0
  22. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DefaultConfig.php +0 -0
  23. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DefaultIntegration.php +0 -0
  24. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DefaultLogger.php +0 -0
  25. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/IntegrationAPIInterface.php +0 -0
  26. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/IntegrationInterface.php +0 -0
  27. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Router/DefaultRestAPIRouter.php +0 -0
  28. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Router/RequestRouter.php +0 -0
  29. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Router/RouterInterface.php +0 -0
  30. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/SecurityUtil.php +0 -3
  31. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/AbstractAPIClientTest.php +9 -9
  32. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/AbstractPluginActionsTest.php +6 -9
  33. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/ClientTest.php +2 -2
  34. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/DefaultHttpClientTest.php +5 -5
  35. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/HostTest.php +2 -2
  36. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/PluginTest.php +2 -2
  37. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Integration/DefaultConfigTest.php +1 -1
  38. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Integration/DefaultLoggerTest.php +1 -1
  39. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Router/DefaultRestAPIRouterTest.php +2 -2
  40. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Router/RequestRouterTest.php +2 -2
  41. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/SecurityUtilTest.php +1 -1
  42. src/Test/WordPress/ClientActionsTest.php +1 -1
  43. {vendor/cloudflare/cloudflare-plugin-backend/src → src}/Utils.php +0 -0
  44. src/WordPress/Utils.php +10 -0
  45. vendor/autoload.php +1 -1
  46. vendor/cloudflare/cloudflare-plugin-backend/.travis.yml +0 -12
  47. vendor/cloudflare/cloudflare-plugin-backend/CHANGELOG.md +0 -156
  48. vendor/cloudflare/cloudflare-plugin-backend/LICENSE.md +0 -11
  49. vendor/cloudflare/cloudflare-plugin-backend/README.md +0 -13
  50. vendor/cloudflare/cloudflare-plugin-backend/composer.json +0 -24
  51. vendor/cloudflare/cloudflare-plugin-backend/composer.lock +0 -1457
  52. vendor/composer/autoload_files.php +1 -0
  53. vendor/composer/autoload_psr4.php +5 -1
  54. vendor/composer/autoload_real.php +7 -7
  55. vendor/composer/autoload_static.php +32 -6
  56. vendor/composer/installed.json +188 -18
  57. vendor/guzzlehttp/guzzle/.travis.yml +52 -0
  58. vendor/guzzlehttp/guzzle/CHANGELOG.md +1075 -0
  59. vendor/guzzlehttp/guzzle/LICENSE +19 -0
  60. vendor/guzzlehttp/guzzle/README.md +70 -0
  61. vendor/guzzlehttp/guzzle/UPGRADING.md +1050 -0
  62. vendor/guzzlehttp/guzzle/composer.json +38 -0
  63. vendor/guzzlehttp/guzzle/src/BatchResults.php +148 -0
  64. vendor/guzzlehttp/guzzle/src/Client.php +362 -0
  65. vendor/guzzlehttp/guzzle/src/ClientInterface.php +150 -0
  66. vendor/guzzlehttp/guzzle/src/Collection.php +236 -0
  67. vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +248 -0
  68. vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +75 -0
  69. vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +86 -0
  70. vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +66 -0
  71. vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +373 -0
  72. vendor/guzzlehttp/guzzle/src/Event/AbstractEvent.php +20 -0
  73. vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php +61 -0
  74. vendor/guzzlehttp/guzzle/src/Event/AbstractRetryableEvent.php +40 -0
  75. vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php +63 -0
  76. vendor/guzzlehttp/guzzle/src/Event/BeforeEvent.php +26 -0
  77. vendor/guzzlehttp/guzzle/src/Event/CompleteEvent.php +14 -0
  78. vendor/guzzlehttp/guzzle/src/Event/Emitter.php +145 -0
  79. vendor/guzzlehttp/guzzle/src/Event/EmitterInterface.php +96 -0
  80. vendor/guzzlehttp/guzzle/src/Event/EndEvent.php +28 -0
  81. vendor/guzzlehttp/guzzle/src/Event/ErrorEvent.php +27 -0
  82. vendor/guzzlehttp/guzzle/src/Event/EventInterface.php +23 -0
  83. vendor/guzzlehttp/guzzle/src/Event/HasEmitterInterface.php +15 -0
  84. vendor/guzzlehttp/guzzle/src/Event/HasEmitterTrait.php +20 -0
  85. vendor/guzzlehttp/guzzle/src/Event/ListenerAttacherTrait.php +88 -0
  86. vendor/guzzlehttp/guzzle/src/Event/ProgressEvent.php +51 -0
  87. vendor/guzzlehttp/guzzle/src/Event/RequestEvents.php +56 -0
  88. vendor/guzzlehttp/guzzle/src/Event/SubscriberInterface.php +34 -0
  89. vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php +7 -0
  90. vendor/guzzlehttp/guzzle/src/Exception/ClientException.php +7 -0
  91. vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php +4 -0
  92. vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php +4 -0
  93. vendor/guzzlehttp/guzzle/src/Exception/ParseException.php +31 -0
  94. vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +121 -0
  95. vendor/guzzlehttp/guzzle/src/Exception/ServerException.php +7 -0
  96. vendor/guzzlehttp/guzzle/src/Exception/StateException.php +4 -0
  97. vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +4 -0
  98. vendor/guzzlehttp/guzzle/src/Exception/TransferException.php +4 -0
  99. vendor/guzzlehttp/guzzle/src/Exception/XmlParseException.php +34 -0
  100. vendor/guzzlehttp/guzzle/src/HasDataTrait.php +75 -0
  101. vendor/guzzlehttp/guzzle/src/Message/AbstractMessage.php +253 -0
  102. vendor/guzzlehttp/guzzle/src/Message/AppliesHeadersInterface.php +24 -0
  103. vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php +158 -0
  104. vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php +364 -0
  105. vendor/guzzlehttp/guzzle/src/Message/MessageFactoryInterface.php +71 -0
  106. vendor/guzzlehttp/guzzle/src/Message/MessageInterface.php +136 -0
  107. vendor/guzzlehttp/guzzle/src/Message/MessageParser.php +171 -0
  108. vendor/guzzlehttp/guzzle/src/Message/Request.php +195 -0
  109. vendor/guzzlehttp/guzzle/src/Message/RequestInterface.php +136 -0
  110. vendor/guzzlehttp/guzzle/src/Message/Response.php +208 -0
  111. vendor/guzzlehttp/guzzle/src/Message/ResponseInterface.php +111 -0
  112. vendor/guzzlehttp/guzzle/src/Mimetypes.php +963 -0
  113. vendor/guzzlehttp/guzzle/src/Pool.php +333 -0
  114. vendor/guzzlehttp/guzzle/src/Post/MultipartBody.php +109 -0
  115. vendor/guzzlehttp/guzzle/src/Post/PostBody.php +287 -0
  116. vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php +109 -0
  117. vendor/guzzlehttp/guzzle/src/Post/PostFile.php +135 -0
  118. vendor/guzzlehttp/guzzle/src/Post/PostFileInterface.php +41 -0
  119. vendor/guzzlehttp/guzzle/src/Query.php +204 -0
  120. vendor/guzzlehttp/guzzle/src/QueryParser.php +163 -0
  121. vendor/guzzlehttp/guzzle/src/RequestFsm.php +153 -0
  122. vendor/guzzlehttp/guzzle/src/RingBridge.php +165 -0
  123. vendor/guzzlehttp/guzzle/src/Subscriber/Cookie.php +58 -0
  124. vendor/guzzlehttp/guzzle/src/Subscriber/History.php +172 -0
  125. vendor/guzzlehttp/guzzle/src/Subscriber/HttpError.php +36 -0
  126. vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php +147 -0
  127. vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php +130 -0
  128. vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php +176 -0
  129. vendor/guzzlehttp/guzzle/src/ToArrayInterface.php +15 -0
  130. vendor/guzzlehttp/guzzle/src/Transaction.php +103 -0
  131. vendor/guzzlehttp/guzzle/src/UriTemplate.php +241 -0
  132. vendor/guzzlehttp/guzzle/src/Url.php +595 -0
  133. vendor/guzzlehttp/guzzle/src/Utils.php +215 -0
  134. vendor/guzzlehttp/ringphp/.travis.yml +43 -0
  135. vendor/guzzlehttp/ringphp/CHANGELOG.md +118 -0
  136. vendor/guzzlehttp/ringphp/LICENSE +19 -0
  137. vendor/guzzlehttp/ringphp/Makefile +46 -0
  138. vendor/guzzlehttp/ringphp/README.rst +46 -0
  139. vendor/guzzlehttp/ringphp/composer.json +43 -0
  140. vendor/guzzlehttp/ringphp/docs/Makefile +153 -0
  141. vendor/guzzlehttp/ringphp/docs/client_handlers.rst +173 -0
  142. vendor/guzzlehttp/ringphp/docs/client_middleware.rst +165 -0
  143. vendor/guzzlehttp/ringphp/docs/conf.py +23 -0
  144. vendor/guzzlehttp/ringphp/docs/futures.rst +164 -0
  145. vendor/guzzlehttp/ringphp/docs/index.rst +50 -0
  146. vendor/guzzlehttp/ringphp/docs/requirements.txt +1 -0
  147. vendor/guzzlehttp/ringphp/docs/spec.rst +311 -0
  148. vendor/guzzlehttp/ringphp/docs/testing.rst +74 -0
  149. vendor/guzzlehttp/ringphp/phpunit.xml.dist +14 -0
  150. vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php +74 -0
  151. vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php +560 -0
  152. vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php +135 -0
  153. vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php +248 -0
  154. vendor/guzzlehttp/ringphp/src/Client/Middleware.php +58 -0
  155. vendor/guzzlehttp/ringphp/src/Client/MockHandler.php +52 -0
  156. vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php +414 -0
  157. vendor/guzzlehttp/ringphp/src/Core.php +364 -0
  158. vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php +7 -0
  159. vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php +4 -0
  160. vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php +7 -0
  161. vendor/guzzlehttp/ringphp/src/Exception/RingException.php +4 -0
  162. vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php +125 -0
  163. vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php +43 -0
  164. vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php +57 -0
  165. vendor/guzzlehttp/ringphp/src/Future/FutureArray.php +40 -0
  166. vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php +11 -0
  167. vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php +40 -0
  168. vendor/guzzlehttp/ringphp/src/Future/FutureValue.php +12 -0
  169. vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php +32 -0
  170. vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php +821 -0
  171. vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php +96 -0
  172. vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php +181 -0
  173. vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php +65 -0
  174. vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php +86 -0
  175. vendor/guzzlehttp/ringphp/tests/Client/Server.php +183 -0
  176. vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php +480 -0
  177. vendor/guzzlehttp/ringphp/tests/Client/server.js +241 -0
  178. vendor/guzzlehttp/ringphp/tests/CoreTest.php +336 -0
  179. vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php +21 -0
  180. vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php +46 -0
  181. vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php +56 -0
  182. vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php +109 -0
  183. vendor/guzzlehttp/ringphp/tests/bootstrap.php +11 -0
  184. vendor/guzzlehttp/streams/.travis.yml +17 -0
  185. vendor/guzzlehttp/streams/CHANGELOG.rst +94 -0
  186. vendor/guzzlehttp/streams/LICENSE +19 -0
  187. vendor/guzzlehttp/streams/Makefile +19 -0
  188. vendor/guzzlehttp/streams/README.rst +36 -0
  189. vendor/guzzlehttp/streams/composer.json +28 -0
  190. vendor/guzzlehttp/streams/phpunit.xml.dist +17 -0
  191. vendor/guzzlehttp/streams/src/AppendStream.php +220 -0
  192. vendor/guzzlehttp/streams/src/AsyncReadStream.php +207 -0
  193. vendor/guzzlehttp/streams/src/BufferStream.php +138 -0
  194. vendor/guzzlehttp/streams/src/CachingStream.php +122 -0
  195. vendor/guzzlehttp/streams/src/DroppingStream.php +42 -0
  196. vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php +4 -0
  197. vendor/guzzlehttp/streams/src/Exception/SeekException.php +27 -0
  198. vendor/guzzlehttp/streams/src/FnStream.php +147 -0
  199. vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php +117 -0
  200. vendor/guzzlehttp/streams/src/InflateStream.php +27 -0
  201. vendor/guzzlehttp/streams/src/LazyOpenStream.php +37 -0
  202. vendor/guzzlehttp/streams/src/LimitStream.php +161 -0
  203. vendor/guzzlehttp/streams/src/MetadataStreamInterface.php +11 -0
  204. vendor/guzzlehttp/streams/src/NoSeekStream.php +25 -0
  205. vendor/guzzlehttp/streams/src/NullStream.php +78 -0
  206. vendor/guzzlehttp/streams/src/PumpStream.php +161 -0
  207. vendor/guzzlehttp/streams/src/Stream.php +261 -0
  208. vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php +143 -0
  209. vendor/guzzlehttp/streams/src/StreamInterface.php +159 -0
  210. vendor/guzzlehttp/streams/src/Utils.php +196 -0
  211. vendor/guzzlehttp/streams/tests/AppendStreamTest.php +178 -0
  212. vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php +186 -0
  213. vendor/guzzlehttp/streams/tests/BufferStreamTest.php +69 -0
  214. vendor/guzzlehttp/streams/tests/CachingStreamTest.php +136 -0
  215. vendor/guzzlehttp/streams/tests/DroppingStreamTest.php +26 -0
  216. vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php +16 -0
  217. vendor/guzzlehttp/streams/tests/FnStreamTest.php +89 -0
  218. vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php +99 -0
  219. vendor/guzzlehttp/streams/tests/InflateStreamTest.php +16 -0
  220. vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php +64 -0
  221. vendor/guzzlehttp/streams/tests/LimitStreamTest.php +133 -0
  222. vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php +41 -0
  223. vendor/guzzlehttp/streams/tests/NullStreamTest.php +39 -0
  224. vendor/guzzlehttp/streams/tests/PumpStreamTest.php +77 -0
  225. vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php +147 -0
  226. vendor/guzzlehttp/streams/tests/StreamTest.php +252 -0
  227. vendor/guzzlehttp/streams/tests/UtilsTest.php +155 -0
  228. vendor/react/promise/CHANGELOG.md +162 -0
  229. vendor/react/promise/LICENSE +22 -0
  230. vendor/react/promise/README.md +876 -0
  231. vendor/react/promise/composer.json +29 -0
  232. vendor/react/promise/src/CancellablePromiseInterface.php +17 -0
  233. vendor/react/promise/src/CancellationQueue.php +55 -0
  234. vendor/react/promise/src/Deferred.php +65 -0
  235. vendor/react/promise/src/Exception/LengthException.php +7 -0
  236. vendor/react/promise/src/ExtendedPromiseInterface.php +98 -0
  237. vendor/react/promise/src/FulfilledPromise.php +71 -0
  238. vendor/react/promise/src/LazyPromise.php +66 -0
  239. vendor/react/promise/src/Promise.php +256 -0
  240. vendor/react/promise/src/PromiseInterface.php +41 -0
  241. vendor/react/promise/src/PromisorInterface.php +13 -0
  242. vendor/react/promise/src/RejectedPromise.php +79 -0
  243. vendor/react/promise/src/UnhandledRejectionException.php +31 -0
  244. vendor/react/promise/src/functions.php +351 -0
  245. vendor/react/promise/src/functions_include.php +5 -0
cloudflare.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Cloudflare
4
  Plugin URI: https://blog.cloudflare.com/new-wordpress-plugin/
5
  Description: Cloudflare speeds up and protects your WordPress site.
6
- Version: 4.6.0
7
  Requires PHP: 7.2
8
  Author: Cloudflare, Inc.
9
  License: BSD-3-Clause
3
  Plugin Name: Cloudflare
4
  Plugin URI: https://blog.cloudflare.com/new-wordpress-plugin/
5
  Description: Cloudflare speeds up and protects your WordPress site.
6
+ Version: 4.7.0
7
  Requires PHP: 7.2
8
  Author: Cloudflare, Inc.
9
  License: BSD-3-Clause
composer.json CHANGED
@@ -10,8 +10,9 @@
10
  "type": "wordpress-plugin",
11
  "require": {
12
  "cloudflare/cf-ip-rewrite": "^1.0.0",
13
- "cloudflare/cloudflare-plugin-backend": "2.6.0",
14
- "symfony/polyfill-intl-idn": "*"
 
15
  },
16
  "require-dev": {
17
  "symfony/yaml": "~2.6",
@@ -32,7 +33,7 @@
32
  "_comment": [
33
  "php-compatibility-install comes from https://github.com/wimg/PHPCompatibility/issues/102#issuecomment-255778195"
34
  ],
35
- "version": "4.6.0",
36
  "config": {
37
  "platform": {
38
  "php": "7.2"
10
  "type": "wordpress-plugin",
11
  "require": {
12
  "cloudflare/cf-ip-rewrite": "^1.0.0",
13
+ "symfony/polyfill-intl-idn": "*",
14
+ "psr/log": "^1.0",
15
+ "guzzlehttp/guzzle": "~5.0"
16
  },
17
  "require-dev": {
18
  "symfony/yaml": "~2.6",
33
  "_comment": [
34
  "php-compatibility-install comes from https://github.com/wimg/PHPCompatibility/issues/102#issuecomment-255778195"
35
  ],
36
+ "version": "4.7.0",
37
  "config": {
38
  "platform": {
39
  "php": "7.2"
composer.lock CHANGED
@@ -4,7 +4,7 @@
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
  "This file is @generated automatically"
6
  ],
7
- "content-hash": "076dac3b2cf7f0f4d508a9efce3219d9",
8
  "packages": [
9
  {
10
  "name": "cloudflare/cf-ip-rewrite",
@@ -52,42 +52,160 @@
52
  "time": "2017-10-10T15:44:33+00:00"
53
  },
54
  {
55
- "name": "cloudflare/cloudflare-plugin-backend",
56
- "version": "2.6.0",
57
  "source": {
58
  "type": "git",
59
- "url": "https://github.com/cloudflare/cloudflare-plugin-backend.git",
60
- "reference": "6af901b5969120bf42fb51e68ab822285839ef9c"
61
  },
62
  "dist": {
63
  "type": "zip",
64
- "url": "https://api.github.com/repos/cloudflare/cloudflare-plugin-backend/zipball/6af901b5969120bf42fb51e68ab822285839ef9c",
65
- "reference": "6af901b5969120bf42fb51e68ab822285839ef9c",
66
  "shasum": ""
67
  },
68
  "require": {
69
- "psr/log": "^1.0"
 
 
70
  },
71
  "require-dev": {
72
- "guzzlehttp/guzzle": "~5.0",
73
- "phpunit/phpunit": "4.8.*",
74
- "squizlabs/php_codesniffer": "2.*"
75
  },
76
  "type": "library",
77
  "autoload": {
78
  "psr-4": {
79
- "CF\\": "src/"
80
  }
81
  },
82
  "notification-url": "https://packagist.org/downloads/",
83
  "license": [
84
- "BSD-3-Clause"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  ],
86
- "description": "A PHP backend for Cloudflare plugins.",
87
- "support": {
88
- "source": "https://github.com/cloudflare/cloudflare-plugin-backend/tree/v2.6.0"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  },
90
- "time": "2021-10-10T23:15:44+00:00"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  },
92
  {
93
  "name": "psr/log",
@@ -136,6 +254,52 @@
136
  ],
137
  "time": "2021-05-03T11:20:27+00:00"
138
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  {
140
  "name": "symfony/polyfill-intl-idn",
141
  "version": "v1.23.0",
@@ -611,16 +775,16 @@
611
  },
612
  {
613
  "name": "phar-io/manifest",
614
- "version": "2.0.1",
615
  "source": {
616
  "type": "git",
617
  "url": "https://github.com/phar-io/manifest.git",
618
- "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133"
619
  },
620
  "dist": {
621
  "type": "zip",
622
- "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
623
- "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
624
  "shasum": ""
625
  },
626
  "require": {
@@ -663,7 +827,7 @@
663
  }
664
  ],
665
  "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
666
- "time": "2020-06-27T14:33:11+00:00"
667
  },
668
  {
669
  "name": "phar-io/version",
@@ -999,16 +1163,16 @@
999
  },
1000
  {
1001
  "name": "phpdocumentor/reflection-docblock",
1002
- "version": "5.2.2",
1003
  "source": {
1004
  "type": "git",
1005
  "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
1006
- "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
1007
  },
1008
  "dist": {
1009
  "type": "zip",
1010
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
1011
- "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
1012
  "shasum": ""
1013
  },
1014
  "require": {
@@ -1019,7 +1183,8 @@
1019
  "webmozart/assert": "^1.9.1"
1020
  },
1021
  "require-dev": {
1022
- "mockery/mockery": "~1.3.2"
 
1023
  },
1024
  "type": "library",
1025
  "extra": {
@@ -1047,20 +1212,20 @@
1047
  }
1048
  ],
1049
  "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
1050
- "time": "2020-09-03T19:13:55+00:00"
1051
  },
1052
  {
1053
  "name": "phpdocumentor/type-resolver",
1054
- "version": "1.4.0",
1055
  "source": {
1056
  "type": "git",
1057
  "url": "https://github.com/phpDocumentor/TypeResolver.git",
1058
- "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
1059
  },
1060
  "dist": {
1061
  "type": "zip",
1062
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
1063
- "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
1064
  "shasum": ""
1065
  },
1066
  "require": {
@@ -1068,7 +1233,8 @@
1068
  "phpdocumentor/reflection-common": "^2.0"
1069
  },
1070
  "require-dev": {
1071
- "ext-tokenizer": "*"
 
1072
  },
1073
  "type": "library",
1074
  "extra": {
@@ -1092,37 +1258,37 @@
1092
  }
1093
  ],
1094
  "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
1095
- "time": "2020-09-17T18:55:26+00:00"
1096
  },
1097
  {
1098
  "name": "phpspec/prophecy",
1099
- "version": "1.13.0",
1100
  "source": {
1101
  "type": "git",
1102
  "url": "https://github.com/phpspec/prophecy.git",
1103
- "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea"
1104
  },
1105
  "dist": {
1106
  "type": "zip",
1107
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea",
1108
- "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea",
1109
  "shasum": ""
1110
  },
1111
  "require": {
1112
  "doctrine/instantiator": "^1.2",
1113
- "php": "^7.2 || ~8.0, <8.1",
1114
  "phpdocumentor/reflection-docblock": "^5.2",
1115
  "sebastian/comparator": "^3.0 || ^4.0",
1116
  "sebastian/recursion-context": "^3.0 || ^4.0"
1117
  },
1118
  "require-dev": {
1119
- "phpspec/phpspec": "^6.0",
1120
  "phpunit/phpunit": "^8.0 || ^9.0"
1121
  },
1122
  "type": "library",
1123
  "extra": {
1124
  "branch-alias": {
1125
- "dev-master": "1.11.x-dev"
1126
  }
1127
  },
1128
  "autoload": {
@@ -1155,20 +1321,20 @@
1155
  "spy",
1156
  "stub"
1157
  ],
1158
- "time": "2021-03-17T13:42:18+00:00"
1159
  },
1160
  {
1161
  "name": "phpunit/php-code-coverage",
1162
- "version": "7.0.14",
1163
  "source": {
1164
  "type": "git",
1165
  "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
1166
- "reference": "bb7c9a210c72e4709cdde67f8b7362f672f2225c"
1167
  },
1168
  "dist": {
1169
  "type": "zip",
1170
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/bb7c9a210c72e4709cdde67f8b7362f672f2225c",
1171
- "reference": "bb7c9a210c72e4709cdde67f8b7362f672f2225c",
1172
  "shasum": ""
1173
  },
1174
  "require": {
@@ -1177,7 +1343,7 @@
1177
  "php": ">=7.2",
1178
  "phpunit/php-file-iterator": "^2.0.2",
1179
  "phpunit/php-text-template": "^1.2.1",
1180
- "phpunit/php-token-stream": "^3.1.1 || ^4.0",
1181
  "sebastian/code-unit-reverse-lookup": "^1.0.1",
1182
  "sebastian/environment": "^4.2.2",
1183
  "sebastian/version": "^2.0.1",
@@ -1224,20 +1390,20 @@
1224
  "type": "github"
1225
  }
1226
  ],
1227
- "time": "2020-12-02T13:39:03+00:00"
1228
  },
1229
  {
1230
  "name": "phpunit/php-file-iterator",
1231
- "version": "2.0.3",
1232
  "source": {
1233
  "type": "git",
1234
  "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
1235
- "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357"
1236
  },
1237
  "dist": {
1238
  "type": "zip",
1239
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/4b49fb70f067272b659ef0174ff9ca40fdaa6357",
1240
- "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357",
1241
  "shasum": ""
1242
  },
1243
  "require": {
@@ -1280,7 +1446,7 @@
1280
  "type": "github"
1281
  }
1282
  ],
1283
- "time": "2020-11-30T08:25:21+00:00"
1284
  },
1285
  {
1286
  "name": "phpunit/php-text-template",
@@ -1380,16 +1546,16 @@
1380
  },
1381
  {
1382
  "name": "phpunit/php-token-stream",
1383
- "version": "3.1.2",
1384
  "source": {
1385
  "type": "git",
1386
  "url": "https://github.com/sebastianbergmann/php-token-stream.git",
1387
- "reference": "472b687829041c24b25f475e14c2f38a09edf1c2"
1388
  },
1389
  "dist": {
1390
  "type": "zip",
1391
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/472b687829041c24b25f475e14c2f38a09edf1c2",
1392
- "reference": "472b687829041c24b25f475e14c2f38a09edf1c2",
1393
  "shasum": ""
1394
  },
1395
  "require": {
@@ -1432,20 +1598,20 @@
1432
  }
1433
  ],
1434
  "abandoned": true,
1435
- "time": "2020-11-30T08:38:46+00:00"
1436
  },
1437
  {
1438
  "name": "phpunit/phpunit",
1439
- "version": "8.5.15",
1440
  "source": {
1441
  "type": "git",
1442
  "url": "https://github.com/sebastianbergmann/phpunit.git",
1443
- "reference": "038d4196d8e8cb405cd5e82cedfe413ad6eef9ef"
1444
  },
1445
  "dist": {
1446
  "type": "zip",
1447
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/038d4196d8e8cb405cd5e82cedfe413ad6eef9ef",
1448
- "reference": "038d4196d8e8cb405cd5e82cedfe413ad6eef9ef",
1449
  "shasum": ""
1450
  },
1451
  "require": {
@@ -1457,12 +1623,12 @@
1457
  "ext-xml": "*",
1458
  "ext-xmlwriter": "*",
1459
  "myclabs/deep-copy": "^1.10.0",
1460
- "phar-io/manifest": "^2.0.1",
1461
  "phar-io/version": "^3.0.2",
1462
  "php": ">=7.2",
1463
  "phpspec/prophecy": "^1.10.3",
1464
  "phpunit/php-code-coverage": "^7.0.12",
1465
- "phpunit/php-file-iterator": "^2.0.2",
1466
  "phpunit/php-text-template": "^1.2.1",
1467
  "phpunit/php-timer": "^2.1.2",
1468
  "sebastian/comparator": "^3.0.2",
@@ -1525,7 +1691,7 @@
1525
  "type": "github"
1526
  }
1527
  ],
1528
- "time": "2021-03-17T07:27:54+00:00"
1529
  },
1530
  {
1531
  "name": "sebastian/code-unit-reverse-lookup",
@@ -2210,16 +2376,16 @@
2210
  },
2211
  {
2212
  "name": "squizlabs/php_codesniffer",
2213
- "version": "3.6.0",
2214
  "source": {
2215
  "type": "git",
2216
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
2217
- "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625"
2218
  },
2219
  "dist": {
2220
  "type": "zip",
2221
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
2222
- "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
2223
  "shasum": ""
2224
  },
2225
  "require": {
@@ -2257,7 +2423,7 @@
2257
  "phpcs",
2258
  "standards"
2259
  ],
2260
- "time": "2021-04-09T00:54:41+00:00"
2261
  },
2262
  {
2263
  "name": "symfony/polyfill-ctype",
@@ -2387,16 +2553,16 @@
2387
  },
2388
  {
2389
  "name": "theseer/tokenizer",
2390
- "version": "1.2.0",
2391
  "source": {
2392
  "type": "git",
2393
  "url": "https://github.com/theseer/tokenizer.git",
2394
- "reference": "75a63c33a8577608444246075ea0af0d052e452a"
2395
  },
2396
  "dist": {
2397
  "type": "zip",
2398
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a",
2399
- "reference": "75a63c33a8577608444246075ea0af0d052e452a",
2400
  "shasum": ""
2401
  },
2402
  "require": {
@@ -2429,7 +2595,7 @@
2429
  "type": "github"
2430
  }
2431
  ],
2432
- "time": "2020-07-12T23:59:07+00:00"
2433
  },
2434
  {
2435
  "name": "webmozart/assert",
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
  "This file is @generated automatically"
6
  ],
7
+ "content-hash": "bda85e02cc5ade00c792494d86651a6d",
8
  "packages": [
9
  {
10
  "name": "cloudflare/cf-ip-rewrite",
52
  "time": "2017-10-10T15:44:33+00:00"
53
  },
54
  {
55
+ "name": "guzzlehttp/guzzle",
56
+ "version": "5.3.4",
57
  "source": {
58
  "type": "git",
59
+ "url": "https://github.com/guzzle/guzzle.git",
60
+ "reference": "b87eda7a7162f95574032da17e9323c9899cb6b2"
61
  },
62
  "dist": {
63
  "type": "zip",
64
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b87eda7a7162f95574032da17e9323c9899cb6b2",
65
+ "reference": "b87eda7a7162f95574032da17e9323c9899cb6b2",
66
  "shasum": ""
67
  },
68
  "require": {
69
+ "guzzlehttp/ringphp": "^1.1",
70
+ "php": ">=5.4.0",
71
+ "react/promise": "^2.2"
72
  },
73
  "require-dev": {
74
+ "ext-curl": "*",
75
+ "phpunit/phpunit": "^4.0"
 
76
  },
77
  "type": "library",
78
  "autoload": {
79
  "psr-4": {
80
+ "GuzzleHttp\\": "src/"
81
  }
82
  },
83
  "notification-url": "https://packagist.org/downloads/",
84
  "license": [
85
+ "MIT"
86
+ ],
87
+ "authors": [
88
+ {
89
+ "name": "Michael Dowling",
90
+ "email": "mtdowling@gmail.com",
91
+ "homepage": "https://github.com/mtdowling"
92
+ }
93
+ ],
94
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
95
+ "homepage": "http://guzzlephp.org/",
96
+ "keywords": [
97
+ "client",
98
+ "curl",
99
+ "framework",
100
+ "http",
101
+ "http client",
102
+ "rest",
103
+ "web service"
104
+ ],
105
+ "time": "2019-10-30T09:32:00+00:00"
106
+ },
107
+ {
108
+ "name": "guzzlehttp/ringphp",
109
+ "version": "1.1.1",
110
+ "source": {
111
+ "type": "git",
112
+ "url": "https://github.com/guzzle/RingPHP.git",
113
+ "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b"
114
+ },
115
+ "dist": {
116
+ "type": "zip",
117
+ "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/5e2a174052995663dd68e6b5ad838afd47dd615b",
118
+ "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b",
119
+ "shasum": ""
120
+ },
121
+ "require": {
122
+ "guzzlehttp/streams": "~3.0",
123
+ "php": ">=5.4.0",
124
+ "react/promise": "~2.0"
125
+ },
126
+ "require-dev": {
127
+ "ext-curl": "*",
128
+ "phpunit/phpunit": "~4.0"
129
+ },
130
+ "suggest": {
131
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
132
+ },
133
+ "type": "library",
134
+ "extra": {
135
+ "branch-alias": {
136
+ "dev-master": "1.1-dev"
137
+ }
138
+ },
139
+ "autoload": {
140
+ "psr-4": {
141
+ "GuzzleHttp\\Ring\\": "src/"
142
+ }
143
+ },
144
+ "notification-url": "https://packagist.org/downloads/",
145
+ "license": [
146
+ "MIT"
147
  ],
148
+ "authors": [
149
+ {
150
+ "name": "Michael Dowling",
151
+ "email": "mtdowling@gmail.com",
152
+ "homepage": "https://github.com/mtdowling"
153
+ }
154
+ ],
155
+ "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
156
+ "abandoned": true,
157
+ "time": "2018-07-31T13:22:33+00:00"
158
+ },
159
+ {
160
+ "name": "guzzlehttp/streams",
161
+ "version": "3.0.0",
162
+ "source": {
163
+ "type": "git",
164
+ "url": "https://github.com/guzzle/streams.git",
165
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
166
+ },
167
+ "dist": {
168
+ "type": "zip",
169
+ "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
170
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
171
+ "shasum": ""
172
+ },
173
+ "require": {
174
+ "php": ">=5.4.0"
175
+ },
176
+ "require-dev": {
177
+ "phpunit/phpunit": "~4.0"
178
+ },
179
+ "type": "library",
180
+ "extra": {
181
+ "branch-alias": {
182
+ "dev-master": "3.0-dev"
183
+ }
184
+ },
185
+ "autoload": {
186
+ "psr-4": {
187
+ "GuzzleHttp\\Stream\\": "src/"
188
+ }
189
  },
190
+ "notification-url": "https://packagist.org/downloads/",
191
+ "license": [
192
+ "MIT"
193
+ ],
194
+ "authors": [
195
+ {
196
+ "name": "Michael Dowling",
197
+ "email": "mtdowling@gmail.com",
198
+ "homepage": "https://github.com/mtdowling"
199
+ }
200
+ ],
201
+ "description": "Provides a simple abstraction over streams of data",
202
+ "homepage": "http://guzzlephp.org/",
203
+ "keywords": [
204
+ "Guzzle",
205
+ "stream"
206
+ ],
207
+ "abandoned": true,
208
+ "time": "2014-10-12T19:18:40+00:00"
209
  },
210
  {
211
  "name": "psr/log",
254
  ],
255
  "time": "2021-05-03T11:20:27+00:00"
256
  },
257
+ {
258
+ "name": "react/promise",
259
+ "version": "v2.8.0",
260
+ "source": {
261
+ "type": "git",
262
+ "url": "https://github.com/reactphp/promise.git",
263
+ "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4"
264
+ },
265
+ "dist": {
266
+ "type": "zip",
267
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4",
268
+ "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4",
269
+ "shasum": ""
270
+ },
271
+ "require": {
272
+ "php": ">=5.4.0"
273
+ },
274
+ "require-dev": {
275
+ "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36"
276
+ },
277
+ "type": "library",
278
+ "autoload": {
279
+ "psr-4": {
280
+ "React\\Promise\\": "src/"
281
+ },
282
+ "files": [
283
+ "src/functions_include.php"
284
+ ]
285
+ },
286
+ "notification-url": "https://packagist.org/downloads/",
287
+ "license": [
288
+ "MIT"
289
+ ],
290
+ "authors": [
291
+ {
292
+ "name": "Jan Sorgalla",
293
+ "email": "jsorgalla@gmail.com"
294
+ }
295
+ ],
296
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
297
+ "keywords": [
298
+ "promise",
299
+ "promises"
300
+ ],
301
+ "time": "2020-05-12T15:16:56+00:00"
302
+ },
303
  {
304
  "name": "symfony/polyfill-intl-idn",
305
  "version": "v1.23.0",
775
  },
776
  {
777
  "name": "phar-io/manifest",
778
+ "version": "2.0.3",
779
  "source": {
780
  "type": "git",
781
  "url": "https://github.com/phar-io/manifest.git",
782
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
783
  },
784
  "dist": {
785
  "type": "zip",
786
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
787
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
788
  "shasum": ""
789
  },
790
  "require": {
827
  }
828
  ],
829
  "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
830
+ "time": "2021-07-20T11:28:43+00:00"
831
  },
832
  {
833
  "name": "phar-io/version",
1163
  },
1164
  {
1165
  "name": "phpdocumentor/reflection-docblock",
1166
+ "version": "5.3.0",
1167
  "source": {
1168
  "type": "git",
1169
  "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
1170
+ "reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
1171
  },
1172
  "dist": {
1173
  "type": "zip",
1174
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
1175
+ "reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
1176
  "shasum": ""
1177
  },
1178
  "require": {
1183
  "webmozart/assert": "^1.9.1"
1184
  },
1185
  "require-dev": {
1186
+ "mockery/mockery": "~1.3.2",
1187
+ "psalm/phar": "^4.8"
1188
  },
1189
  "type": "library",
1190
  "extra": {
1212
  }
1213
  ],
1214
  "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
1215
+ "time": "2021-10-19T17:43:47+00:00"
1216
  },
1217
  {
1218
  "name": "phpdocumentor/type-resolver",
1219
+ "version": "1.5.1",
1220
  "source": {
1221
  "type": "git",
1222
  "url": "https://github.com/phpDocumentor/TypeResolver.git",
1223
+ "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae"
1224
  },
1225
  "dist": {
1226
  "type": "zip",
1227
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae",
1228
+ "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae",
1229
  "shasum": ""
1230
  },
1231
  "require": {
1233
  "phpdocumentor/reflection-common": "^2.0"
1234
  },
1235
  "require-dev": {
1236
+ "ext-tokenizer": "*",
1237
+ "psalm/phar": "^4.8"
1238
  },
1239
  "type": "library",
1240
  "extra": {
1258
  }
1259
  ],
1260
  "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
1261
+ "time": "2021-10-02T14:08:47+00:00"
1262
  },
1263
  {
1264
  "name": "phpspec/prophecy",
1265
+ "version": "1.14.0",
1266
  "source": {
1267
  "type": "git",
1268
  "url": "https://github.com/phpspec/prophecy.git",
1269
+ "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e"
1270
  },
1271
  "dist": {
1272
  "type": "zip",
1273
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
1274
+ "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
1275
  "shasum": ""
1276
  },
1277
  "require": {
1278
  "doctrine/instantiator": "^1.2",
1279
+ "php": "^7.2 || ~8.0, <8.2",
1280
  "phpdocumentor/reflection-docblock": "^5.2",
1281
  "sebastian/comparator": "^3.0 || ^4.0",
1282
  "sebastian/recursion-context": "^3.0 || ^4.0"
1283
  },
1284
  "require-dev": {
1285
+ "phpspec/phpspec": "^6.0 || ^7.0",
1286
  "phpunit/phpunit": "^8.0 || ^9.0"
1287
  },
1288
  "type": "library",
1289
  "extra": {
1290
  "branch-alias": {
1291
+ "dev-master": "1.x-dev"
1292
  }
1293
  },
1294
  "autoload": {
1321
  "spy",
1322
  "stub"
1323
  ],
1324
+ "time": "2021-09-10T09:02:12+00:00"
1325
  },
1326
  {
1327
  "name": "phpunit/php-code-coverage",
1328
+ "version": "7.0.15",
1329
  "source": {
1330
  "type": "git",
1331
  "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
1332
+ "reference": "819f92bba8b001d4363065928088de22f25a3a48"
1333
  },
1334
  "dist": {
1335
  "type": "zip",
1336
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/819f92bba8b001d4363065928088de22f25a3a48",
1337
+ "reference": "819f92bba8b001d4363065928088de22f25a3a48",
1338
  "shasum": ""
1339
  },
1340
  "require": {
1343
  "php": ">=7.2",
1344
  "phpunit/php-file-iterator": "^2.0.2",
1345
  "phpunit/php-text-template": "^1.2.1",
1346
+ "phpunit/php-token-stream": "^3.1.3 || ^4.0",
1347
  "sebastian/code-unit-reverse-lookup": "^1.0.1",
1348
  "sebastian/environment": "^4.2.2",
1349
  "sebastian/version": "^2.0.1",
1390
  "type": "github"
1391
  }
1392
  ],
1393
+ "time": "2021-07-26T12:20:09+00:00"
1394
  },
1395
  {
1396
  "name": "phpunit/php-file-iterator",
1397
+ "version": "2.0.4",
1398
  "source": {
1399
  "type": "git",
1400
  "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
1401
+ "reference": "28af674ff175d0768a5a978e6de83f697d4a7f05"
1402
  },
1403
  "dist": {
1404
  "type": "zip",
1405
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/28af674ff175d0768a5a978e6de83f697d4a7f05",
1406
+ "reference": "28af674ff175d0768a5a978e6de83f697d4a7f05",
1407
  "shasum": ""
1408
  },
1409
  "require": {
1446
  "type": "github"
1447
  }
1448
  ],
1449
+ "time": "2021-07-19T06:46:01+00:00"
1450
  },
1451
  {
1452
  "name": "phpunit/php-text-template",
1546
  },
1547
  {
1548
  "name": "phpunit/php-token-stream",
1549
+ "version": "3.1.3",
1550
  "source": {
1551
  "type": "git",
1552
  "url": "https://github.com/sebastianbergmann/php-token-stream.git",
1553
+ "reference": "9c1da83261628cb24b6a6df371b6e312b3954768"
1554
  },
1555
  "dist": {
1556
  "type": "zip",
1557
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9c1da83261628cb24b6a6df371b6e312b3954768",
1558
+ "reference": "9c1da83261628cb24b6a6df371b6e312b3954768",
1559
  "shasum": ""
1560
  },
1561
  "require": {
1598
  }
1599
  ],
1600
  "abandoned": true,
1601
+ "time": "2021-07-26T12:15:06+00:00"
1602
  },
1603
  {
1604
  "name": "phpunit/phpunit",
1605
+ "version": "8.5.21",
1606
  "source": {
1607
  "type": "git",
1608
  "url": "https://github.com/sebastianbergmann/phpunit.git",
1609
+ "reference": "50a58a60b85947b0bee4c8ecfe0f4bbdcf20e984"
1610
  },
1611
  "dist": {
1612
  "type": "zip",
1613
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/50a58a60b85947b0bee4c8ecfe0f4bbdcf20e984",
1614
+ "reference": "50a58a60b85947b0bee4c8ecfe0f4bbdcf20e984",
1615
  "shasum": ""
1616
  },
1617
  "require": {
1623
  "ext-xml": "*",
1624
  "ext-xmlwriter": "*",
1625
  "myclabs/deep-copy": "^1.10.0",
1626
+ "phar-io/manifest": "^2.0.3",
1627
  "phar-io/version": "^3.0.2",
1628
  "php": ">=7.2",
1629
  "phpspec/prophecy": "^1.10.3",
1630
  "phpunit/php-code-coverage": "^7.0.12",
1631
+ "phpunit/php-file-iterator": "^2.0.4",
1632
  "phpunit/php-text-template": "^1.2.1",
1633
  "phpunit/php-timer": "^2.1.2",
1634
  "sebastian/comparator": "^3.0.2",
1691
  "type": "github"
1692
  }
1693
  ],
1694
+ "time": "2021-09-25T07:37:20+00:00"
1695
  },
1696
  {
1697
  "name": "sebastian/code-unit-reverse-lookup",
2376
  },
2377
  {
2378
  "name": "squizlabs/php_codesniffer",
2379
+ "version": "3.6.1",
2380
  "source": {
2381
  "type": "git",
2382
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
2383
+ "reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e"
2384
  },
2385
  "dist": {
2386
  "type": "zip",
2387
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f268ca40d54617c6e06757f83f699775c9b3ff2e",
2388
+ "reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e",
2389
  "shasum": ""
2390
  },
2391
  "require": {
2423
  "phpcs",
2424
  "standards"
2425
  ],
2426
+ "time": "2021-10-11T04:00:11+00:00"
2427
  },
2428
  {
2429
  "name": "symfony/polyfill-ctype",
2553
  },
2554
  {
2555
  "name": "theseer/tokenizer",
2556
+ "version": "1.2.1",
2557
  "source": {
2558
  "type": "git",
2559
  "url": "https://github.com/theseer/tokenizer.git",
2560
+ "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
2561
  },
2562
  "dist": {
2563
  "type": "zip",
2564
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
2565
+ "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
2566
  "shasum": ""
2567
  },
2568
  "require": {
2595
  "type": "github"
2596
  }
2597
  ],
2598
+ "time": "2021-07-28T10:34:58+00:00"
2599
  },
2600
  {
2601
  "name": "webmozart/assert",
config.json CHANGED
@@ -25,5 +25,5 @@
25
  },
26
  "locale": "en",
27
  "integrationName": "wordpress",
28
- "version": "4.6.0"
29
  }
25
  },
26
  "locale": "en",
27
  "integrationName": "wordpress",
28
+ "version": "4.7.0"
29
  }
output.log CHANGED
@@ -17,39 +17,39 @@ php-7.4-build2: Pulling from cloudflare/cloudflare-wordpress/php-actions_compose
17
  65564f077fec: Pulling fs layer
18
  4d1e94121e00: Pulling fs layer
19
  79c03e12047a: Waiting
20
- 4612e05a72cf: Waiting
21
  51393fef6543: Waiting
22
  5571c1cd7f43: Waiting
23
  65564f077fec: Waiting
24
  4d1e94121e00: Waiting
 
25
  9b2beae78beb: Waiting
26
  320f26ee9b1c: Verifying Checksum
27
  320f26ee9b1c: Download complete
 
 
 
 
 
 
 
 
28
  30e209609427: Verifying Checksum
29
  30e209609427: Download complete
30
  801bfaa63ef2: Verifying Checksum
31
  801bfaa63ef2: Download complete
32
  801bfaa63ef2: Pull complete
33
- 4612e05a72cf: Verifying Checksum
34
- 4612e05a72cf: Download complete
 
 
35
  30e209609427: Pull complete
36
  320f26ee9b1c: Pull complete
37
- 79c03e12047a: Verifying Checksum
38
- 79c03e12047a: Download complete
39
  4612e05a72cf: Pull complete
40
- 9b2beae78beb: Verifying Checksum
41
- 9b2beae78beb: Download complete
42
  9b2beae78beb: Pull complete
43
  79c03e12047a: Pull complete
 
44
  5571c1cd7f43: Verifying Checksum
45
  5571c1cd7f43: Download complete
46
- 51393fef6543: Verifying Checksum
47
- 51393fef6543: Download complete
48
- 65564f077fec: Verifying Checksum
49
- 65564f077fec: Download complete
50
- 4d1e94121e00: Verifying Checksum
51
- 4d1e94121e00: Download complete
52
- 51393fef6543: Pull complete
53
  5571c1cd7f43: Pull complete
54
  65564f077fec: Pull complete
55
  4d1e94121e00: Pull complete
17
  65564f077fec: Pulling fs layer
18
  4d1e94121e00: Pulling fs layer
19
  79c03e12047a: Waiting
 
20
  51393fef6543: Waiting
21
  5571c1cd7f43: Waiting
22
  65564f077fec: Waiting
23
  4d1e94121e00: Waiting
24
+ 4612e05a72cf: Waiting
25
  9b2beae78beb: Waiting
26
  320f26ee9b1c: Verifying Checksum
27
  320f26ee9b1c: Download complete
28
+ 4612e05a72cf: Verifying Checksum
29
+ 4612e05a72cf: Download complete
30
+ 9b2beae78beb: Verifying Checksum
31
+ 9b2beae78beb: Download complete
32
+ 79c03e12047a: Verifying Checksum
33
+ 79c03e12047a: Download complete
34
+ 51393fef6543: Verifying Checksum
35
+ 51393fef6543: Download complete
36
  30e209609427: Verifying Checksum
37
  30e209609427: Download complete
38
  801bfaa63ef2: Verifying Checksum
39
  801bfaa63ef2: Download complete
40
  801bfaa63ef2: Pull complete
41
+ 65564f077fec: Verifying Checksum
42
+ 65564f077fec: Download complete
43
+ 4d1e94121e00: Verifying Checksum
44
+ 4d1e94121e00: Download complete
45
  30e209609427: Pull complete
46
  320f26ee9b1c: Pull complete
 
 
47
  4612e05a72cf: Pull complete
 
 
48
  9b2beae78beb: Pull complete
49
  79c03e12047a: Pull complete
50
+ 51393fef6543: Pull complete
51
  5571c1cd7f43: Verifying Checksum
52
  5571c1cd7f43: Download complete
 
 
 
 
 
 
 
53
  5571c1cd7f43: Pull complete
54
  65564f077fec: Pull complete
55
  4d1e94121e00: Pull complete
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: icyapril, manatarms, thillcf, deuill, epatryk, jacobbednarz
3
  Tags: cloudflare, seo, ssl, ddos, speed, security, cdn, performance, free
4
  Requires at least: 3.4
5
  Tested up to: 5.7
6
- Stable tag: 4.6.0
7
  Requires PHP: 7.2
8
  License: BSD-3-Clause
9
 
@@ -17,9 +17,9 @@ https://www.youtube.com/watch?v=DWANhxoDxFI?feature=youtu.be
17
 
18
  **Automatic Platform Optimization (APO)**
19
 
20
- Speed up your WordPress site by up to 300% with Cloudflare’s Automatic Platform Optimization (APO) plugin. APO allows Cloudflare to serve your entire WordPress site from our edge network of over 250+ data centers worldwide ensuring fast & reliable performance for your visitors no matter where they are.
21
 
22
- Optimizing your WordPress site with multiple plugins can be overwhelming. Take your WordPress site’s performance to the next level by switching to a single plugin for CDN, intelligent caching, and other key WordPress optimizations with Cloudflare (APO). Visit our [announcement blog](https://blog.cloudflare.com/automatic-platform-optimizations-starting-with-wordpress/) to learn more about APO.
23
 
24
  **What makes APO different from other caching plugins?**
25
 
@@ -29,7 +29,7 @@ APO intelligently caches your HTML pages and will automatically purge content fr
29
 
30
  **What you get with Cloudflare APO**
31
 
32
- APO is a $5 add-on with Cloudflare’s free plan and comes with an unlimited amount of subdomains. With APO you also get to leverage many of the other benefits of Cloudflare such as **Free DNS, Free Automated SSL Certificates, Free DDoS Mitigation, and more.** APO is free for all paid plan users so if you have Cloudflare Pro or Business already you can just turn it on. You can compare all our plans [here](https://www.cloudflare.com/plans/?utm_source=promo&utm_medium=social&utm_term=&utm_content=&utm_campaign=g421o-pl-apo-wordpress-plans).
33
 
34
  **Protect your WordPress site with Cloudflare’s Web Application Firewall (WAF)**
35
 
@@ -99,6 +99,10 @@ Yes, Cloudflare works with, and helps speed up your site even more, if you have
99
 
100
  == Changelog ==
101
 
 
 
 
 
102
  = 4.6.0 - 2021-10-11 =
103
 
104
  * Make frontend use native await/async
3
  Tags: cloudflare, seo, ssl, ddos, speed, security, cdn, performance, free
4
  Requires at least: 3.4
5
  Tested up to: 5.7
6
+ Stable tag: 4.7.0
7
  Requires PHP: 7.2
8
  License: BSD-3-Clause
9
 
17
 
18
  **Automatic Platform Optimization (APO)**
19
 
20
+ Speed up your WordPress site by up to 300% with Cloudflare’s Automatic Platform Optimization (APO) plugin. APO allows Cloudflare to serve your entire WordPress site from our edge network of over 250+ data centers worldwide ensuring fast & reliable performance for your visitors no matter where they are.
21
 
22
+ Optimizing your WordPress site with multiple plugins can be overwhelming. Take your WordPress site’s performance to the next level by switching to a single plugin for CDN, intelligent caching, and other key WordPress optimizations with Cloudflare (APO). Visit our [announcement blog](https://blog.cloudflare.com/automatic-platform-optimizations-starting-with-wordpress/) to learn more about APO.
23
 
24
  **What makes APO different from other caching plugins?**
25
 
29
 
30
  **What you get with Cloudflare APO**
31
 
32
+ APO is a $5 add-on with Cloudflare’s free plan and comes with an unlimited amount of subdomains. With APO you also get to leverage many of the other benefits of Cloudflare such as **Free DNS, Free Automated SSL Certificates, Free DDoS Mitigation, and more.** APO is free for all paid plan users so if you have Cloudflare Pro or Business already you can just turn it on. You can compare all our plans [here](https://www.cloudflare.com/plans/?utm_source=promo&utm_medium=social&utm_term=&utm_content=&utm_campaign=g421o-pl-apo-wordpress-plans).
33
 
34
  **Protect your WordPress site with Cloudflare’s Web Application Firewall (WAF)**
35
 
99
 
100
  == Changelog ==
101
 
102
+ = 4.7.0 - 2021-10-28 =
103
+
104
+ * Merge cloudflare-plugin-backend into Cloudflare-WordPress repository
105
+
106
  = 4.6.0 - 2021-10-11 =
107
 
108
  * Make frontend use native await/async
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/APIInterface.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/AbstractAPIClient.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/AbstractPluginActions.php RENAMED
@@ -148,7 +148,7 @@ abstract class AbstractPluginActions
148
  $settingId = $path_array[3];
149
 
150
  $body = $this->request->getBody();
151
- $value = $body['value'];
152
  $options = $this->dataStore->set($settingId, $this->api->createPluginSettingObject($settingId, $value, true, true));
153
 
154
  if (!isset($options)) {
148
  $settingId = $path_array[3];
149
 
150
  $body = $this->request->getBody();
151
+ $value = $body['value'] ?? "";
152
  $options = $this->dataStore->set($settingId, $this->api->createPluginSettingObject($settingId, $value, true, true));
153
 
154
  if (!isset($options)) {
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Client.php RENAMED
@@ -4,6 +4,7 @@ namespace CF\API;
4
 
5
  use Guzzle\Http\Exception\BadResponseException;
6
  use CF\Integration\IntegrationInterface;
 
7
 
8
  class Client extends AbstractAPIClient
9
  {
@@ -13,6 +14,7 @@ class Client extends AbstractAPIClient
13
  const X_AUTH_EMAIL = 'X-Auth-Email';
14
  const AUTHORIZATION = 'Authorization';
15
  const AUTH_KEY_LEN = 37;
 
16
 
17
  /**
18
  * @param Request $request
@@ -26,6 +28,11 @@ class Client extends AbstractAPIClient
26
  self::CONTENT_TYPE_KEY => self::APPLICATION_JSON_KEY,
27
  );
28
 
 
 
 
 
 
29
  // Determine authentication method from key format. Global API keys are
30
  // always returned in hexadecimal format, while API Tokens are encoded
31
  // using a wider range of characters.
4
 
5
  use Guzzle\Http\Exception\BadResponseException;
6
  use CF\Integration\IntegrationInterface;
7
+ use CF\WordPress\Utils;
8
 
9
  class Client extends AbstractAPIClient
10
  {
14
  const X_AUTH_EMAIL = 'X-Auth-Email';
15
  const AUTHORIZATION = 'Authorization';
16
  const AUTH_KEY_LEN = 37;
17
+ const USER_AGENT = 'User-Agent';
18
 
19
  /**
20
  * @param Request $request
28
  self::CONTENT_TYPE_KEY => self::APPLICATION_JSON_KEY,
29
  );
30
 
31
+ $composer = Utils::getComposerJson();
32
+ $version = $composer['version'] ?? 'unknown';
33
+ $wp_version = $GLOBALS['wp_version'] ?? 'unknown';
34
+ $headers[self::USER_AGENT] = 'wordpress/' . $wp_version . '; cloudflare-wordpress-plugin/' . $version;
35
+
36
  // Determine authentication method from key format. Global API keys are
37
  // always returned in hexadecimal format, while API Tokens are encoded
38
  // using a wider range of characters.
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/DefaultHttpClient.php RENAMED
@@ -45,7 +45,10 @@ class DefaultHttpClient implements HttpClientInterface
45
  */
46
  public function createGuzzleRequest(Request $request)
47
  {
48
- $bodyType = (($request->getHeaders()[self::CONTENT_TYPE_KEY] === self::APPLICATION_JSON_KEY) ? 'json' : 'body');
 
 
 
49
 
50
  $requestOptions = array(
51
  'headers' => $request->getHeaders(),
45
  */
46
  public function createGuzzleRequest(Request $request)
47
  {
48
+ $bodyType = 'body';
49
+ if (isset($request->getHeaders()[self::CONTENT_TYPE_KEY]) && $request->getHeaders()[self::CONTENT_TYPE_KEY] === self::APPLICATION_JSON_KEY) {
50
+ $bodyType = 'json';
51
+ }
52
 
53
  $requestOptions = array(
54
  'headers' => $request->getHeaders(),
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Exception/CloudFlareException.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Exception/ZoneSettingFailException.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Host.php RENAMED
@@ -30,7 +30,7 @@ class Host extends AbstractAPIClient
30
 
31
  $body = $request->getBody();
32
  $user_key_actions = array('zone_set', 'full_zone_set');
33
- if (in_array(strtolower($body['act']), $user_key_actions)) {
34
  $body['user_key'] = $this->data_store->getHostAPIUserKey();
35
  }
36
  $body['host_key'] = $this->integrationAPI->getHostAPIKey();
30
 
31
  $body = $request->getBody();
32
  $user_key_actions = array('zone_set', 'full_zone_set');
33
+ if (in_array(strtolower($body['act'] ?? ""), $user_key_actions)) {
34
  $body['user_key'] = $this->data_store->getHostAPIUserKey();
35
  }
36
  $body['host_key'] = $this->integrationAPI->getHostAPIKey();
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/HttpClientInterface.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Plugin.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/PluginRoutes.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/API/Request.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/DNSRecord.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/ConfigInterface.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DataStoreInterface.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DefaultConfig.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DefaultIntegration.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/DefaultLogger.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/IntegrationAPIInterface.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Integration/IntegrationInterface.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Router/DefaultRestAPIRouter.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Router/RequestRouter.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Router/RouterInterface.php RENAMED
File without changes
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/SecurityUtil.php RENAMED
@@ -11,9 +11,6 @@ class SecurityUtil
11
  {
12
  if (function_exists('random_bytes')) {
13
  $randBytes = random_bytes(16);
14
- } elseif (function_exists('mcrypt_create_iv')) {
15
- srand();
16
- $randBytes = mcrypt_create_iv(16);
17
  } elseif (function_exists('openssl_random_pseudo_bytes')) {
18
  $wasItSecure = false;
19
  $randBytes = openssl_random_pseudo_bytes(16, $wasItSecure);
11
  {
12
  if (function_exists('random_bytes')) {
13
  $randBytes = random_bytes(16);
 
 
 
14
  } elseif (function_exists('openssl_random_pseudo_bytes')) {
15
  $wasItSecure = false;
16
  $randBytes = openssl_random_pseudo_bytes(16, $wasItSecure);
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/AbstractAPIClientTest.php RENAMED
@@ -14,7 +14,7 @@ use \CF\API\Request;
14
  use \CF\API\AbstractAPIClient;
15
  use \CF\Integration\DefaultConfig;
16
 
17
- class AbstractAPIClientTest extends \PHPUnit_Framework_TestCase
18
  {
19
  protected $mockAbstractAPIClient;
20
  protected $mockAPI;
@@ -26,13 +26,13 @@ class AbstractAPIClientTest extends \PHPUnit_Framework_TestCase
26
 
27
  const TOTAL_PAGES = 3;
28
  const MOCK_RESPONSE = [
29
- 'result' => [],
30
- 'result_info' => [
31
- 'total_pages' => self::TOTAL_PAGES
32
- ]
33
  ];
34
 
35
- public function setup()
36
  {
37
  $this->mockRequest = $this->getMockBuilder(Request::class)
38
  ->disableOriginalConstructor()
@@ -65,7 +65,7 @@ class AbstractAPIClientTest extends \PHPUnit_Framework_TestCase
65
  {
66
  $this->mockRequest->method('getMethod')->willReturn('GET');
67
  $this->mockClient->expects($this->exactly((self::TOTAL_PAGES - 1)))->method('send')->willReturn([
68
- 'result' => []
69
  ]);
70
  $this->mockAbstractAPIClient->getPaginatedResults($this->mockRequest, self::MOCK_RESPONSE);
71
  }
@@ -94,7 +94,7 @@ class AbstractAPIClientTest extends \PHPUnit_Framework_TestCase
94
  {
95
  $endpoint = 'http://api.cloudflare.com/client/v4';
96
  $path = '/zones';
97
- $this->mockRequest->method('getUrl')->willReturn($endpoint.$path);
98
  $this->mockAbstractAPIClient->method('getEndpoint')->willReturn($endpoint);
99
  $this->assertEquals($path, $this->mockAbstractAPIClient->getPath($this->mockRequest));
100
  }
@@ -102,7 +102,7 @@ class AbstractAPIClientTest extends \PHPUnit_Framework_TestCase
102
  public function testShouldRouteRequestReturnsTrueForValidRequest()
103
  {
104
  $endpoint = 'http://api.cloudflare.com/client/v4';
105
- $url = $endpoint.'/zones';
106
  $this->mockRequest->method('getUrl')->willReturn($url);
107
  $this->mockAbstractAPIClient->method('getEndpoint')->willReturn($endpoint);
108
  $this->assertTrue($this->mockAbstractAPIClient->shouldRouteRequest($this->mockRequest));
14
  use \CF\API\AbstractAPIClient;
15
  use \CF\Integration\DefaultConfig;
16
 
17
+ class AbstractAPIClientTest extends \PHPUnit\Framework\TestCase
18
  {
19
  protected $mockAbstractAPIClient;
20
  protected $mockAPI;
26
 
27
  const TOTAL_PAGES = 3;
28
  const MOCK_RESPONSE = [
29
+ 'result' => [],
30
+ 'result_info' => [
31
+ 'total_pages' => self::TOTAL_PAGES
32
+ ]
33
  ];
34
 
35
+ public function setup(): void
36
  {
37
  $this->mockRequest = $this->getMockBuilder(Request::class)
38
  ->disableOriginalConstructor()
65
  {
66
  $this->mockRequest->method('getMethod')->willReturn('GET');
67
  $this->mockClient->expects($this->exactly((self::TOTAL_PAGES - 1)))->method('send')->willReturn([
68
+ 'result' => []
69
  ]);
70
  $this->mockAbstractAPIClient->getPaginatedResults($this->mockRequest, self::MOCK_RESPONSE);
71
  }
94
  {
95
  $endpoint = 'http://api.cloudflare.com/client/v4';
96
  $path = '/zones';
97
+ $this->mockRequest->method('getUrl')->willReturn($endpoint . $path);
98
  $this->mockAbstractAPIClient->method('getEndpoint')->willReturn($endpoint);
99
  $this->assertEquals($path, $this->mockAbstractAPIClient->getPath($this->mockRequest));
100
  }
102
  public function testShouldRouteRequestReturnsTrueForValidRequest()
103
  {
104
  $endpoint = 'http://api.cloudflare.com/client/v4';
105
+ $url = $endpoint . '/zones';
106
  $this->mockRequest->method('getUrl')->willReturn($url);
107
  $this->mockAbstractAPIClient->method('getEndpoint')->willReturn($endpoint);
108
  $this->assertTrue($this->mockAbstractAPIClient->shouldRouteRequest($this->mockRequest));
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/AbstractPluginActionsTest.php RENAMED
@@ -4,7 +4,7 @@ namespace CF\API\Test;
4
 
5
  use CF\API\Plugin;
6
 
7
- class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
8
  {
9
  protected $mockAbstractPluginActions;
10
  protected $mockAPIClient;
@@ -14,7 +14,7 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
14
  protected $mockRequest;
15
  protected $pluginActions;
16
 
17
- public function setup()
18
  {
19
  $this->mockAPIClient = $this->getMockBuilder('\CF\API\Plugin')
20
  ->disableOriginalConstructor()
@@ -50,7 +50,6 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
50
  'email' => 'email',
51
  ));
52
  $this->mockAPIClient->method('createAPIError')->willReturn(array('success' => false));
53
- $this->mockDefaultIntegration->method('getOriginalDomain')->willReturn('name.com');
54
 
55
  $response = $this->mockAbstractPluginActions->login();
56
 
@@ -63,7 +62,6 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
63
  'apiKey' => 'apiKey',
64
  ));
65
  $this->mockAPIClient->method('createAPIError')->willReturn(array('success' => false));
66
- $this->mockDefaultIntegration->method('getOriginalDomain')->willReturn('name.com');
67
 
68
  $response = $this->mockAbstractPluginActions->login();
69
 
@@ -96,7 +94,7 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
96
  * count(Plugin::getPluginSettingsKeys())
97
  */
98
  $this->mockDataStore->method('get')->willReturn(array());
99
- $this->mockDataStore->expects($this->exactly(6))->method('get');
100
  $this->mockAPIClient->expects($this->once())->method('createAPISuccessResponse');
101
  $this->mockAbstractPluginActions->getPluginSettings();
102
  }
@@ -105,7 +103,7 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
105
  {
106
  $value = 'value';
107
  $settingId = 'settingId';
108
- $this->mockRequest->method('getUrl')->willReturn('plugin/:zonedId/settings/'.$settingId);
109
  $this->mockRequest->method('getBody')->willReturn(array($value => $value));
110
  $this->mockDataStore->method('set')->willReturn(true);
111
  $this->mockDataStore->expects($this->once())->method('set');
@@ -117,7 +115,7 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
117
  {
118
  $value = 'value';
119
  $settingId = 'settingId';
120
- $this->mockRequest->method('getUrl')->willReturn('plugin/:zonedId/settings/'.$settingId);
121
  $this->mockRequest->method('getBody')->willReturn(array($value => $value));
122
  $this->mockDataStore->method('set')->willReturn(null);
123
  $this->mockDataStore->expects($this->once())->method('set');
@@ -135,7 +133,6 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
135
  ));
136
  $this->mockDataStore->method('createUserDataStore')->willReturn(true);
137
  $this->mockClientAPI->method('responseOk')->willReturn(false);
138
- $this->mockDefaultIntegration->method('getOriginalDomain')->willReturn('name.com');
139
 
140
  $this->mockAPIClient->expects($this->once())->method('createAPIError');
141
  $this->mockAbstractPluginActions->login();
@@ -151,7 +148,7 @@ class AbstractPluginActionsTest extends \PHPUnit_Framework_TestCase
151
  public function testPatchPluginSettingsCallsApplyDefaultSettingsIfSettingIsDefaultSettings()
152
  {
153
  $settingId = 'default_settings';
154
- $this->mockRequest->method('getUrl')->willReturn('plugin/:zonedId/settings/'.$settingId);
155
  $this->mockDataStore->method('set')->willReturn(true);
156
  $this->mockAbstractPluginActions->expects($this->once())->method('applyDefaultSettings');
157
  $this->mockAbstractPluginActions->patchPluginSettings();
4
 
5
  use CF\API\Plugin;
6
 
7
+ class AbstractPluginActionsTest extends \PHPUnit\Framework\TestCase
8
  {
9
  protected $mockAbstractPluginActions;
10
  protected $mockAPIClient;
14
  protected $mockRequest;
15
  protected $pluginActions;
16
 
17
+ public function setup(): void
18
  {
19
  $this->mockAPIClient = $this->getMockBuilder('\CF\API\Plugin')
20
  ->disableOriginalConstructor()
50
  'email' => 'email',
51
  ));
52
  $this->mockAPIClient->method('createAPIError')->willReturn(array('success' => false));
 
53
 
54
  $response = $this->mockAbstractPluginActions->login();
55
 
62
  'apiKey' => 'apiKey',
63
  ));
64
  $this->mockAPIClient->method('createAPIError')->willReturn(array('success' => false));
 
65
 
66
  $response = $this->mockAbstractPluginActions->login();
67
 
94
  * count(Plugin::getPluginSettingsKeys())
95
  */
96
  $this->mockDataStore->method('get')->willReturn(array());
97
+ $this->mockDataStore->expects($this->exactly(7))->method('get');
98
  $this->mockAPIClient->expects($this->once())->method('createAPISuccessResponse');
99
  $this->mockAbstractPluginActions->getPluginSettings();
100
  }
103
  {
104
  $value = 'value';
105
  $settingId = 'settingId';
106
+ $this->mockRequest->method('getUrl')->willReturn('plugin/:zonedId/settings/' . $settingId);
107
  $this->mockRequest->method('getBody')->willReturn(array($value => $value));
108
  $this->mockDataStore->method('set')->willReturn(true);
109
  $this->mockDataStore->expects($this->once())->method('set');
115
  {
116
  $value = 'value';
117
  $settingId = 'settingId';
118
+ $this->mockRequest->method('getUrl')->willReturn('plugin/:zonedId/settings/' . $settingId);
119
  $this->mockRequest->method('getBody')->willReturn(array($value => $value));
120
  $this->mockDataStore->method('set')->willReturn(null);
121
  $this->mockDataStore->expects($this->once())->method('set');
133
  ));
134
  $this->mockDataStore->method('createUserDataStore')->willReturn(true);
135
  $this->mockClientAPI->method('responseOk')->willReturn(false);
 
136
 
137
  $this->mockAPIClient->expects($this->once())->method('createAPIError');
138
  $this->mockAbstractPluginActions->login();
148
  public function testPatchPluginSettingsCallsApplyDefaultSettingsIfSettingIsDefaultSettings()
149
  {
150
  $settingId = 'default_settings';
151
+ $this->mockRequest->method('getUrl')->willReturn('plugin/:zonedId/settings/' . $settingId);
152
  $this->mockDataStore->method('set')->willReturn(true);
153
  $this->mockAbstractPluginActions->expects($this->once())->method('applyDefaultSettings');
154
  $this->mockAbstractPluginActions->patchPluginSettings();
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/ClientTest.php RENAMED
@@ -5,7 +5,7 @@ namespace CF\API\Test;
5
  use CF\API\Client;
6
  use CF\Integration\DefaultIntegration;
7
 
8
- class ClientTest extends \PHPUnit_Framework_TestCase
9
  {
10
  private $mockConfig;
11
  private $mockClientAPI;
@@ -14,7 +14,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase
14
  private $mockLogger;
15
  private $mockCpanelIntegration;
16
 
17
- public function setup()
18
  {
19
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
20
  ->disableOriginalConstructor()
5
  use CF\API\Client;
6
  use CF\Integration\DefaultIntegration;
7
 
8
+ class ClientTest extends \PHPUnit\Framework\TestCase
9
  {
10
  private $mockConfig;
11
  private $mockClientAPI;
14
  private $mockLogger;
15
  private $mockCpanelIntegration;
16
 
17
+ public function setup(): void
18
  {
19
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
20
  ->disableOriginalConstructor()
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/DefaultHttpClientTest.php RENAMED
@@ -8,14 +8,14 @@ use GuzzleHttp\Message\RequestInterface;
8
  use GuzzleHttp\Message\ResponseInterface;
9
  use \CF\API\Request;
10
 
11
- class DefaultHttpClientTest extends \PHPUnit_Framework_TestCase
12
  {
13
  protected $mockClient;
14
  protected $mockGuzzleRequest;
15
  protected $mockGuzzleResponse;
16
  protected $mockRequest;
17
 
18
- public function setup()
19
  {
20
  $this->mockClient = $this->getMockBuilder(GuzzleHttp\Client::class)
21
  ->disableOriginalConstructor()
@@ -40,10 +40,10 @@ class DefaultHttpClientTest extends \PHPUnit_Framework_TestCase
40
 
41
  public function testSendRequestCallsGuzzleSend()
42
  {
43
- $this->mockGuzzleResponse->method('json')->willReturn(true);
44
- $this->mockClient->expects($this->once())->method('send');
45
 
46
- $this->defaultHttpClient->send($this->mockRequest);
47
  }
48
 
49
  public function testCreateGuzzleRequestReturnsGuzzleRequest()
8
  use GuzzleHttp\Message\ResponseInterface;
9
  use \CF\API\Request;
10
 
11
+ class DefaultHttpClientTest extends \PHPUnit\Framework\TestCase
12
  {
13
  protected $mockClient;
14
  protected $mockGuzzleRequest;
15
  protected $mockGuzzleResponse;
16
  protected $mockRequest;
17
 
18
+ public function setup(): void
19
  {
20
  $this->mockClient = $this->getMockBuilder(GuzzleHttp\Client::class)
21
  ->disableOriginalConstructor()
40
 
41
  public function testSendRequestCallsGuzzleSend()
42
  {
43
+ $this->mockGuzzleResponse->method('json')->willReturn(true);
44
+ $this->mockClient->expects($this->once())->method('send');
45
 
46
+ $this->defaultHttpClient->send($this->mockRequest);
47
  }
48
 
49
  public function testCreateGuzzleRequestReturnsGuzzleRequest()
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/HostTest.php RENAMED
@@ -6,7 +6,7 @@ use CF\API\Host;
6
  use CF\API\Request;
7
  use CF\Integration\DefaultIntegration;
8
 
9
- class HostTest extends \PHPUnit_Framework_TestCase
10
  {
11
  private $hostAPI;
12
  private $mockConfig;
@@ -15,7 +15,7 @@ class HostTest extends \PHPUnit_Framework_TestCase
15
  private $mockLogger;
16
  private $mockCpanelIntegration;
17
 
18
- public function setup()
19
  {
20
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
21
  ->disableOriginalConstructor()
6
  use CF\API\Request;
7
  use CF\Integration\DefaultIntegration;
8
 
9
+ class HostTest extends \PHPUnit\Framework\TestCase
10
  {
11
  private $hostAPI;
12
  private $mockConfig;
15
  private $mockLogger;
16
  private $mockCpanelIntegration;
17
 
18
+ public function setup(): void
19
  {
20
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
21
  ->disableOriginalConstructor()
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/API/PluginTest.php RENAMED
@@ -5,7 +5,7 @@ namespace CF\Test\API;
5
  use CF\Integration\DefaultIntegration;
6
  use CF\API\Plugin;
7
 
8
- class PluginTest extends \PHPUnit_Framework_TestCase
9
  {
10
  private $mockConfig;
11
  private $mockWordPressAPI;
@@ -15,7 +15,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase
15
  private $mockRequest;
16
  private $pluginAPIClient;
17
 
18
- public function setup()
19
  {
20
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
21
  ->disableOriginalConstructor()
5
  use CF\Integration\DefaultIntegration;
6
  use CF\API\Plugin;
7
 
8
+ class PluginTest extends \PHPUnit\Framework\TestCase
9
  {
10
  private $mockConfig;
11
  private $mockWordPressAPI;
15
  private $mockRequest;
16
  private $pluginAPIClient;
17
 
18
+ public function setup(): void
19
  {
20
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
21
  ->disableOriginalConstructor()
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Integration/DefaultConfigTest.php RENAMED
@@ -4,7 +4,7 @@ namespace CF\Integration\Test;
4
 
5
  use CF\Integration\DefaultConfig;
6
 
7
- class DefaultConfigTest extends \PHPUnit_Framework_TestCase
8
  {
9
  public function testGetValueReturnsCorrectValue()
10
  {
4
 
5
  use CF\Integration\DefaultConfig;
6
 
7
+ class DefaultConfigTest extends \PHPUnit\Framework\TestCase
8
  {
9
  public function testGetValueReturnsCorrectValue()
10
  {
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Integration/DefaultLoggerTest.php RENAMED
@@ -4,7 +4,7 @@ namespace CF\Integration\Test;
4
 
5
  use CF\Integration\DefaultLogger;
6
 
7
- class DefaultLoggerTest extends \PHPUnit_Framework_TestCase
8
  {
9
  public function testDebugLogOnlyLogsIfDebugIsEnabled()
10
  {
4
 
5
  use CF\Integration\DefaultLogger;
6
 
7
+ class DefaultLoggerTest extends \PHPUnit\Framework\TestCase
8
  {
9
  public function testDebugLogOnlyLogsIfDebugIsEnabled()
10
  {
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Router/DefaultRestAPIRouterTest.php RENAMED
@@ -6,7 +6,7 @@ use CF\API\Request;
6
  use CF\Integration\DefaultIntegration;
7
  use CF\Router\DefaultRestAPIRouter;
8
 
9
- class DefaultRestAPIRouterTest extends \PHPUnit_Framework_TestCase
10
  {
11
  private $clientV4APIRouter;
12
  private $mockConfig;
@@ -17,7 +17,7 @@ class DefaultRestAPIRouterTest extends \PHPUnit_Framework_TestCase
17
  private $mockLogger;
18
  private $mockRoutes = array();
19
 
20
- public function setup()
21
  {
22
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
23
  ->disableOriginalConstructor()
6
  use CF\Integration\DefaultIntegration;
7
  use CF\Router\DefaultRestAPIRouter;
8
 
9
+ class DefaultRestAPIRouterTest extends \PHPUnit\Framework\TestCase
10
  {
11
  private $clientV4APIRouter;
12
  private $mockConfig;
17
  private $mockLogger;
18
  private $mockRoutes = array();
19
 
20
+ public function setup(): void
21
  {
22
  $this->mockConfig = $this->getMockBuilder('CF\Integration\DefaultConfig')
23
  ->disableOriginalConstructor()
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/Router/RequestRouterTest.php RENAMED
@@ -12,7 +12,7 @@ use CF\Integration\IntegrationAPIInterface;
12
  use CF\Router\RequestRouter;
13
  use CF\Router\DefaultRestAPIRouter;
14
 
15
- class RequestRouterTest extends \PHPUnit_Framework_TestCase
16
  {
17
  protected $mockConfig;
18
  protected $mockClient;
@@ -23,7 +23,7 @@ class RequestRouterTest extends \PHPUnit_Framework_TestCase
23
  protected $mockRequest;
24
  protected $requestRouter;
25
 
26
- public function setup()
27
  {
28
  $this->mockConfig = $this->getMockBuilder(DefaultConfig::class)
29
  ->disableOriginalConstructor()
12
  use CF\Router\RequestRouter;
13
  use CF\Router\DefaultRestAPIRouter;
14
 
15
+ class RequestRouterTest extends \PHPUnit\Framework\TestCase
16
  {
17
  protected $mockConfig;
18
  protected $mockClient;
23
  protected $mockRequest;
24
  protected $requestRouter;
25
 
26
+ public function setup(): void
27
  {
28
  $this->mockConfig = $this->getMockBuilder(DefaultConfig::class)
29
  ->disableOriginalConstructor()
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Test/SecurityUtilTest.php RENAMED
@@ -2,7 +2,7 @@
2
 
3
  namespace CF;
4
 
5
- class SecurityUtilTest extends \PHPUnit_Framework_TestCase
6
  {
7
  public function testCSRFTokenValidateReturnsTrueForValidToken()
8
  {
2
 
3
  namespace CF;
4
 
5
+ class SecurityUtilTest extends \PHPUnit\Framework\TestCase
6
  {
7
  public function testCSRFTokenValidateReturnsTrueForValidToken()
8
  {
src/Test/WordPress/ClientActionsTest.php CHANGED
@@ -62,7 +62,7 @@ class ClientActionsTest extends \PHPUnit\Framework\TestCase
62
  'name' => $responseDomain,
63
  ),
64
  ),
65
- );
66
 
67
  $request = new Request(null, null, null, null);
68
  $clientActions = new ClientActions($this->mockDefaultIntegration, $this->mockClientAPI, $request);
62
  'name' => $responseDomain,
63
  ),
64
  ),
65
+ );
66
 
67
  $request = new Request(null, null, null, null);
68
  $clientActions = new ClientActions($this->mockDefaultIntegration, $this->mockClientAPI, $request);
{vendor/cloudflare/cloudflare-plugin-backend/src → src}/Utils.php RENAMED
File without changes
src/WordPress/Utils.php CHANGED
@@ -4,6 +4,8 @@ namespace CF\WordPress;
4
 
5
  class Utils
6
  {
 
 
7
  /**
8
  * @param $haystack
9
  * @param $needle
@@ -41,4 +43,12 @@ class Utils
41
  // sub1.sub2.domain.com -> sub2.domain.com
42
  return preg_replace('/^[^.]*.\s*/', '', $domainName);
43
  }
 
 
 
 
 
 
 
 
44
  }
4
 
5
  class Utils
6
  {
7
+ const COMPOSER_CONFIG_PATH = '/../../composer.json';
8
+
9
  /**
10
  * @param $haystack
11
  * @param $needle
43
  // sub1.sub2.domain.com -> sub2.domain.com
44
  return preg_replace('/^[^.]*.\s*/', '', $domainName);
45
  }
46
+
47
+ public static function getComposerJson(): array
48
+ {
49
+ if (!file_exists(dirname(__FILE__) . self::COMPOSER_CONFIG_PATH)) {
50
+ return [];
51
+ }
52
+ return json_decode(file_get_contents(dirname(__FILE__) . self::COMPOSER_CONFIG_PATH), true);
53
+ }
54
  }
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitb9183805180972492bbb5c9641f787bc::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitb4c5e3a2bd2c2924c4d2474a7b9c8add::getLoader();
vendor/cloudflare/cloudflare-plugin-backend/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- language: php
2
-
3
- php:
4
- - '5.6'
5
- - '7.0'
6
-
7
- install:
8
- - composer install
9
-
10
- script:
11
- - composer lint
12
- - composer test
 
 
 
 
 
 
 
 
 
 
 
 
vendor/cloudflare/cloudflare-plugin-backend/CHANGELOG.md DELETED
@@ -1,156 +0,0 @@
1
- # Change Log
2
- All notable changes to this project will be documented in this file.
3
- This project adheres to [Semantic Versioning](http://semver.org/).
4
-
5
- ## [2.6.0](#2.6.0) - 2021-10-11
6
-
7
- ### Added
8
- - Add `SETTING_AUTOMATIC_PLATFORM_OPTIMIZATION_CACHE_BY_DEVICE_TYPE` setting [#53](https://github.com/cloudflare/cloudflare-plugin-backend/pull/53)
9
-
10
- ## [2.5.0](#2.5.0) - 2021-03-19
11
-
12
- ### Fixed
13
- - Sanitize sensitive HTTP headers when calling the `logAPICall` method. [#52](https://github.com/cloudflare/cloudflare-plugin-backend/pull/52)
14
- - Stop sending `cfCRSFToken` to remote API. [#41](https://github.com/cloudflare/cloudflare-plugin-backend/pull/41)
15
-
16
- ## [2.4.0](#2.4.0) - 2020-10-01
17
- ### Added
18
- - Added APO support [#48](https://github.com/cloudflare/cloudflare-plugin-backend/pull/48)
19
-
20
- ## [2.3.0](#2.3.0) - 2020-09-23
21
- ### Fixed
22
- - Fixed issue #255 Scope test api request to current zone. [#46](https://github.com/cloudflare/cloudflare-plugin-backend/pull/46)
23
- - Sanitize authentication headers. [#45](https://github.com/cloudflare/cloudflare-plugin-backend/pull/45)
24
- - Update version of Guzzle, fix issues with Client and tests. [#44](https://github.com/cloudflare/cloudflare-plugin-backend/pull/44)
25
- - Client.php: Use `self::` prefix for `AUTH_KEY_LEN` constant. [#43](https://github.com/cloudflare/cloudflare-plugin-backend/pull/43)
26
-
27
- ### Added
28
- - Added support for API Tokens. [#42](https://github.com/cloudflare/cloudflare-plugin-backend/pull/42)
29
-
30
- ## [2.2.0](#2.2.0) - 2017-07-10
31
- ### Added
32
- - Added a new route to get config. Returns an empty array by default. [#39](https://github.com/cloudflare/cloudflare-plugin-backend/pull/39)
33
-
34
- ## [2.1.1](#2.1.1) - 2017-04-05
35
- ### Changed
36
- - DefaultConfig has a default empty JSON config as the constructor argument now. [#38](https://github.com/cloudflare/cloudflare-plugin-backend/pull/38)
37
-
38
- ## [2.1.0](#2.1.0) - 2017-03-08
39
- ### Changed
40
- - `CF\API\AbstractAPIClient` depends on `CF\API\HttpClientInterface` and uses `CF\API\DefaultHttpClient` (Guzzle 5) [#37](https://github.com/cloudflare/cloudflare-plugin-backend/pull/37)
41
-
42
- ## [2.0.0](#2.0.0) - 2017-03-08
43
- ### Changed
44
- - Reverted `CF\API\AbstractAPIClient` to Guzzle 5 [#35](https://github.com/cloudflare/cloudflare-plugin-backend/pull/35)
45
-
46
- ### Fixed
47
- - API Clients must be instantiated outside `RequestRouter` now to fix DI issue in Magento [#36](https://github.com/cloudflare/cloudflare-plugin-backend/pull/36)
48
-
49
- ## [1.1.13](#1.1.13) - 2017-02-28
50
- ### Added
51
- - Travis CI [#34](https://github.com/cloudflare/cloudflare-plugin-backend/pull/34)
52
-
53
- ### Fixed
54
- - Fixed Guzzle type hints on getErrorMessage() [#33](https://github.com/cloudflare/cloudflare-plugin-backend/pull/33)
55
-
56
- ## [1.1.12](#1.1.12) - 2016-02-3
57
- ### Changed
58
- - Moved Guzzle to require-dev [#31](https://github.com/cloudflare/cloudflare-plugin-backend/pull/31)
59
-
60
- ## [1.1.11](#1.1.11) - 2016-09-27
61
- ### Fixed
62
- - Fixed bug where requests were not paginating. [#27](https://github.com/cloudflare/cloudflare-plugin-backend/pull/27)
63
-
64
- ## [1.1.10](#1.1.10) - 2016-09-12
65
- ### Fixed
66
- - Fixed method PUT not having a http body bug. [#26](https://github.com/cloudflare/cloudflare-plugin-backend/pull/26)
67
-
68
- ## [1.1.9](#1.1.9) - 2016-09-12
69
- ### Fixed
70
- - Fixed bugs in Guzzle3 and backend which didn't work with PHP 5.3. [#25](https://github.com/cloudflare/cloudflare-plugin-backend/pull/25)
71
-
72
- ## [1.1.8](#1.1.8) - 2016-09-12
73
- ### Changed
74
- - Downgraded guzzlehttp 5.0 to guzzle 3.9 to support PHP 5.3. [#23](https://github.com/cloudflare/cloudflare-plugin-backend/pull/23)
75
-
76
- ## [1.1.7](#1.1.7) - 2016-09-6
77
- ### Changed
78
- - Moved plugin settings consts from DataStore to Plugin API. [#18](https://github.com/cloudflare/cloudflare-plugin-backend/pull/18)
79
- - createPluginSettingObject() is no longer static. [#18](https://github.com/cloudflare/cloudflare-plugin-backend/pull/18)
80
-
81
- ### Fixed
82
- - Fixed patchPluginSettings() to return correct JSON structure. [#19](https://github.com/cloudflare/cloudflare-plugin-backend/pull/19)
83
- - Fixed bug where getPluginSettings was returning incorrect JSON structure. [#18](https://github.com/cloudflare/cloudflare-plugin-backend/pull/18)
84
-
85
-
86
- ## [1.1.6](#1.1.6) - 2016-09-5
87
- ### Fixed
88
- - Fixed where DataStoreInterface was not included [c3502d](https://github.com/cloudflare/cloudflare-plugin-backend/commit/c3502db2904be385e2ad0e37287085fcecbfba5f)
89
-
90
- ## [1.1.5](#1.1.5) - 2016-09-2
91
- ### Fixed
92
- - Fixed Datastore::get [bdfb9](https://github.com/cloudflare/cloudflare-plugin-backend/commit/bdfb94275bb297473cf0801b33938810c32f0cc3)
93
-
94
- ## [1.1.4](#1.1.4) - 2016-09-2
95
- ### Changed
96
- - Changed Datastore to support objects. [#15](https://github.com/cloudflare/cloudflare-plugin-backend/pull/15)
97
- - Made PageRuleLimitException shorter. [#16](https://github.com/cloudflare/cloudflare-plugin-backend/pull/16)
98
-
99
- ## [1.1.3](#1.1.3) - 2016-08-31
100
- ### Fixed
101
- - Fixed bug where CF\API\AbstractPluginActions::login() would log the user in with invalid credentials. [#14](https://github.com/cloudflare/cloudflare-plugin-backend/pull/14)
102
-
103
- ## [1.1.2](#1.1.2) - 2016-08-17
104
- ### Changed
105
- - Fixed bug in CF\API\Exception. [#13](https://github.com/cloudflare/cloudflare-plugin-backend/pull/13)
106
-
107
- ## [1.1.1](#1.1.1) - 2016-08-16
108
- ### Added
109
- - Added plugin_specific_cache_tag setting to CF\API\Plugin settings. [#12](https://github.com/cloudflare/cloudflare-plugin-backend/pull/12)
110
-
111
- ## [1.1.0](#1.1.0) - 2016-08-11
112
- ### Added
113
- - Added CF\Router\RequestRouter to consolidate duplicate request routing logic each plugin was implementing. [#8](https://github.com/cloudflare/cloudflare-plugin-backend/pull/8)
114
-
115
- ### Changed
116
- - PluginRoutes, PluginActions moved to CF\API to consolidate the Internal Plugin API logic across all plugins. [#10](https://github.com/cloudflare/cloudflare-plugin-backend/pull/10)
117
-
118
- ## [1.0.9](#1.0.9) - 2016-08-03
119
- ### Changed
120
- - Removed static type checking to support earlier php versions [ad13c1e](https://github.com/cloudflare/cloudflare-plugin-backend/commit/ad13c1ec6edeceae5a85f8912208ce2c80f4a5f2)
121
-
122
- ## [1.0.8](#1.0.8) - 2016-08-02
123
- ### Changed
124
- - Fixed error message bug [61584ca](https://github.com/cloudflare/cloudflare-plugin-backend/commit/61584ca56f8ed6ba76cb321593955e0b57f3c88d)
125
-
126
- ## [1.0.7](#1.0.7) - 2016-08-02
127
- ### Changed
128
- - Updated CHANGELOG [5e72177](https://github.com/cloudflare/cloudflare-plugin-backend/commit/5e72177aadf1c34cf75904b52bf017e7b6c6c672)
129
-
130
- ## [1.0.6](#1.0.6) - 2016-08-02
131
- ### Changed
132
- - Changed error message from always "Bad Request" to original API message [235b020](https://github.com/cloudflare/cloudflare-plugin-backend/commit/235b020ad48cf9c0d2cdcb067b34d1424f0571f6)
133
-
134
- ## [1.0.5](#1.0.5) - 2016-07-22
135
- ### Added
136
- - PI-697 added PLUGIN_SPECIFIC_CACHE consts to CF\API\Plugin [10fb134](https://github.com/cloudflare/cloudflare-plugin-backend/commit/10fb1346d81e6b7fb71abfdfb93ce12c3d55fb91)
137
-
138
- ## [1.0.4](#1.0.4) - 2016-07-15
139
- ### Added
140
- - Added setting name consts to CF\API\Plugin [70372ab](https://github.com/cloudflare/cloudflare-plugin-backend/commit/70372ab0d1e294e0e6b57799e31c8a22ed4dedf6)
141
-
142
-
143
- ## [1.0.3](#1.0.3) - 2016-06-27
144
- ### Added
145
- - Added CF\API\Plugin.php built by @thellimist to handle plugin specific API calls. [#3](https://github.com/cloudflare/cloudflare-plugin-backend/pull/3)
146
-
147
- ## [1.0.2](#1.0.2) - 2016-06-14
148
- ### Changed
149
- - CF\Integration\LoggerInterface::logAPICall() moved to CF\API\AbstractAPIClient::logAPICall(). [#2](https://github.com/cloudflare/cloudflare-plugin-backend/pull/2)
150
-
151
- ## Removed
152
- - Removed CF\Integration\LoggerInterface. [#2](https://github.com/cloudflare/cloudflare-plugin-backend/pull/2)
153
-
154
- ## [1.0.1](#1.0.1) - 2016-06-07
155
- ### Changed
156
- - CF\Integration\LoggerInterface now implements PSR-3 LoggerInterface. [#1](https://github.com/cloudflare/cloudflare-plugin-backend/pull/1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/cloudflare/cloudflare-plugin-backend/LICENSE.md DELETED
@@ -1,11 +0,0 @@
1
- Copyright (c) 2016, Cloudflare. All rights reserved.
2
-
3
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
-
5
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
-
7
- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
-
9
- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
-
11
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 
 
 
 
 
 
 
 
 
vendor/cloudflare/cloudflare-plugin-backend/README.md DELETED
@@ -1,13 +0,0 @@
1
- [![Build Status](https://travis-ci.org/cloudflare/cloudflare-plugin-backend.svg?branch=master)](https://travis-ci.org/cloudflare/cloudflare-plugin-backend)
2
-
3
- This is a PHP backend for the official Cloudflare [cPanel](https://github.com/cloudflare/CloudFlare-CPanel), [Magento](https://github.com/cloudflare/CloudFlare-Magento), and [WordPress](https://github.com/cloudflare/CloudFlare-WordPress) plugins.
4
-
5
- ## Installation
6
- `composer require cloudflare/cloudflare-plugin-backend`
7
-
8
- ## Development
9
- ```
10
- $ composer test
11
- $ composer lint
12
- $ composer format
13
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/cloudflare/cloudflare-plugin-backend/composer.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "name": "cloudflare/cloudflare-plugin-backend",
3
- "description": "A PHP backend for Cloudflare plugins.",
4
- "license": "BSD-3-Clause",
5
- "version": "2.6.0",
6
- "scripts": {
7
- "test": "vendor/bin/phpunit",
8
- "lint": "vendor/bin/phpcs -n --standard=PSR2 --extensions=php src/",
9
- "format": "vendor/bin/phpcbf --standard=PSR2 --extensions=php src/"
10
- },
11
- "require": {
12
- "psr/log": "^1.0"
13
- },
14
- "require-dev": {
15
- "phpunit/phpunit": "4.8.*",
16
- "squizlabs/php_codesniffer": "2.*",
17
- "guzzlehttp/guzzle": "~5.0"
18
- },
19
- "autoload": {
20
- "psr-4": {
21
- "CF\\": "src/"
22
- }
23
- }
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/cloudflare/cloudflare-plugin-backend/composer.lock DELETED
@@ -1,1457 +0,0 @@
1
- {
2
- "_readme": [
3
- "This file locks the dependencies of your project to a known state",
4
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
- "This file is @generated automatically"
6
- ],
7
- "content-hash": "a4872e9aa68eb14cfd39a53c12f2db0b",
8
- "packages": [
9
- {
10
- "name": "psr/log",
11
- "version": "1.0.2",
12
- "source": {
13
- "type": "git",
14
- "url": "https://github.com/php-fig/log.git",
15
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
16
- },
17
- "dist": {
18
- "type": "zip",
19
- "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
20
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
21
- "shasum": ""
22
- },
23
- "require": {
24
- "php": ">=5.3.0"
25
- },
26
- "type": "library",
27
- "extra": {
28
- "branch-alias": {
29
- "dev-master": "1.0.x-dev"
30
- }
31
- },
32
- "autoload": {
33
- "psr-4": {
34
- "Psr\\Log\\": "Psr/Log/"
35
- }
36
- },
37
- "notification-url": "https://packagist.org/downloads/",
38
- "license": [
39
- "MIT"
40
- ],
41
- "authors": [
42
- {
43
- "name": "PHP-FIG",
44
- "homepage": "http://www.php-fig.org/"
45
- }
46
- ],
47
- "description": "Common interface for logging libraries",
48
- "homepage": "https://github.com/php-fig/log",
49
- "keywords": [
50
- "log",
51
- "psr",
52
- "psr-3"
53
- ],
54
- "time": "2016-10-10T12:19:37+00:00"
55
- }
56
- ],
57
- "packages-dev": [
58
- {
59
- "name": "doctrine/instantiator",
60
- "version": "1.0.5",
61
- "source": {
62
- "type": "git",
63
- "url": "https://github.com/doctrine/instantiator.git",
64
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
65
- },
66
- "dist": {
67
- "type": "zip",
68
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
69
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
70
- "shasum": ""
71
- },
72
- "require": {
73
- "php": ">=5.3,<8.0-DEV"
74
- },
75
- "require-dev": {
76
- "athletic/athletic": "~0.1.8",
77
- "ext-pdo": "*",
78
- "ext-phar": "*",
79
- "phpunit/phpunit": "~4.0",
80
- "squizlabs/php_codesniffer": "~2.0"
81
- },
82
- "type": "library",
83
- "extra": {
84
- "branch-alias": {
85
- "dev-master": "1.0.x-dev"
86
- }
87
- },
88
- "autoload": {
89
- "psr-4": {
90
- "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
91
- }
92
- },
93
- "notification-url": "https://packagist.org/downloads/",
94
- "license": [
95
- "MIT"
96
- ],
97
- "authors": [
98
- {
99
- "name": "Marco Pivetta",
100
- "email": "ocramius@gmail.com",
101
- "homepage": "http://ocramius.github.com/"
102
- }
103
- ],
104
- "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
105
- "homepage": "https://github.com/doctrine/instantiator",
106
- "keywords": [
107
- "constructor",
108
- "instantiate"
109
- ],
110
- "time": "2015-06-14T21:17:01+00:00"
111
- },
112
- {
113
- "name": "guzzlehttp/guzzle",
114
- "version": "5.3.3",
115
- "source": {
116
- "type": "git",
117
- "url": "https://github.com/guzzle/guzzle.git",
118
- "reference": "93bbdb30d59be6cd9839495306c65f2907370eb9"
119
- },
120
- "dist": {
121
- "type": "zip",
122
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/93bbdb30d59be6cd9839495306c65f2907370eb9",
123
- "reference": "93bbdb30d59be6cd9839495306c65f2907370eb9",
124
- "shasum": ""
125
- },
126
- "require": {
127
- "guzzlehttp/ringphp": "^1.1",
128
- "php": ">=5.4.0",
129
- "react/promise": "^2.2"
130
- },
131
- "require-dev": {
132
- "ext-curl": "*",
133
- "phpunit/phpunit": "^4.0"
134
- },
135
- "type": "library",
136
- "autoload": {
137
- "psr-4": {
138
- "GuzzleHttp\\": "src/"
139
- }
140
- },
141
- "notification-url": "https://packagist.org/downloads/",
142
- "license": [
143
- "MIT"
144
- ],
145
- "authors": [
146
- {
147
- "name": "Michael Dowling",
148
- "email": "mtdowling@gmail.com",
149
- "homepage": "https://github.com/mtdowling"
150
- }
151
- ],
152
- "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
153
- "homepage": "http://guzzlephp.org/",
154
- "keywords": [
155
- "client",
156
- "curl",
157
- "framework",
158
- "http",
159
- "http client",
160
- "rest",
161
- "web service"
162
- ],
163
- "time": "2018-07-31T13:33:10+00:00"
164
- },
165
- {
166
- "name": "guzzlehttp/ringphp",
167
- "version": "1.1.0",
168
- "source": {
169
- "type": "git",
170
- "url": "https://github.com/guzzle/RingPHP.git",
171
- "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b"
172
- },
173
- "dist": {
174
- "type": "zip",
175
- "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
176
- "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
177
- "shasum": ""
178
- },
179
- "require": {
180
- "guzzlehttp/streams": "~3.0",
181
- "php": ">=5.4.0",
182
- "react/promise": "~2.0"
183
- },
184
- "require-dev": {
185
- "ext-curl": "*",
186
- "phpunit/phpunit": "~4.0"
187
- },
188
- "suggest": {
189
- "ext-curl": "Guzzle will use specific adapters if cURL is present"
190
- },
191
- "type": "library",
192
- "extra": {
193
- "branch-alias": {
194
- "dev-master": "1.1-dev"
195
- }
196
- },
197
- "autoload": {
198
- "psr-4": {
199
- "GuzzleHttp\\Ring\\": "src/"
200
- }
201
- },
202
- "notification-url": "https://packagist.org/downloads/",
203
- "license": [
204
- "MIT"
205
- ],
206
- "authors": [
207
- {
208
- "name": "Michael Dowling",
209
- "email": "mtdowling@gmail.com",
210
- "homepage": "https://github.com/mtdowling"
211
- }
212
- ],
213
- "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
214
- "time": "2015-05-20T03:37:09+00:00"
215
- },
216
- {
217
- "name": "guzzlehttp/streams",
218
- "version": "3.0.0",
219
- "source": {
220
- "type": "git",
221
- "url": "https://github.com/guzzle/streams.git",
222
- "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
223
- },
224
- "dist": {
225
- "type": "zip",
226
- "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
227
- "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
228
- "shasum": ""
229
- },
230
- "require": {
231
- "php": ">=5.4.0"
232
- },
233
- "require-dev": {
234
- "phpunit/phpunit": "~4.0"
235
- },
236
- "type": "library",
237
- "extra": {
238
- "branch-alias": {
239
- "dev-master": "3.0-dev"
240
- }
241
- },
242
- "autoload": {
243
- "psr-4": {
244
- "GuzzleHttp\\Stream\\": "src/"
245
- }
246
- },
247
- "notification-url": "https://packagist.org/downloads/",
248
- "license": [
249
- "MIT"
250
- ],
251
- "authors": [
252
- {
253
- "name": "Michael Dowling",
254
- "email": "mtdowling@gmail.com",
255
- "homepage": "https://github.com/mtdowling"
256
- }
257
- ],
258
- "description": "Provides a simple abstraction over streams of data",
259
- "homepage": "http://guzzlephp.org/",
260
- "keywords": [
261
- "Guzzle",
262
- "stream"
263
- ],
264
- "time": "2014-10-12T19:18:40+00:00"
265
- },
266
- {
267
- "name": "phpdocumentor/reflection-common",
268
- "version": "1.0",
269
- "source": {
270
- "type": "git",
271
- "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
272
- "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
273
- },
274
- "dist": {
275
- "type": "zip",
276
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
277
- "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
278
- "shasum": ""
279
- },
280
- "require": {
281
- "php": ">=5.5"
282
- },
283
- "require-dev": {
284
- "phpunit/phpunit": "^4.6"
285
- },
286
- "type": "library",
287
- "extra": {
288
- "branch-alias": {
289
- "dev-master": "1.0.x-dev"
290
- }
291
- },
292
- "autoload": {
293
- "psr-4": {
294
- "phpDocumentor\\Reflection\\": [
295
- "src"
296
- ]
297
- }
298
- },
299
- "notification-url": "https://packagist.org/downloads/",
300
- "license": [
301
- "MIT"
302
- ],
303
- "authors": [
304
- {
305
- "name": "Jaap van Otterdijk",
306
- "email": "opensource@ijaap.nl"
307
- }
308
- ],
309
- "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
310
- "homepage": "http://www.phpdoc.org",
311
- "keywords": [
312
- "FQSEN",
313
- "phpDocumentor",
314
- "phpdoc",
315
- "reflection",
316
- "static analysis"
317
- ],
318
- "time": "2015-12-27T11:43:31+00:00"
319
- },
320
- {
321
- "name": "phpdocumentor/reflection-docblock",
322
- "version": "3.1.1",
323
- "source": {
324
- "type": "git",
325
- "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
326
- "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
327
- },
328
- "dist": {
329
- "type": "zip",
330
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
331
- "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
332
- "shasum": ""
333
- },
334
- "require": {
335
- "php": ">=5.5",
336
- "phpdocumentor/reflection-common": "^1.0@dev",
337
- "phpdocumentor/type-resolver": "^0.2.0",
338
- "webmozart/assert": "^1.0"
339
- },
340
- "require-dev": {
341
- "mockery/mockery": "^0.9.4",
342
- "phpunit/phpunit": "^4.4"
343
- },
344
- "type": "library",
345
- "autoload": {
346
- "psr-4": {
347
- "phpDocumentor\\Reflection\\": [
348
- "src/"
349
- ]
350
- }
351
- },
352
- "notification-url": "https://packagist.org/downloads/",
353
- "license": [
354
- "MIT"
355
- ],
356
- "authors": [
357
- {
358
- "name": "Mike van Riel",
359
- "email": "me@mikevanriel.com"
360
- }
361
- ],
362
- "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
363
- "time": "2016-09-30T07:12:33+00:00"
364
- },
365
- {
366
- "name": "phpdocumentor/type-resolver",
367
- "version": "0.2.1",
368
- "source": {
369
- "type": "git",
370
- "url": "https://github.com/phpDocumentor/TypeResolver.git",
371
- "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb"
372
- },
373
- "dist": {
374
- "type": "zip",
375
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
376
- "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
377
- "shasum": ""
378
- },
379
- "require": {
380
- "php": ">=5.5",
381
- "phpdocumentor/reflection-common": "^1.0"
382
- },
383
- "require-dev": {
384
- "mockery/mockery": "^0.9.4",
385
- "phpunit/phpunit": "^5.2||^4.8.24"
386
- },
387
- "type": "library",
388
- "extra": {
389
- "branch-alias": {
390
- "dev-master": "1.0.x-dev"
391
- }
392
- },
393
- "autoload": {
394
- "psr-4": {
395
- "phpDocumentor\\Reflection\\": [
396
- "src/"
397
- ]
398
- }
399
- },
400
- "notification-url": "https://packagist.org/downloads/",
401
- "license": [
402
- "MIT"
403
- ],
404
- "authors": [
405
- {
406
- "name": "Mike van Riel",
407
- "email": "me@mikevanriel.com"
408
- }
409
- ],
410
- "time": "2016-11-25T06:54:22+00:00"
411
- },
412
- {
413
- "name": "phpspec/prophecy",
414
- "version": "v1.7.0",
415
- "source": {
416
- "type": "git",
417
- "url": "https://github.com/phpspec/prophecy.git",
418
- "reference": "93d39f1f7f9326d746203c7c056f300f7f126073"
419
- },
420
- "dist": {
421
- "type": "zip",
422
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073",
423
- "reference": "93d39f1f7f9326d746203c7c056f300f7f126073",
424
- "shasum": ""
425
- },
426
- "require": {
427
- "doctrine/instantiator": "^1.0.2",
428
- "php": "^5.3|^7.0",
429
- "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
430
- "sebastian/comparator": "^1.1|^2.0",
431
- "sebastian/recursion-context": "^1.0|^2.0|^3.0"
432
- },
433
- "require-dev": {
434
- "phpspec/phpspec": "^2.5|^3.2",
435
- "phpunit/phpunit": "^4.8 || ^5.6.5"
436
- },
437
- "type": "library",
438
- "extra": {
439
- "branch-alias": {
440
- "dev-master": "1.6.x-dev"
441
- }
442
- },
443
- "autoload": {
444
- "psr-0": {
445
- "Prophecy\\": "src/"
446
- }
447
- },
448
- "notification-url": "https://packagist.org/downloads/",
449
- "license": [
450
- "MIT"
451
- ],
452
- "authors": [
453
- {
454
- "name": "Konstantin Kudryashov",
455
- "email": "ever.zet@gmail.com",
456
- "homepage": "http://everzet.com"
457
- },
458
- {
459
- "name": "Marcello Duarte",
460
- "email": "marcello.duarte@gmail.com"
461
- }
462
- ],
463
- "description": "Highly opinionated mocking framework for PHP 5.3+",
464
- "homepage": "https://github.com/phpspec/prophecy",
465
- "keywords": [
466
- "Double",
467
- "Dummy",
468
- "fake",
469
- "mock",
470
- "spy",
471
- "stub"
472
- ],
473
- "time": "2017-03-02T20:05:34+00:00"
474
- },
475
- {
476
- "name": "phpunit/php-code-coverage",
477
- "version": "2.2.4",
478
- "source": {
479
- "type": "git",
480
- "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
481
- "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
482
- },
483
- "dist": {
484
- "type": "zip",
485
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
486
- "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
487
- "shasum": ""
488
- },
489
- "require": {
490
- "php": ">=5.3.3",
491
- "phpunit/php-file-iterator": "~1.3",
492
- "phpunit/php-text-template": "~1.2",
493
- "phpunit/php-token-stream": "~1.3",
494
- "sebastian/environment": "^1.3.2",
495
- "sebastian/version": "~1.0"
496
- },
497
- "require-dev": {
498
- "ext-xdebug": ">=2.1.4",
499
- "phpunit/phpunit": "~4"
500
- },
501
- "suggest": {
502
- "ext-dom": "*",
503
- "ext-xdebug": ">=2.2.1",
504
- "ext-xmlwriter": "*"
505
- },
506
- "type": "library",
507
- "extra": {
508
- "branch-alias": {
509
- "dev-master": "2.2.x-dev"
510
- }
511
- },
512
- "autoload": {
513
- "classmap": [
514
- "src/"
515
- ]
516
- },
517
- "notification-url": "https://packagist.org/downloads/",
518
- "license": [
519
- "BSD-3-Clause"
520
- ],
521
- "authors": [
522
- {
523
- "name": "Sebastian Bergmann",
524
- "email": "sb@sebastian-bergmann.de",
525
- "role": "lead"
526
- }
527
- ],
528
- "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
529
- "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
530
- "keywords": [
531
- "coverage",
532
- "testing",
533
- "xunit"
534
- ],
535
- "time": "2015-10-06T15:47:00+00:00"
536
- },
537
- {
538
- "name": "phpunit/php-file-iterator",
539
- "version": "1.4.2",
540
- "source": {
541
- "type": "git",
542
- "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
543
- "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
544
- },
545
- "dist": {
546
- "type": "zip",
547
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
548
- "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
549
- "shasum": ""
550
- },
551
- "require": {
552
- "php": ">=5.3.3"
553
- },
554
- "type": "library",
555
- "extra": {
556
- "branch-alias": {
557
- "dev-master": "1.4.x-dev"
558
- }
559
- },
560
- "autoload": {
561
- "classmap": [
562
- "src/"
563
- ]
564
- },
565
- "notification-url": "https://packagist.org/downloads/",
566
- "license": [
567
- "BSD-3-Clause"
568
- ],
569
- "authors": [
570
- {
571
- "name": "Sebastian Bergmann",
572
- "email": "sb@sebastian-bergmann.de",
573
- "role": "lead"
574
- }
575
- ],
576
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
577
- "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
578
- "keywords": [
579
- "filesystem",
580
- "iterator"
581
- ],
582
- "time": "2016-10-03T07:40:28+00:00"
583
- },
584
- {
585
- "name": "phpunit/php-text-template",
586
- "version": "1.2.1",
587
- "source": {
588
- "type": "git",
589
- "url": "https://github.com/sebastianbergmann/php-text-template.git",
590
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
591
- },
592
- "dist": {
593
- "type": "zip",
594
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
595
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
596
- "shasum": ""
597
- },
598
- "require": {
599
- "php": ">=5.3.3"
600
- },
601
- "type": "library",
602
- "autoload": {
603
- "classmap": [
604
- "src/"
605
- ]
606
- },
607
- "notification-url": "https://packagist.org/downloads/",
608
- "license": [
609
- "BSD-3-Clause"
610
- ],
611
- "authors": [
612
- {
613
- "name": "Sebastian Bergmann",
614
- "email": "sebastian@phpunit.de",
615
- "role": "lead"
616
- }
617
- ],
618
- "description": "Simple template engine.",
619
- "homepage": "https://github.com/sebastianbergmann/php-text-template/",
620
- "keywords": [
621
- "template"
622
- ],
623
- "time": "2015-06-21T13:50:34+00:00"
624
- },
625
- {
626
- "name": "phpunit/php-timer",
627
- "version": "1.0.9",
628
- "source": {
629
- "type": "git",
630
- "url": "https://github.com/sebastianbergmann/php-timer.git",
631
- "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
632
- },
633
- "dist": {
634
- "type": "zip",
635
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
636
- "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
637
- "shasum": ""
638
- },
639
- "require": {
640
- "php": "^5.3.3 || ^7.0"
641
- },
642
- "require-dev": {
643
- "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
644
- },
645
- "type": "library",
646
- "extra": {
647
- "branch-alias": {
648
- "dev-master": "1.0-dev"
649
- }
650
- },
651
- "autoload": {
652
- "classmap": [
653
- "src/"
654
- ]
655
- },
656
- "notification-url": "https://packagist.org/downloads/",
657
- "license": [
658
- "BSD-3-Clause"
659
- ],
660
- "authors": [
661
- {
662
- "name": "Sebastian Bergmann",
663
- "email": "sb@sebastian-bergmann.de",
664
- "role": "lead"
665
- }
666
- ],
667
- "description": "Utility class for timing",
668
- "homepage": "https://github.com/sebastianbergmann/php-timer/",
669
- "keywords": [
670
- "timer"
671
- ],
672
- "time": "2017-02-26T11:10:40+00:00"
673
- },
674
- {
675
- "name": "phpunit/php-token-stream",
676
- "version": "1.4.11",
677
- "source": {
678
- "type": "git",
679
- "url": "https://github.com/sebastianbergmann/php-token-stream.git",
680
- "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7"
681
- },
682
- "dist": {
683
- "type": "zip",
684
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7",
685
- "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7",
686
- "shasum": ""
687
- },
688
- "require": {
689
- "ext-tokenizer": "*",
690
- "php": ">=5.3.3"
691
- },
692
- "require-dev": {
693
- "phpunit/phpunit": "~4.2"
694
- },
695
- "type": "library",
696
- "extra": {
697
- "branch-alias": {
698
- "dev-master": "1.4-dev"
699
- }
700
- },
701
- "autoload": {
702
- "classmap": [
703
- "src/"
704
- ]
705
- },
706
- "notification-url": "https://packagist.org/downloads/",
707
- "license": [
708
- "BSD-3-Clause"
709
- ],
710
- "authors": [
711
- {
712
- "name": "Sebastian Bergmann",
713
- "email": "sebastian@phpunit.de"
714
- }
715
- ],
716
- "description": "Wrapper around PHP's tokenizer extension.",
717
- "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
718
- "keywords": [
719
- "tokenizer"
720
- ],
721
- "time": "2017-02-27T10:12:30+00:00"
722
- },
723
- {
724
- "name": "phpunit/phpunit",
725
- "version": "4.8.35",
726
- "source": {
727
- "type": "git",
728
- "url": "https://github.com/sebastianbergmann/phpunit.git",
729
- "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87"
730
- },
731
- "dist": {
732
- "type": "zip",
733
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87",
734
- "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87",
735
- "shasum": ""
736
- },
737
- "require": {
738
- "ext-dom": "*",
739
- "ext-json": "*",
740
- "ext-pcre": "*",
741
- "ext-reflection": "*",
742
- "ext-spl": "*",
743
- "php": ">=5.3.3",
744
- "phpspec/prophecy": "^1.3.1",
745
- "phpunit/php-code-coverage": "~2.1",
746
- "phpunit/php-file-iterator": "~1.4",
747
- "phpunit/php-text-template": "~1.2",
748
- "phpunit/php-timer": "^1.0.6",
749
- "phpunit/phpunit-mock-objects": "~2.3",
750
- "sebastian/comparator": "~1.2.2",
751
- "sebastian/diff": "~1.2",
752
- "sebastian/environment": "~1.3",
753
- "sebastian/exporter": "~1.2",
754
- "sebastian/global-state": "~1.0",
755
- "sebastian/version": "~1.0",
756
- "symfony/yaml": "~2.1|~3.0"
757
- },
758
- "suggest": {
759
- "phpunit/php-invoker": "~1.1"
760
- },
761
- "bin": [
762
- "phpunit"
763
- ],
764
- "type": "library",
765
- "extra": {
766
- "branch-alias": {
767
- "dev-master": "4.8.x-dev"
768
- }
769
- },
770
- "autoload": {
771
- "classmap": [
772
- "src/"
773
- ]
774
- },
775
- "notification-url": "https://packagist.org/downloads/",
776
- "license": [
777
- "BSD-3-Clause"
778
- ],
779
- "authors": [
780
- {
781
- "name": "Sebastian Bergmann",
782
- "email": "sebastian@phpunit.de",
783
- "role": "lead"
784
- }
785
- ],
786
- "description": "The PHP Unit Testing framework.",
787
- "homepage": "https://phpunit.de/",
788
- "keywords": [
789
- "phpunit",
790
- "testing",
791
- "xunit"
792
- ],
793
- "time": "2017-02-06T05:18:07+00:00"
794
- },
795
- {
796
- "name": "phpunit/phpunit-mock-objects",
797
- "version": "2.3.8",
798
- "source": {
799
- "type": "git",
800
- "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
801
- "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
802
- },
803
- "dist": {
804
- "type": "zip",
805
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
806
- "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
807
- "shasum": ""
808
- },
809
- "require": {
810
- "doctrine/instantiator": "^1.0.2",
811
- "php": ">=5.3.3",
812
- "phpunit/php-text-template": "~1.2",
813
- "sebastian/exporter": "~1.2"
814
- },
815
- "require-dev": {
816
- "phpunit/phpunit": "~4.4"
817
- },
818
- "suggest": {
819
- "ext-soap": "*"
820
- },
821
- "type": "library",
822
- "extra": {
823
- "branch-alias": {
824
- "dev-master": "2.3.x-dev"
825
- }
826
- },
827
- "autoload": {
828
- "classmap": [
829
- "src/"
830
- ]
831
- },
832
- "notification-url": "https://packagist.org/downloads/",
833
- "license": [
834
- "BSD-3-Clause"
835
- ],
836
- "authors": [
837
- {
838
- "name": "Sebastian Bergmann",
839
- "email": "sb@sebastian-bergmann.de",
840
- "role": "lead"
841
- }
842
- ],
843
- "description": "Mock Object library for PHPUnit",
844
- "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
845
- "keywords": [
846
- "mock",
847
- "xunit"
848
- ],
849
- "time": "2015-10-02T06:51:40+00:00"
850
- },
851
- {
852
- "name": "react/promise",
853
- "version": "v2.5.0",
854
- "source": {
855
- "type": "git",
856
- "url": "https://github.com/reactphp/promise.git",
857
- "reference": "2760f3898b7e931aa71153852dcd48a75c9b95db"
858
- },
859
- "dist": {
860
- "type": "zip",
861
- "url": "https://api.github.com/repos/reactphp/promise/zipball/2760f3898b7e931aa71153852dcd48a75c9b95db",
862
- "reference": "2760f3898b7e931aa71153852dcd48a75c9b95db",
863
- "shasum": ""
864
- },
865
- "require": {
866
- "php": ">=5.4.0"
867
- },
868
- "type": "library",
869
- "autoload": {
870
- "psr-4": {
871
- "React\\Promise\\": "src/"
872
- },
873
- "files": [
874
- "src/functions_include.php"
875
- ]
876
- },
877
- "notification-url": "https://packagist.org/downloads/",
878
- "license": [
879
- "MIT"
880
- ],
881
- "authors": [
882
- {
883
- "name": "Jan Sorgalla",
884
- "email": "jsorgalla@gmail.com"
885
- }
886
- ],
887
- "description": "A lightweight implementation of CommonJS Promises/A for PHP",
888
- "keywords": [
889
- "promise",
890
- "promises"
891
- ],
892
- "time": "2016-12-22T14:09:01+00:00"
893
- },
894
- {
895
- "name": "sebastian/comparator",
896
- "version": "1.2.4",
897
- "source": {
898
- "type": "git",
899
- "url": "https://github.com/sebastianbergmann/comparator.git",
900
- "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
901
- },
902
- "dist": {
903
- "type": "zip",
904
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
905
- "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
906
- "shasum": ""
907
- },
908
- "require": {
909
- "php": ">=5.3.3",
910
- "sebastian/diff": "~1.2",
911
- "sebastian/exporter": "~1.2 || ~2.0"
912
- },
913
- "require-dev": {
914
- "phpunit/phpunit": "~4.4"
915
- },
916
- "type": "library",
917
- "extra": {
918
- "branch-alias": {
919
- "dev-master": "1.2.x-dev"
920
- }
921
- },
922
- "autoload": {
923
- "classmap": [
924
- "src/"
925
- ]
926
- },
927
- "notification-url": "https://packagist.org/downloads/",
928
- "license": [
929
- "BSD-3-Clause"
930
- ],
931
- "authors": [
932
- {
933
- "name": "Jeff Welch",
934
- "email": "whatthejeff@gmail.com"
935
- },
936
- {
937
- "name": "Volker Dusch",
938
- "email": "github@wallbash.com"
939
- },
940
- {
941
- "name": "Bernhard Schussek",
942
- "email": "bschussek@2bepublished.at"
943
- },
944
- {
945
- "name": "Sebastian Bergmann",
946
- "email": "sebastian@phpunit.de"
947
- }
948
- ],
949
- "description": "Provides the functionality to compare PHP values for equality",
950
- "homepage": "http://www.github.com/sebastianbergmann/comparator",
951
- "keywords": [
952
- "comparator",
953
- "compare",
954
- "equality"
955
- ],
956
- "time": "2017-01-29T09:50:25+00:00"
957
- },
958
- {
959
- "name": "sebastian/diff",
960
- "version": "1.4.1",
961
- "source": {
962
- "type": "git",
963
- "url": "https://github.com/sebastianbergmann/diff.git",
964
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
965
- },
966
- "dist": {
967
- "type": "zip",
968
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
969
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
970
- "shasum": ""
971
- },
972
- "require": {
973
- "php": ">=5.3.3"
974
- },
975
- "require-dev": {
976
- "phpunit/phpunit": "~4.8"
977
- },
978
- "type": "library",
979
- "extra": {
980
- "branch-alias": {
981
- "dev-master": "1.4-dev"
982
- }
983
- },
984
- "autoload": {
985
- "classmap": [
986
- "src/"
987
- ]
988
- },
989
- "notification-url": "https://packagist.org/downloads/",
990
- "license": [
991
- "BSD-3-Clause"
992
- ],
993
- "authors": [
994
- {
995
- "name": "Kore Nordmann",
996
- "email": "mail@kore-nordmann.de"
997
- },
998
- {
999
- "name": "Sebastian Bergmann",
1000
- "email": "sebastian@phpunit.de"
1001
- }
1002
- ],
1003
- "description": "Diff implementation",
1004
- "homepage": "https://github.com/sebastianbergmann/diff",
1005
- "keywords": [
1006
- "diff"
1007
- ],
1008
- "time": "2015-12-08T07:14:41+00:00"
1009
- },
1010
- {
1011
- "name": "sebastian/environment",
1012
- "version": "1.3.8",
1013
- "source": {
1014
- "type": "git",
1015
- "url": "https://github.com/sebastianbergmann/environment.git",
1016
- "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
1017
- },
1018
- "dist": {
1019
- "type": "zip",
1020
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
1021
- "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
1022
- "shasum": ""
1023
- },
1024
- "require": {
1025
- "php": "^5.3.3 || ^7.0"
1026
- },
1027
- "require-dev": {
1028
- "phpunit/phpunit": "^4.8 || ^5.0"
1029
- },
1030
- "type": "library",
1031
- "extra": {
1032
- "branch-alias": {
1033
- "dev-master": "1.3.x-dev"
1034
- }
1035
- },
1036
- "autoload": {
1037
- "classmap": [
1038
- "src/"
1039
- ]
1040
- },
1041
- "notification-url": "https://packagist.org/downloads/",
1042
- "license": [
1043
- "BSD-3-Clause"
1044
- ],
1045
- "authors": [
1046
- {
1047
- "name": "Sebastian Bergmann",
1048
- "email": "sebastian@phpunit.de"
1049
- }
1050
- ],
1051
- "description": "Provides functionality to handle HHVM/PHP environments",
1052
- "homepage": "http://www.github.com/sebastianbergmann/environment",
1053
- "keywords": [
1054
- "Xdebug",
1055
- "environment",
1056
- "hhvm"
1057
- ],
1058
- "time": "2016-08-18T05:49:44+00:00"
1059
- },
1060
- {
1061
- "name": "sebastian/exporter",
1062
- "version": "1.2.2",
1063
- "source": {
1064
- "type": "git",
1065
- "url": "https://github.com/sebastianbergmann/exporter.git",
1066
- "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
1067
- },
1068
- "dist": {
1069
- "type": "zip",
1070
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
1071
- "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
1072
- "shasum": ""
1073
- },
1074
- "require": {
1075
- "php": ">=5.3.3",
1076
- "sebastian/recursion-context": "~1.0"
1077
- },
1078
- "require-dev": {
1079
- "ext-mbstring": "*",
1080
- "phpunit/phpunit": "~4.4"
1081
- },
1082
- "type": "library",
1083
- "extra": {
1084
- "branch-alias": {
1085
- "dev-master": "1.3.x-dev"
1086
- }
1087
- },
1088
- "autoload": {
1089
- "classmap": [
1090
- "src/"
1091
- ]
1092
- },
1093
- "notification-url": "https://packagist.org/downloads/",
1094
- "license": [
1095
- "BSD-3-Clause"
1096
- ],
1097
- "authors": [
1098
- {
1099
- "name": "Jeff Welch",
1100
- "email": "whatthejeff@gmail.com"
1101
- },
1102
- {
1103
- "name": "Volker Dusch",
1104
- "email": "github@wallbash.com"
1105
- },
1106
- {
1107
- "name": "Bernhard Schussek",
1108
- "email": "bschussek@2bepublished.at"
1109
- },
1110
- {
1111
- "name": "Sebastian Bergmann",
1112
- "email": "sebastian@phpunit.de"
1113
- },
1114
- {
1115
- "name": "Adam Harvey",
1116
- "email": "aharvey@php.net"
1117
- }
1118
- ],
1119
- "description": "Provides the functionality to export PHP variables for visualization",
1120
- "homepage": "http://www.github.com/sebastianbergmann/exporter",
1121
- "keywords": [
1122
- "export",
1123
- "exporter"
1124
- ],
1125
- "time": "2016-06-17T09:04:28+00:00"
1126
- },
1127
- {
1128
- "name": "sebastian/global-state",
1129
- "version": "1.1.1",
1130
- "source": {
1131
- "type": "git",
1132
- "url": "https://github.com/sebastianbergmann/global-state.git",
1133
- "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
1134
- },
1135
- "dist": {
1136
- "type": "zip",
1137
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
1138
- "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
1139
- "shasum": ""
1140
- },
1141
- "require": {
1142
- "php": ">=5.3.3"
1143
- },
1144
- "require-dev": {
1145
- "phpunit/phpunit": "~4.2"
1146
- },
1147
- "suggest": {
1148
- "ext-uopz": "*"
1149
- },
1150
- "type": "library",
1151
- "extra": {
1152
- "branch-alias": {
1153
- "dev-master": "1.0-dev"
1154
- }
1155
- },
1156
- "autoload": {
1157
- "classmap": [
1158
- "src/"
1159
- ]
1160
- },
1161
- "notification-url": "https://packagist.org/downloads/",
1162
- "license": [
1163
- "BSD-3-Clause"
1164
- ],
1165
- "authors": [
1166
- {
1167
- "name": "Sebastian Bergmann",
1168
- "email": "sebastian@phpunit.de"
1169
- }
1170
- ],
1171
- "description": "Snapshotting of global state",
1172
- "homepage": "http://www.github.com/sebastianbergmann/global-state",
1173
- "keywords": [
1174
- "global state"
1175
- ],
1176
- "time": "2015-10-12T03:26:01+00:00"
1177
- },
1178
- {
1179
- "name": "sebastian/recursion-context",
1180
- "version": "1.0.5",
1181
- "source": {
1182
- "type": "git",
1183
- "url": "https://github.com/sebastianbergmann/recursion-context.git",
1184
- "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7"
1185
- },
1186
- "dist": {
1187
- "type": "zip",
1188
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
1189
- "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
1190
- "shasum": ""
1191
- },
1192
- "require": {
1193
- "php": ">=5.3.3"
1194
- },
1195
- "require-dev": {
1196
- "phpunit/phpunit": "~4.4"
1197
- },
1198
- "type": "library",
1199
- "extra": {
1200
- "branch-alias": {
1201
- "dev-master": "1.0.x-dev"
1202
- }
1203
- },
1204
- "autoload": {
1205
- "classmap": [
1206
- "src/"
1207
- ]
1208
- },
1209
- "notification-url": "https://packagist.org/downloads/",
1210
- "license": [
1211
- "BSD-3-Clause"
1212
- ],
1213
- "authors": [
1214
- {
1215
- "name": "Jeff Welch",
1216
- "email": "whatthejeff@gmail.com"
1217
- },
1218
- {
1219
- "name": "Sebastian Bergmann",
1220
- "email": "sebastian@phpunit.de"
1221
- },
1222
- {
1223
- "name": "Adam Harvey",
1224
- "email": "aharvey@php.net"
1225
- }
1226
- ],
1227
- "description": "Provides functionality to recursively process PHP variables",
1228
- "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1229
- "time": "2016-10-03T07:41:43+00:00"
1230
- },
1231
- {
1232
- "name": "sebastian/version",
1233
- "version": "1.0.6",
1234
- "source": {
1235
- "type": "git",
1236
- "url": "https://github.com/sebastianbergmann/version.git",
1237
- "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
1238
- },
1239
- "dist": {
1240
- "type": "zip",
1241
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1242
- "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1243
- "shasum": ""
1244
- },
1245
- "type": "library",
1246
- "autoload": {
1247
- "classmap": [
1248
- "src/"
1249
- ]
1250
- },
1251
- "notification-url": "https://packagist.org/downloads/",
1252
- "license": [
1253
- "BSD-3-Clause"
1254
- ],
1255
- "authors": [
1256
- {
1257
- "name": "Sebastian Bergmann",
1258
- "email": "sebastian@phpunit.de",
1259
- "role": "lead"
1260
- }
1261
- ],
1262
- "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1263
- "homepage": "https://github.com/sebastianbergmann/version",
1264
- "time": "2015-06-21T13:59:46+00:00"
1265
- },
1266
- {
1267
- "name": "squizlabs/php_codesniffer",
1268
- "version": "2.8.1",
1269
- "source": {
1270
- "type": "git",
1271
- "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
1272
- "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d"
1273
- },
1274
- "dist": {
1275
- "type": "zip",
1276
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d",
1277
- "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d",
1278
- "shasum": ""
1279
- },
1280
- "require": {
1281
- "ext-simplexml": "*",
1282
- "ext-tokenizer": "*",
1283
- "ext-xmlwriter": "*",
1284
- "php": ">=5.1.2"
1285
- },
1286
- "require-dev": {
1287
- "phpunit/phpunit": "~4.0"
1288
- },
1289
- "bin": [
1290
- "scripts/phpcs",
1291
- "scripts/phpcbf"
1292
- ],
1293
- "type": "library",
1294
- "extra": {
1295
- "branch-alias": {
1296
- "dev-master": "2.x-dev"
1297
- }
1298
- },
1299
- "autoload": {
1300
- "classmap": [
1301
- "CodeSniffer.php",
1302
- "CodeSniffer/CLI.php",
1303
- "CodeSniffer/Exception.php",
1304
- "CodeSniffer/File.php",
1305
- "CodeSniffer/Fixer.php",
1306
- "CodeSniffer/Report.php",
1307
- "CodeSniffer/Reporting.php",
1308
- "CodeSniffer/Sniff.php",
1309
- "CodeSniffer/Tokens.php",
1310
- "CodeSniffer/Reports/",
1311
- "CodeSniffer/Tokenizers/",
1312
- "CodeSniffer/DocGenerators/",
1313
- "CodeSniffer/Standards/AbstractPatternSniff.php",
1314
- "CodeSniffer/Standards/AbstractScopeSniff.php",
1315
- "CodeSniffer/Standards/AbstractVariableSniff.php",
1316
- "CodeSniffer/Standards/IncorrectPatternException.php",
1317
- "CodeSniffer/Standards/Generic/Sniffs/",
1318
- "CodeSniffer/Standards/MySource/Sniffs/",
1319
- "CodeSniffer/Standards/PEAR/Sniffs/",
1320
- "CodeSniffer/Standards/PSR1/Sniffs/",
1321
- "CodeSniffer/Standards/PSR2/Sniffs/",
1322
- "CodeSniffer/Standards/Squiz/Sniffs/",
1323
- "CodeSniffer/Standards/Zend/Sniffs/"
1324
- ]
1325
- },
1326
- "notification-url": "https://packagist.org/downloads/",
1327
- "license": [
1328
- "BSD-3-Clause"
1329
- ],
1330
- "authors": [
1331
- {
1332
- "name": "Greg Sherwood",
1333
- "role": "lead"
1334
- }
1335
- ],
1336
- "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
1337
- "homepage": "http://www.squizlabs.com/php-codesniffer",
1338
- "keywords": [
1339
- "phpcs",
1340
- "standards"
1341
- ],
1342
- "time": "2017-03-01T22:17:45+00:00"
1343
- },
1344
- {
1345
- "name": "symfony/yaml",
1346
- "version": "v3.2.4",
1347
- "source": {
1348
- "type": "git",
1349
- "url": "https://github.com/symfony/yaml.git",
1350
- "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8"
1351
- },
1352
- "dist": {
1353
- "type": "zip",
1354
- "url": "https://api.github.com/repos/symfony/yaml/zipball/9724c684646fcb5387d579b4bfaa63ee0b0c64c8",
1355
- "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8",
1356
- "shasum": ""
1357
- },
1358
- "require": {
1359
- "php": ">=5.5.9"
1360
- },
1361
- "require-dev": {
1362
- "symfony/console": "~2.8|~3.0"
1363
- },
1364
- "suggest": {
1365
- "symfony/console": "For validating YAML files using the lint command"
1366
- },
1367
- "type": "library",
1368
- "extra": {
1369
- "branch-alias": {
1370
- "dev-master": "3.2-dev"
1371
- }
1372
- },
1373
- "autoload": {
1374
- "psr-4": {
1375
- "Symfony\\Component\\Yaml\\": ""
1376
- },
1377
- "exclude-from-classmap": [
1378
- "/Tests/"
1379
- ]
1380
- },
1381
- "notification-url": "https://packagist.org/downloads/",
1382
- "license": [
1383
- "MIT"
1384
- ],
1385
- "authors": [
1386
- {
1387
- "name": "Fabien Potencier",
1388
- "email": "fabien@symfony.com"
1389
- },
1390
- {
1391
- "name": "Symfony Community",
1392
- "homepage": "https://symfony.com/contributors"
1393
- }
1394
- ],
1395
- "description": "Symfony Yaml Component",
1396
- "homepage": "https://symfony.com",
1397
- "time": "2017-02-16T22:46:52+00:00"
1398
- },
1399
- {
1400
- "name": "webmozart/assert",
1401
- "version": "1.2.0",
1402
- "source": {
1403
- "type": "git",
1404
- "url": "https://github.com/webmozart/assert.git",
1405
- "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f"
1406
- },
1407
- "dist": {
1408
- "type": "zip",
1409
- "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f",
1410
- "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f",
1411
- "shasum": ""
1412
- },
1413
- "require": {
1414
- "php": "^5.3.3 || ^7.0"
1415
- },
1416
- "require-dev": {
1417
- "phpunit/phpunit": "^4.6",
1418
- "sebastian/version": "^1.0.1"
1419
- },
1420
- "type": "library",
1421
- "extra": {
1422
- "branch-alias": {
1423
- "dev-master": "1.3-dev"
1424
- }
1425
- },
1426
- "autoload": {
1427
- "psr-4": {
1428
- "Webmozart\\Assert\\": "src/"
1429
- }
1430
- },
1431
- "notification-url": "https://packagist.org/downloads/",
1432
- "license": [
1433
- "MIT"
1434
- ],
1435
- "authors": [
1436
- {
1437
- "name": "Bernhard Schussek",
1438
- "email": "bschussek@gmail.com"
1439
- }
1440
- ],
1441
- "description": "Assertions to validate method input/output with nice error messages.",
1442
- "keywords": [
1443
- "assert",
1444
- "check",
1445
- "validate"
1446
- ],
1447
- "time": "2016-11-23T20:04:58+00:00"
1448
- }
1449
- ],
1450
- "aliases": [],
1451
- "minimum-stability": "stable",
1452
- "stability-flags": [],
1453
- "prefer-stable": false,
1454
- "prefer-lowest": false,
1455
- "platform": [],
1456
- "platform-dev": []
1457
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/composer/autoload_files.php CHANGED
@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
10
  'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
11
  'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
10
  '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
11
  'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
12
  'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
vendor/composer/autoload_psr4.php CHANGED
@@ -9,6 +9,10 @@ return array(
9
  'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
10
  'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
11
  'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
 
12
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
13
- 'CF\\' => array($baseDir . '/src', $vendorDir . '/cloudflare/cloudflare-plugin-backend/src'),
 
 
 
14
  );
9
  'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
10
  'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
11
  'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
12
+ 'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
13
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
14
+ 'GuzzleHttp\\Stream\\' => array($vendorDir . '/guzzlehttp/streams/src'),
15
+ 'GuzzleHttp\\Ring\\' => array($vendorDir . '/guzzlehttp/ringphp/src'),
16
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
17
+ 'CF\\' => array($baseDir . '/src'),
18
  );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitb9183805180972492bbb5c9641f787bc
6
  {
7
  private static $loader;
8
 
@@ -22,15 +22,15 @@ class ComposerAutoloaderInitb9183805180972492bbb5c9641f787bc
22
  return self::$loader;
23
  }
24
 
25
- spl_autoload_register(array('ComposerAutoloaderInitb9183805180972492bbb5c9641f787bc', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
- spl_autoload_unregister(array('ComposerAutoloaderInitb9183805180972492bbb5c9641f787bc', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
- call_user_func(\Composer\Autoload\ComposerStaticInitb9183805180972492bbb5c9641f787bc::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
@@ -51,19 +51,19 @@ class ComposerAutoloaderInitb9183805180972492bbb5c9641f787bc
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
- $includeFiles = Composer\Autoload\ComposerStaticInitb9183805180972492bbb5c9641f787bc::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
- composerRequireb9183805180972492bbb5c9641f787bc($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
- function composerRequireb9183805180972492bbb5c9641f787bc($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitb4c5e3a2bd2c2924c4d2474a7b9c8add
6
  {
7
  private static $loader;
8
 
22
  return self::$loader;
23
  }
24
 
25
+ spl_autoload_register(array('ComposerAutoloaderInitb4c5e3a2bd2c2924c4d2474a7b9c8add', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInitb4c5e3a2bd2c2924c4d2474a7b9c8add', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
+ call_user_func(\Composer\Autoload\ComposerStaticInitb4c5e3a2bd2c2924c4d2474a7b9c8add::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
+ $includeFiles = Composer\Autoload\ComposerStaticInitb4c5e3a2bd2c2924c4d2474a7b9c8add::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
+ composerRequireb4c5e3a2bd2c2924c4d2474a7b9c8add($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
+ function composerRequireb4c5e3a2bd2c2924c4d2474a7b9c8add($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,9 +4,10 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitb9183805180972492bbb5c9641f787bc
8
  {
9
  public static $files = array (
 
10
  '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
11
  'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
12
  'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
@@ -19,10 +20,20 @@ class ComposerStaticInitb9183805180972492bbb5c9641f787bc
19
  'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
20
  'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
21
  ),
 
 
 
 
22
  'P' =>
23
  array (
24
  'Psr\\Log\\' => 8,
25
  ),
 
 
 
 
 
 
26
  'C' =>
27
  array (
28
  'CF\\' => 3,
@@ -42,14 +53,29 @@ class ComposerStaticInitb9183805180972492bbb5c9641f787bc
42
  array (
43
  0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
44
  ),
 
 
 
 
45
  'Psr\\Log\\' =>
46
  array (
47
  0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
48
  ),
 
 
 
 
 
 
 
 
 
 
 
 
49
  'CF\\' =>
50
  array (
51
  0 => __DIR__ . '/../..' . '/src',
52
- 1 => __DIR__ . '/..' . '/cloudflare/cloudflare-plugin-backend/src',
53
  ),
54
  );
55
 
@@ -70,10 +96,10 @@ class ComposerStaticInitb9183805180972492bbb5c9641f787bc
70
  public static function getInitializer(ClassLoader $loader)
71
  {
72
  return \Closure::bind(function () use ($loader) {
73
- $loader->prefixLengthsPsr4 = ComposerStaticInitb9183805180972492bbb5c9641f787bc::$prefixLengthsPsr4;
74
- $loader->prefixDirsPsr4 = ComposerStaticInitb9183805180972492bbb5c9641f787bc::$prefixDirsPsr4;
75
- $loader->prefixesPsr0 = ComposerStaticInitb9183805180972492bbb5c9641f787bc::$prefixesPsr0;
76
- $loader->classMap = ComposerStaticInitb9183805180972492bbb5c9641f787bc::$classMap;
77
 
78
  }, null, ClassLoader::class);
79
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitb4c5e3a2bd2c2924c4d2474a7b9c8add
8
  {
9
  public static $files = array (
10
+ 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
11
  '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
12
  'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
13
  'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
20
  'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
21
  'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
22
  ),
23
+ 'R' =>
24
+ array (
25
+ 'React\\Promise\\' => 14,
26
+ ),
27
  'P' =>
28
  array (
29
  'Psr\\Log\\' => 8,
30
  ),
31
+ 'G' =>
32
+ array (
33
+ 'GuzzleHttp\\Stream\\' => 18,
34
+ 'GuzzleHttp\\Ring\\' => 16,
35
+ 'GuzzleHttp\\' => 11,
36
+ ),
37
  'C' =>
38
  array (
39
  'CF\\' => 3,
53
  array (
54
  0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
55
  ),
56
+ 'React\\Promise\\' =>
57
+ array (
58
+ 0 => __DIR__ . '/..' . '/react/promise/src',
59
+ ),
60
  'Psr\\Log\\' =>
61
  array (
62
  0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
63
  ),
64
+ 'GuzzleHttp\\Stream\\' =>
65
+ array (
66
+ 0 => __DIR__ . '/..' . '/guzzlehttp/streams/src',
67
+ ),
68
+ 'GuzzleHttp\\Ring\\' =>
69
+ array (
70
+ 0 => __DIR__ . '/..' . '/guzzlehttp/ringphp/src',
71
+ ),
72
+ 'GuzzleHttp\\' =>
73
+ array (
74
+ 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
75
+ ),
76
  'CF\\' =>
77
  array (
78
  0 => __DIR__ . '/../..' . '/src',
 
79
  ),
80
  );
81
 
96
  public static function getInitializer(ClassLoader $loader)
97
  {
98
  return \Closure::bind(function () use ($loader) {
99
+ $loader->prefixLengthsPsr4 = ComposerStaticInitb4c5e3a2bd2c2924c4d2474a7b9c8add::$prefixLengthsPsr4;
100
+ $loader->prefixDirsPsr4 = ComposerStaticInitb4c5e3a2bd2c2924c4d2474a7b9c8add::$prefixDirsPsr4;
101
+ $loader->prefixesPsr0 = ComposerStaticInitb4c5e3a2bd2c2924c4d2474a7b9c8add::$prefixesPsr0;
102
+ $loader->classMap = ComposerStaticInitb4c5e3a2bd2c2924c4d2474a7b9c8add::$classMap;
103
 
104
  }, null, ClassLoader::class);
105
  }
vendor/composer/installed.json CHANGED
@@ -47,44 +47,166 @@
47
  ]
48
  },
49
  {
50
- "name": "cloudflare/cloudflare-plugin-backend",
51
- "version": "2.6.0",
52
- "version_normalized": "2.6.0.0",
53
  "source": {
54
  "type": "git",
55
- "url": "https://github.com/cloudflare/cloudflare-plugin-backend.git",
56
- "reference": "6af901b5969120bf42fb51e68ab822285839ef9c"
57
  },
58
  "dist": {
59
  "type": "zip",
60
- "url": "https://api.github.com/repos/cloudflare/cloudflare-plugin-backend/zipball/6af901b5969120bf42fb51e68ab822285839ef9c",
61
- "reference": "6af901b5969120bf42fb51e68ab822285839ef9c",
62
  "shasum": ""
63
  },
64
  "require": {
65
- "psr/log": "^1.0"
 
 
66
  },
67
  "require-dev": {
68
- "guzzlehttp/guzzle": "~5.0",
69
- "phpunit/phpunit": "4.8.*",
70
- "squizlabs/php_codesniffer": "2.*"
71
  },
72
- "time": "2021-10-10T23:15:44+00:00",
73
  "type": "library",
74
  "installation-source": "dist",
75
  "autoload": {
76
  "psr-4": {
77
- "CF\\": "src/"
78
  }
79
  },
80
  "notification-url": "https://packagist.org/downloads/",
81
  "license": [
82
- "BSD-3-Clause"
83
  ],
84
- "description": "A PHP backend for Cloudflare plugins.",
85
- "support": {
86
- "source": "https://github.com/cloudflare/cloudflare-plugin-backend/tree/v2.6.0"
87
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  },
89
  {
90
  "name": "psr/log",
@@ -135,6 +257,54 @@
135
  "psr-3"
136
  ]
137
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  {
139
  "name": "symfony/polyfill-intl-idn",
140
  "version": "v1.23.0",
47
  ]
48
  },
49
  {
50
+ "name": "guzzlehttp/guzzle",
51
+ "version": "5.3.4",
52
+ "version_normalized": "5.3.4.0",
53
  "source": {
54
  "type": "git",
55
+ "url": "https://github.com/guzzle/guzzle.git",
56
+ "reference": "b87eda7a7162f95574032da17e9323c9899cb6b2"
57
  },
58
  "dist": {
59
  "type": "zip",
60
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b87eda7a7162f95574032da17e9323c9899cb6b2",
61
+ "reference": "b87eda7a7162f95574032da17e9323c9899cb6b2",
62
  "shasum": ""
63
  },
64
  "require": {
65
+ "guzzlehttp/ringphp": "^1.1",
66
+ "php": ">=5.4.0",
67
+ "react/promise": "^2.2"
68
  },
69
  "require-dev": {
70
+ "ext-curl": "*",
71
+ "phpunit/phpunit": "^4.0"
 
72
  },
73
+ "time": "2019-10-30T09:32:00+00:00",
74
  "type": "library",
75
  "installation-source": "dist",
76
  "autoload": {
77
  "psr-4": {
78
+ "GuzzleHttp\\": "src/"
79
  }
80
  },
81
  "notification-url": "https://packagist.org/downloads/",
82
  "license": [
83
+ "MIT"
84
  ],
85
+ "authors": [
86
+ {
87
+ "name": "Michael Dowling",
88
+ "email": "mtdowling@gmail.com",
89
+ "homepage": "https://github.com/mtdowling"
90
+ }
91
+ ],
92
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
93
+ "homepage": "http://guzzlephp.org/",
94
+ "keywords": [
95
+ "client",
96
+ "curl",
97
+ "framework",
98
+ "http",
99
+ "http client",
100
+ "rest",
101
+ "web service"
102
+ ]
103
+ },
104
+ {
105
+ "name": "guzzlehttp/ringphp",
106
+ "version": "1.1.1",
107
+ "version_normalized": "1.1.1.0",
108
+ "source": {
109
+ "type": "git",
110
+ "url": "https://github.com/guzzle/RingPHP.git",
111
+ "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b"
112
+ },
113
+ "dist": {
114
+ "type": "zip",
115
+ "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/5e2a174052995663dd68e6b5ad838afd47dd615b",
116
+ "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b",
117
+ "shasum": ""
118
+ },
119
+ "require": {
120
+ "guzzlehttp/streams": "~3.0",
121
+ "php": ">=5.4.0",
122
+ "react/promise": "~2.0"
123
+ },
124
+ "require-dev": {
125
+ "ext-curl": "*",
126
+ "phpunit/phpunit": "~4.0"
127
+ },
128
+ "suggest": {
129
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
130
+ },
131
+ "time": "2018-07-31T13:22:33+00:00",
132
+ "type": "library",
133
+ "extra": {
134
+ "branch-alias": {
135
+ "dev-master": "1.1-dev"
136
+ }
137
+ },
138
+ "installation-source": "dist",
139
+ "autoload": {
140
+ "psr-4": {
141
+ "GuzzleHttp\\Ring\\": "src/"
142
+ }
143
+ },
144
+ "notification-url": "https://packagist.org/downloads/",
145
+ "license": [
146
+ "MIT"
147
+ ],
148
+ "authors": [
149
+ {
150
+ "name": "Michael Dowling",
151
+ "email": "mtdowling@gmail.com",
152
+ "homepage": "https://github.com/mtdowling"
153
+ }
154
+ ],
155
+ "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
156
+ "abandoned": true
157
+ },
158
+ {
159
+ "name": "guzzlehttp/streams",
160
+ "version": "3.0.0",
161
+ "version_normalized": "3.0.0.0",
162
+ "source": {
163
+ "type": "git",
164
+ "url": "https://github.com/guzzle/streams.git",
165
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
166
+ },
167
+ "dist": {
168
+ "type": "zip",
169
+ "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
170
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
171
+ "shasum": ""
172
+ },
173
+ "require": {
174
+ "php": ">=5.4.0"
175
+ },
176
+ "require-dev": {
177
+ "phpunit/phpunit": "~4.0"
178
+ },
179
+ "time": "2014-10-12T19:18:40+00:00",
180
+ "type": "library",
181
+ "extra": {
182
+ "branch-alias": {
183
+ "dev-master": "3.0-dev"
184
+ }
185
+ },
186
+ "installation-source": "dist",
187
+ "autoload": {
188
+ "psr-4": {
189
+ "GuzzleHttp\\Stream\\": "src/"
190
+ }
191
+ },
192
+ "notification-url": "https://packagist.org/downloads/",
193
+ "license": [
194
+ "MIT"
195
+ ],
196
+ "authors": [
197
+ {
198
+ "name": "Michael Dowling",
199
+ "email": "mtdowling@gmail.com",
200
+ "homepage": "https://github.com/mtdowling"
201
+ }
202
+ ],
203
+ "description": "Provides a simple abstraction over streams of data",
204
+ "homepage": "http://guzzlephp.org/",
205
+ "keywords": [
206
+ "Guzzle",
207
+ "stream"
208
+ ],
209
+ "abandoned": true
210
  },
211
  {
212
  "name": "psr/log",
257
  "psr-3"
258
  ]
259
  },
260
+ {
261
+ "name": "react/promise",
262
+ "version": "v2.8.0",
263
+ "version_normalized": "2.8.0.0",
264
+ "source": {
265
+ "type": "git",
266
+ "url": "https://github.com/reactphp/promise.git",
267
+ "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4"
268
+ },
269
+ "dist": {
270
+ "type": "zip",
271
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4",
272
+ "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4",
273
+ "shasum": ""
274
+ },
275
+ "require": {
276
+ "php": ">=5.4.0"
277
+ },
278
+ "require-dev": {
279
+ "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36"
280
+ },
281
+ "time": "2020-05-12T15:16:56+00:00",
282
+ "type": "library",
283
+ "installation-source": "dist",
284
+ "autoload": {
285
+ "psr-4": {
286
+ "React\\Promise\\": "src/"
287
+ },
288
+ "files": [
289
+ "src/functions_include.php"
290
+ ]
291
+ },
292
+ "notification-url": "https://packagist.org/downloads/",
293
+ "license": [
294
+ "MIT"
295
+ ],
296
+ "authors": [
297
+ {
298
+ "name": "Jan Sorgalla",
299
+ "email": "jsorgalla@gmail.com"
300
+ }
301
+ ],
302
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
303
+ "keywords": [
304
+ "promise",
305
+ "promises"
306
+ ]
307
+ },
308
  {
309
  "name": "symfony/polyfill-intl-idn",
310
  "version": "v1.23.0",
vendor/guzzlehttp/guzzle/.travis.yml ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+
3
+ php:
4
+ - 5.4
5
+ - 5.5
6
+ - 5.6
7
+ - 7.0
8
+ - 7.1
9
+ - 7.2
10
+ - hhvm
11
+ - nightly
12
+
13
+ env:
14
+ global:
15
+ - TEST_COMMAND="composer test"
16
+
17
+ before_script:
18
+ - curl --version
19
+ - pear config-set php_ini ~/.phpenv/versions/`php -r 'echo phpversion();'`/etc/php.ini || echo 'Error modifying PEAR'
20
+ - pecl install uri_template || echo 'Error installing uri_template'
21
+ # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
22
+ - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
23
+ - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
24
+ - ~/.nvm/nvm.sh install v0.6.14
25
+ - ~/.nvm/nvm.sh run v0.6.14
26
+
27
+ script: $TEST_COMMAND
28
+
29
+ matrix:
30
+ allow_failures:
31
+ - php: hhvm
32
+ - php: nightly
33
+ fast_finish: true
34
+ include:
35
+ - php: 5.4
36
+ env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci"
37
+
38
+ before_deploy:
39
+ - make package
40
+
41
+ deploy:
42
+ provider: releases
43
+ api_key:
44
+ secure: UpypqlYgsU68QT/x40YzhHXvzWjFwCNo9d+G8KAdm7U9+blFfcWhV1aMdzugvPMl6woXgvJj7qHq5tAL4v6oswCORhpSBfLgOQVFaica5LiHsvWlAedOhxGmnJqMTwuepjBCxXhs3+I8Kof1n4oUL9gKytXjOVCX/f7XU1HiinU=
45
+ file:
46
+ - build/artifacts/guzzle.phar
47
+ - build/artifacts/guzzle.zip
48
+ on:
49
+ repo: guzzle/guzzle
50
+ tags: true
51
+ all_branches: true
52
+ php: 5.4
vendor/guzzlehttp/guzzle/CHANGELOG.md ADDED
@@ -0,0 +1,1075 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CHANGELOG
2
+
3
+ ## 5.3.4 - 2019-10-30
4
+
5
+ * Fix: Prevent concurrent writes in `FileCookieJar`
6
+
7
+ ## 5.3.3 - 2018-07-31
8
+
9
+ * Fix bug parsing 0 epoch expiry times
10
+ * Fix PHP 7.3 compatibility
11
+
12
+ ## 5.3.2 - 2018-01-15
13
+
14
+ * Improve tests
15
+ * Fix react promise dependency
16
+ * Fix PHP 7 compatibility
17
+
18
+ ## 5.3.1 - 2016-07-18
19
+
20
+ * Address HTTP_PROXY security vulnerability, CVE-2016-5385:
21
+ https://httpoxy.org/
22
+ * Event name fix: https://github.com/guzzle/guzzle/commit/fcae91ff31de41e312fe113ec3acbcda31b2622e
23
+ * Response header case sensitivity fix: https://github.com/guzzle/guzzle/commit/043eeadf20ee40ddc6712faee4d3957a91f2b041
24
+
25
+ ## 5.3.0 - 2015-05-19
26
+
27
+ * Mock now supports `save_to`
28
+ * Marked `AbstractRequestEvent::getTransaction()` as public.
29
+ * Fixed a bug in which multiple headers using different casing would overwrite
30
+ previous headers in the associative array.
31
+ * Added `Utils::getDefaultHandler()`
32
+ * Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
33
+ * URL scheme is now always lowercased.
34
+
35
+ ## 5.2.0 - 2015-01-27
36
+
37
+ * Added `AppliesHeadersInterface` to make applying headers to a request based
38
+ on the body more generic and not specific to `PostBodyInterface`.
39
+ * Reduced the number of stack frames needed to send requests.
40
+ * Nested futures are now resolved in the client rather than the RequestFsm
41
+ * Finishing state transitions is now handled in the RequestFsm rather than the
42
+ RingBridge.
43
+ * Added a guard in the Pool class to not use recursion for request retries.
44
+
45
+ ## 5.1.0 - 2014-12-19
46
+
47
+ * Pool class no longer uses recursion when a request is intercepted.
48
+ * The size of a Pool can now be dynamically adjusted using a callback.
49
+ See https://github.com/guzzle/guzzle/pull/943.
50
+ * Setting a request option to `null` when creating a request with a client will
51
+ ensure that the option is not set. This allows you to overwrite default
52
+ request options on a per-request basis.
53
+ See https://github.com/guzzle/guzzle/pull/937.
54
+ * Added the ability to limit which protocols are allowed for redirects by
55
+ specifying a `protocols` array in the `allow_redirects` request option.
56
+ * Nested futures due to retries are now resolved when waiting for synchronous
57
+ responses. See https://github.com/guzzle/guzzle/pull/947.
58
+ * `"0"` is now an allowed URI path. See
59
+ https://github.com/guzzle/guzzle/pull/935.
60
+ * `Query` no longer typehints on the `$query` argument in the constructor,
61
+ allowing for strings and arrays.
62
+ * Exceptions thrown in the `end` event are now correctly wrapped with Guzzle
63
+ specific exceptions if necessary.
64
+
65
+ ## 5.0.3 - 2014-11-03
66
+
67
+ This change updates query strings so that they are treated as un-encoded values
68
+ by default where the value represents an un-encoded value to send over the
69
+ wire. A Query object then encodes the value before sending over the wire. This
70
+ means that even value query string values (e.g., ":") are url encoded. This
71
+ makes the Query class match PHP's http_build_query function. However, if you
72
+ want to send requests over the wire using valid query string characters that do
73
+ not need to be encoded, then you can provide a string to Url::setQuery() and
74
+ pass true as the second argument to specify that the query string is a raw
75
+ string that should not be parsed or encoded (unless a call to getQuery() is
76
+ subsequently made, forcing the query-string to be converted into a Query
77
+ object).
78
+
79
+ ## 5.0.2 - 2014-10-30
80
+
81
+ * Added a trailing `\r\n` to multipart/form-data payloads. See
82
+ https://github.com/guzzle/guzzle/pull/871
83
+ * Added a `GuzzleHttp\Pool::send()` convenience method to match the docs.
84
+ * Status codes are now returned as integers. See
85
+ https://github.com/guzzle/guzzle/issues/881
86
+ * No longer overwriting an existing `application/x-www-form-urlencoded` header
87
+ when sending POST requests, allowing for customized headers. See
88
+ https://github.com/guzzle/guzzle/issues/877
89
+ * Improved path URL serialization.
90
+
91
+ * No longer double percent-encoding characters in the path or query string if
92
+ they are already encoded.
93
+ * Now properly encoding the supplied path to a URL object, instead of only
94
+ encoding ' ' and '?'.
95
+ * Note: This has been changed in 5.0.3 to now encode query string values by
96
+ default unless the `rawString` argument is provided when setting the query
97
+ string on a URL: Now allowing many more characters to be present in the
98
+ query string without being percent encoded. See http://tools.ietf.org/html/rfc3986#appendix-A
99
+
100
+ ## 5.0.1 - 2014-10-16
101
+
102
+ Bugfix release.
103
+
104
+ * Fixed an issue where connection errors still returned response object in
105
+ error and end events event though the response is unusable. This has been
106
+ corrected so that a response is not returned in the `getResponse` method of
107
+ these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867
108
+ * Fixed an issue where transfer statistics were not being populated in the
109
+ RingBridge. https://github.com/guzzle/guzzle/issues/866
110
+
111
+ ## 5.0.0 - 2014-10-12
112
+
113
+ Adding support for non-blocking responses and some minor API cleanup.
114
+
115
+ ### New Features
116
+
117
+ * Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`.
118
+ * Added a public API for creating a default HTTP adapter.
119
+ * Updated the redirect plugin to be non-blocking so that redirects are sent
120
+ concurrently. Other plugins like this can now be updated to be non-blocking.
121
+ * Added a "progress" event so that you can get upload and download progress
122
+ events.
123
+ * Added `GuzzleHttp\Pool` which implements FutureInterface and transfers
124
+ requests concurrently using a capped pool size as efficiently as possible.
125
+ * Added `hasListeners()` to EmitterInterface.
126
+ * Removed `GuzzleHttp\ClientInterface::sendAll` and marked
127
+ `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the
128
+ recommended way).
129
+
130
+ ### Breaking changes
131
+
132
+ The breaking changes in this release are relatively minor. The biggest thing to
133
+ look out for is that request and response objects no longer implement fluent
134
+ interfaces.
135
+
136
+ * Removed the fluent interfaces (i.e., `return $this`) from requests,
137
+ responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`,
138
+ `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and
139
+ `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of
140
+ why I did this: http://ocramius.github.io/blog/fluent-interfaces-are-evil/.
141
+ This also makes the Guzzle message interfaces compatible with the current
142
+ PSR-7 message proposal.
143
+ * Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except
144
+ for the HTTP request functions from function.php, these functions are now
145
+ implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode`
146
+ moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to
147
+ `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to
148
+ `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be
149
+ `GuzzleHttp\Pool::batch`, which returns an `objectStorage`. Using functions.php
150
+ caused problems for many users: they aren't PSR-4 compliant, require an
151
+ explicit include, and needed an if-guard to ensure that the functions are not
152
+ declared multiple times.
153
+ * Rewrote adapter layer.
154
+ * Removing all classes from `GuzzleHttp\Adapter`, these are now
155
+ implemented as callables that are stored in `GuzzleHttp\Ring\Client`.
156
+ * Removed the concept of "parallel adapters". Sending requests serially or
157
+ concurrently is now handled using a single adapter.
158
+ * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The
159
+ Transaction object now exposes the request, response, and client as public
160
+ properties. The getters and setters have been removed.
161
+ * Removed the "headers" event. This event was only useful for changing the
162
+ body a response once the headers of the response were known. You can implement
163
+ a similar behavior in a number of ways. One example might be to use a
164
+ FnStream that has access to the transaction being sent. For example, when the
165
+ first byte is written, you could check if the response headers match your
166
+ expectations, and if so, change the actual stream body that is being
167
+ written to.
168
+ * Removed the `asArray` parameter from
169
+ `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
170
+ value as an array, then use the newly added `getHeaderAsArray()` method of
171
+ `MessageInterface`. This change makes the Guzzle interfaces compatible with
172
+ the PSR-7 interfaces.
173
+ * `GuzzleHttp\Message\MessageFactory` no longer allows subclasses to add
174
+ custom request options using double-dispatch (this was an implementation
175
+ detail). Instead, you should now provide an associative array to the
176
+ constructor which is a mapping of the request option name mapping to a
177
+ function that applies the option value to a request.
178
+ * Removed the concept of "throwImmediately" from exceptions and error events.
179
+ This control mechanism was used to stop a transfer of concurrent requests
180
+ from completing. This can now be handled by throwing the exception or by
181
+ cancelling a pool of requests or each outstanding future request individually.
182
+ * Updated to "GuzzleHttp\Streams" 3.0.
183
+ * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a
184
+ `maxLen` parameter. This update makes the Guzzle streams project
185
+ compatible with the current PSR-7 proposal.
186
+ * `GuzzleHttp\Stream\Stream::__construct`,
187
+ `GuzzleHttp\Stream\Stream::factory`, and
188
+ `GuzzleHttp\Stream\Utils::create` no longer accept a size in the second
189
+ argument. They now accept an associative array of options, including the
190
+ "size" key and "metadata" key which can be used to provide custom metadata.
191
+
192
+ ## 4.2.2 - 2014-09-08
193
+
194
+ * Fixed a memory leak in the CurlAdapter when reusing cURL handles.
195
+ * No longer using `request_fulluri` in stream adapter proxies.
196
+ * Relative redirects are now based on the last response, not the first response.
197
+
198
+ ## 4.2.1 - 2014-08-19
199
+
200
+ * Ensuring that the StreamAdapter does not always add a Content-Type header
201
+ * Adding automated github releases with a phar and zip
202
+
203
+ ## 4.2.0 - 2014-08-17
204
+
205
+ * Now merging in default options using a case-insensitive comparison.
206
+ Closes https://github.com/guzzle/guzzle/issues/767
207
+ * Added the ability to automatically decode `Content-Encoding` response bodies
208
+ using the `decode_content` request option. This is set to `true` by default
209
+ to decode the response body if it comes over the wire with a
210
+ `Content-Encoding`. Set this value to `false` to disable decoding the
211
+ response content, and pass a string to provide a request `Accept-Encoding`
212
+ header and turn on automatic response decoding. This feature now allows you
213
+ to pass an `Accept-Encoding` header in the headers of a request but still
214
+ disable automatic response decoding.
215
+ Closes https://github.com/guzzle/guzzle/issues/764
216
+ * Added the ability to throw an exception immediately when transferring
217
+ requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760
218
+ * Updating guzzlehttp/streams dependency to ~2.1
219
+ * No longer utilizing the now deprecated namespaced methods from the stream
220
+ package.
221
+
222
+ ## 4.1.8 - 2014-08-14
223
+
224
+ * Fixed an issue in the CurlFactory that caused setting the `stream=false`
225
+ request option to throw an exception.
226
+ See: https://github.com/guzzle/guzzle/issues/769
227
+ * TransactionIterator now calls rewind on the inner iterator.
228
+ See: https://github.com/guzzle/guzzle/pull/765
229
+ * You can now set the `Content-Type` header to `multipart/form-data`
230
+ when creating POST requests to force multipart bodies.
231
+ See https://github.com/guzzle/guzzle/issues/768
232
+
233
+ ## 4.1.7 - 2014-08-07
234
+
235
+ * Fixed an error in the HistoryPlugin that caused the same request and response
236
+ to be logged multiple times when an HTTP protocol error occurs.
237
+ * Ensuring that cURL does not add a default Content-Type when no Content-Type
238
+ has been supplied by the user. This prevents the adapter layer from modifying
239
+ the request that is sent over the wire after any listeners may have already
240
+ put the request in a desired state (e.g., signed the request).
241
+ * Throwing an exception when you attempt to send requests that have the
242
+ "stream" set to true in parallel using the MultiAdapter.
243
+ * Only calling curl_multi_select when there are active cURL handles. This was
244
+ previously changed and caused performance problems on some systems due to PHP
245
+ always selecting until the maximum select timeout.
246
+ * Fixed a bug where multipart/form-data POST fields were not correctly
247
+ aggregated (e.g., values with "&").
248
+
249
+ ## 4.1.6 - 2014-08-03
250
+
251
+ * Added helper methods to make it easier to represent messages as strings,
252
+ including getting the start line and getting headers as a string.
253
+
254
+ ## 4.1.5 - 2014-08-02
255
+
256
+ * Automatically retrying cURL "Connection died, retrying a fresh connect"
257
+ errors when possible.
258
+ * cURL implementation cleanup
259
+ * Allowing multiple event subscriber listeners to be registered per event by
260
+ passing an array of arrays of listener configuration.
261
+
262
+ ## 4.1.4 - 2014-07-22
263
+
264
+ * Fixed a bug that caused multi-part POST requests with more than one field to
265
+ serialize incorrectly.
266
+ * Paths can now be set to "0"
267
+ * `ResponseInterface::xml` now accepts a `libxml_options` option and added a
268
+ missing default argument that was required when parsing XML response bodies.
269
+ * A `save_to` stream is now created lazily, which means that files are not
270
+ created on disk unless a request succeeds.
271
+
272
+ ## 4.1.3 - 2014-07-15
273
+
274
+ * Various fixes to multipart/form-data POST uploads
275
+ * Wrapping function.php in an if-statement to ensure Guzzle can be used
276
+ globally and in a Composer install
277
+ * Fixed an issue with generating and merging in events to an event array
278
+ * POST headers are only applied before sending a request to allow you to change
279
+ the query aggregator used before uploading
280
+ * Added much more robust query string parsing
281
+ * Fixed various parsing and normalization issues with URLs
282
+ * Fixing an issue where multi-valued headers were not being utilized correctly
283
+ in the StreamAdapter
284
+
285
+ ## 4.1.2 - 2014-06-18
286
+
287
+ * Added support for sending payloads with GET requests
288
+
289
+ ## 4.1.1 - 2014-06-08
290
+
291
+ * Fixed an issue related to using custom message factory options in subclasses
292
+ * Fixed an issue with nested form fields in a multi-part POST
293
+ * Fixed an issue with using the `json` request option for POST requests
294
+ * Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar`
295
+
296
+ ## 4.1.0 - 2014-05-27
297
+
298
+ * Added a `json` request option to easily serialize JSON payloads.
299
+ * Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON.
300
+ * Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`.
301
+ * Added the ability to provide an emitter to a client in the client constructor.
302
+ * Added the ability to persist a cookie session using $_SESSION.
303
+ * Added a trait that can be used to add event listeners to an iterator.
304
+ * Removed request method constants from RequestInterface.
305
+ * Fixed warning when invalid request start-lines are received.
306
+ * Updated MessageFactory to work with custom request option methods.
307
+ * Updated cacert bundle to latest build.
308
+
309
+ 4.0.2 (2014-04-16)
310
+ ------------------
311
+
312
+ * Proxy requests using the StreamAdapter now properly use request_fulluri (#632)
313
+ * Added the ability to set scalars as POST fields (#628)
314
+
315
+ ## 4.0.1 - 2014-04-04
316
+
317
+ * The HTTP status code of a response is now set as the exception code of
318
+ RequestException objects.
319
+ * 303 redirects will now correctly switch from POST to GET requests.
320
+ * The default parallel adapter of a client now correctly uses the MultiAdapter.
321
+ * HasDataTrait now initializes the internal data array as an empty array so
322
+ that the toArray() method always returns an array.
323
+
324
+ ## 4.0.0 - 2014-03-29
325
+
326
+ * For more information on the 4.0 transition, see:
327
+ http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/
328
+ * For information on changes and upgrading, see:
329
+ https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
330
+ * Added `GuzzleHttp\batch()` as a convenience function for sending requests in
331
+ parallel without needing to write asynchronous code.
332
+ * Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`.
333
+ You can now pass a callable or an array of associative arrays where each
334
+ associative array contains the "fn", "priority", and "once" keys.
335
+
336
+ ## 4.0.0.rc-2 - 2014-03-25
337
+
338
+ * Removed `getConfig()` and `setConfig()` from clients to avoid confusion
339
+ around whether things like base_url, message_factory, etc. should be able to
340
+ be retrieved or modified.
341
+ * Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface
342
+ * functions.php functions were renamed using snake_case to match PHP idioms
343
+ * Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and
344
+ `GUZZLE_CURL_SELECT_TIMEOUT` environment variables
345
+ * Added the ability to specify custom `sendAll()` event priorities
346
+ * Added the ability to specify custom stream context options to the stream
347
+ adapter.
348
+ * Added a functions.php function for `get_path()` and `set_path()`
349
+ * CurlAdapter and MultiAdapter now use a callable to generate curl resources
350
+ * MockAdapter now properly reads a body and emits a `headers` event
351
+ * Updated Url class to check if a scheme and host are set before adding ":"
352
+ and "//". This allows empty Url (e.g., "") to be serialized as "".
353
+ * Parsing invalid XML no longer emits warnings
354
+ * Curl classes now properly throw AdapterExceptions
355
+ * Various performance optimizations
356
+ * Streams are created with the faster `Stream\create()` function
357
+ * Marked deprecation_proxy() as internal
358
+ * Test server is now a collection of static methods on a class
359
+
360
+ ## 4.0.0-rc.1 - 2014-03-15
361
+
362
+ * See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
363
+
364
+ ## 3.8.1 - 2014-01-28
365
+
366
+ * Bug: Always using GET requests when redirecting from a 303 response
367
+ * Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in
368
+ `Guzzle\Http\ClientInterface::setSslVerification()`
369
+ * Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL
370
+ * Bug: The body of a request can now be set to `"0"`
371
+ * Sending PHP stream requests no longer forces `HTTP/1.0`
372
+ * Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of
373
+ each sub-exception
374
+ * Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than
375
+ clobbering everything).
376
+ * Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators)
377
+ * Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`.
378
+ For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`.
379
+ * Now properly escaping the regular expression delimiter when matching Cookie domains.
380
+ * Network access is now disabled when loading XML documents
381
+
382
+ ## 3.8.0 - 2013-12-05
383
+
384
+ * Added the ability to define a POST name for a file
385
+ * JSON response parsing now properly walks additionalProperties
386
+ * cURL error code 18 is now retried automatically in the BackoffPlugin
387
+ * Fixed a cURL error when URLs contain fragments
388
+ * Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were
389
+ CurlExceptions
390
+ * CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e)
391
+ * Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS`
392
+ * Fixed a bug that was encountered when parsing empty header parameters
393
+ * UriTemplate now has a `setRegex()` method to match the docs
394
+ * The `debug` request parameter now checks if it is truthy rather than if it exists
395
+ * Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin
396
+ * Added the ability to combine URLs using strict RFC 3986 compliance
397
+ * Command objects can now return the validation errors encountered by the command
398
+ * Various fixes to cache revalidation (#437 and 29797e5)
399
+ * Various fixes to the AsyncPlugin
400
+ * Cleaned up build scripts
401
+
402
+ ## 3.7.4 - 2013-10-02
403
+
404
+ * Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430)
405
+ * Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp
406
+ (see https://github.com/aws/aws-sdk-php/issues/147)
407
+ * Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots
408
+ * Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420)
409
+ * Updated the bundled cacert.pem (#419)
410
+ * OauthPlugin now supports adding authentication to headers or query string (#425)
411
+
412
+ ## 3.7.3 - 2013-09-08
413
+
414
+ * Added the ability to get the exception associated with a request/command when using `MultiTransferException` and
415
+ `CommandTransferException`.
416
+ * Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description
417
+ * Schemas are only injected into response models when explicitly configured.
418
+ * No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of
419
+ an EntityBody.
420
+ * Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator.
421
+ * Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`.
422
+ * Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody()
423
+ * Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin
424
+ * Bug fix: Visiting XML attributes first before visiting XML children when serializing requests
425
+ * Bug fix: Properly parsing headers that contain commas contained in quotes
426
+ * Bug fix: mimetype guessing based on a filename is now case-insensitive
427
+
428
+ ## 3.7.2 - 2013-08-02
429
+
430
+ * Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander
431
+ See https://github.com/guzzle/guzzle/issues/371
432
+ * Bug fix: Cookie domains are now matched correctly according to RFC 6265
433
+ See https://github.com/guzzle/guzzle/issues/377
434
+ * Bug fix: GET parameters are now used when calculating an OAuth signature
435
+ * Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted
436
+ * `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched
437
+ * `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input.
438
+ See https://github.com/guzzle/guzzle/issues/379
439
+ * Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See
440
+ https://github.com/guzzle/guzzle/pull/380
441
+ * cURL multi cleanup and optimizations
442
+
443
+ ## 3.7.1 - 2013-07-05
444
+
445
+ * Bug fix: Setting default options on a client now works
446
+ * Bug fix: Setting options on HEAD requests now works. See #352
447
+ * Bug fix: Moving stream factory before send event to before building the stream. See #353
448
+ * Bug fix: Cookies no longer match on IP addresses per RFC 6265
449
+ * Bug fix: Correctly parsing header parameters that are in `<>` and quotes
450
+ * Added `cert` and `ssl_key` as request options
451
+ * `Host` header can now diverge from the host part of a URL if the header is set manually
452
+ * `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter
453
+ * OAuth parameters are only added via the plugin if they aren't already set
454
+ * Exceptions are now thrown when a URL cannot be parsed
455
+ * Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails
456
+ * Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin
457
+
458
+ ## 3.7.0 - 2013-06-10
459
+
460
+ * See UPGRADING.md for more information on how to upgrade.
461
+ * Requests now support the ability to specify an array of $options when creating a request to more easily modify a
462
+ request. You can pass a 'request.options' configuration setting to a client to apply default request options to
463
+ every request created by a client (e.g. default query string variables, headers, curl options, etc.).
464
+ * Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`.
465
+ See `Guzzle\Http\StaticClient::mount`.
466
+ * Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
467
+ created by a command (e.g. custom headers, query string variables, timeout settings, etc.).
468
+ * Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the
469
+ headers of a response
470
+ * Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key
471
+ (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)
472
+ * ServiceBuilders now support storing and retrieving arbitrary data
473
+ * CachePlugin can now purge all resources for a given URI
474
+ * CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource
475
+ * CachePlugin now uses the Vary header to determine if a resource is a cache hit
476
+ * `Guzzle\Http\Message\Response` now implements `\Serializable`
477
+ * Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
478
+ * `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
479
+ * Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()`
480
+ * Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size
481
+ * `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message
482
+ * Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older
483
+ Symfony users can still use the old version of Monolog.
484
+ * Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`.
485
+ Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`.
486
+ * Several performance improvements to `Guzzle\Common\Collection`
487
+ * Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
488
+ createRequest, head, delete, put, patch, post, options, prepareRequest
489
+ * Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
490
+ * Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
491
+ * Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
492
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
493
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
494
+ * Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
495
+ default `array()`
496
+ * Added `Guzzle\Stream\StreamInterface::isRepeatable`
497
+ * Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
498
+ $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
499
+ $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`.
500
+ * Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.
501
+ * Removed `Guzzle\Http\ClientInterface::expandTemplate()`
502
+ * Removed `Guzzle\Http\ClientInterface::setRequestFactory()`
503
+ * Removed `Guzzle\Http\ClientInterface::getCurlMulti()`
504
+ * Removed `Guzzle\Http\Message\RequestInterface::canCache`
505
+ * Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`
506
+ * Removed `Guzzle\Http\Message\RequestInterface::isRedirect`
507
+ * Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
508
+ * You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting
509
+ `Guzzle\Common\Version::$emitWarnings` to true.
510
+ * Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use
511
+ `$request->getResponseBody()->isRepeatable()` instead.
512
+ * Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
513
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
514
+ * Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
515
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
516
+ * Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
517
+ * Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
518
+ * Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
519
+ * Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand.
520
+ These will work through Guzzle 4.0
521
+ * Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use [request.options][params].
522
+ * Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
523
+ * Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`.
524
+ * Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`.
525
+ * Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
526
+ * Marked `Guzzle\Common\Collection::inject()` as deprecated.
527
+ * Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');`
528
+ * CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
529
+ CacheStorageInterface. These two objects and interface will be removed in a future version.
530
+ * Always setting X-cache headers on cached responses
531
+ * Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
532
+ * `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
533
+ $request, Response $response);`
534
+ * `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
535
+ * `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
536
+ * Added `CacheStorageInterface::purge($url)`
537
+ * `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
538
+ $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
539
+ CanCacheStrategyInterface $canCache = null)`
540
+ * Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
541
+
542
+ ## 3.6.0 - 2013-05-29
543
+
544
+ * ServiceDescription now implements ToArrayInterface
545
+ * Added command.hidden_params to blacklist certain headers from being treated as additionalParameters
546
+ * Guzzle can now correctly parse incomplete URLs
547
+ * Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
548
+ * Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
549
+ * Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
550
+ * Specific header implementations can be created for complex headers. When a message creates a header, it uses a
551
+ HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
552
+ CacheControl header implementation.
553
+ * Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
554
+ * Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
555
+ * Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
556
+ Guzzle\Http\Curl\RequestMediator
557
+ * Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
558
+ * Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
559
+ * Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
560
+ * Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
561
+ * Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
562
+ * All response header helper functions return a string rather than mixing Header objects and strings inconsistently
563
+ * Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
564
+ directly via interfaces
565
+ * Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
566
+ but are a no-op until removed.
567
+ * Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
568
+ `Guzzle\Service\Command\ArrayCommandInterface`.
569
+ * Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
570
+ on a request while the request is still being transferred
571
+ * The ability to case-insensitively search for header values
572
+ * Guzzle\Http\Message\Header::hasExactHeader
573
+ * Guzzle\Http\Message\Header::raw. Use getAll()
574
+ * Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
575
+ instead.
576
+ * `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
577
+ * Added the ability to cast Model objects to a string to view debug information.
578
+
579
+ ## 3.5.0 - 2013-05-13
580
+
581
+ * Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times
582
+ * Bug: Better cleanup of one-time events across the board (when an event is meant to fire once, it will now remove
583
+ itself from the EventDispatcher)
584
+ * Bug: `Guzzle\Log\MessageFormatter` now properly writes "total_time" and "connect_time" values
585
+ * Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too
586
+ * Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a
587
+ non-existent key
588
+ * Bug: All __call() method arguments are now required (helps with mocking frameworks)
589
+ * Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference
590
+ to help with refcount based garbage collection of resources created by sending a request
591
+ * Deprecating ZF1 cache and log adapters. These will be removed in the next major version.
592
+ * Deprecating `Response::getPreviousResponse()` (method signature still exists, but it'sdeprecated). Use the
593
+ HistoryPlugin for a history.
594
+ * Added a `responseBody` alias for the `response_body` location
595
+ * Refactored internals to no longer rely on Response::getRequest()
596
+ * HistoryPlugin can now be cast to a string
597
+ * HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests
598
+ and responses that are sent over the wire
599
+ * Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects
600
+
601
+ ## 3.4.3 - 2013-04-30
602
+
603
+ * Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response
604
+ * Added a check to re-extract the temp cacert bundle from the phar before sending each request
605
+
606
+ ## 3.4.2 - 2013-04-29
607
+
608
+ * Bug fix: Stream objects now work correctly with "a" and "a+" modes
609
+ * Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present
610
+ * Bug fix: AsyncPlugin no longer forces HEAD requests
611
+ * Bug fix: DateTime timezones are now properly handled when using the service description schema formatter
612
+ * Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails
613
+ * Setting a response on a request will write to the custom request body from the response body if one is specified
614
+ * LogPlugin now writes to php://output when STDERR is undefined
615
+ * Added the ability to set multiple POST files for the same key in a single call
616
+ * application/x-www-form-urlencoded POSTs now use the utf-8 charset by default
617
+ * Added the ability to queue CurlExceptions to the MockPlugin
618
+ * Cleaned up how manual responses are queued on requests (removed "queued_response" and now using request.before_send)
619
+ * Configuration loading now allows remote files
620
+
621
+ ## 3.4.1 - 2013-04-16
622
+
623
+ * Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti
624
+ handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost.
625
+ * Exceptions are now properly grouped when sending requests in parallel
626
+ * Redirects are now properly aggregated when a multi transaction fails
627
+ * Redirects now set the response on the original object even in the event of a failure
628
+ * Bug fix: Model names are now properly set even when using $refs
629
+ * Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax
630
+ * Added support for oauth_callback in OAuth signatures
631
+ * Added support for oauth_verifier in OAuth signatures
632
+ * Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection
633
+
634
+ ## 3.4.0 - 2013-04-11
635
+
636
+ * Bug fix: URLs are now resolved correctly based on http://tools.ietf.org/html/rfc3986#section-5.2. #289
637
+ * Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289
638
+ * Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263
639
+ * Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264.
640
+ * Bug fix: Added `number` type to service descriptions.
641
+ * Bug fix: empty parameters are removed from an OAuth signature
642
+ * Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header
643
+ * Bug fix: Fixed "array to string" error when validating a union of types in a service description
644
+ * Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream
645
+ * Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin.
646
+ * Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs.
647
+ * The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections.
648
+ * Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if
649
+ the Content-Type can be determined based on the entity body or the path of the request.
650
+ * Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder.
651
+ * Added support for a PSR-3 LogAdapter.
652
+ * Added a `command.after_prepare` event
653
+ * Added `oauth_callback` parameter to the OauthPlugin
654
+ * Added the ability to create a custom stream class when using a stream factory
655
+ * Added a CachingEntityBody decorator
656
+ * Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized.
657
+ * The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar.
658
+ * You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies
659
+ * POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This
660
+ means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use
661
+ POST fields or files (the latter is only used when emulating a form POST in the browser).
662
+ * Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest
663
+
664
+ ## 3.3.1 - 2013-03-10
665
+
666
+ * Added the ability to create PHP streaming responses from HTTP requests
667
+ * Bug fix: Running any filters when parsing response headers with service descriptions
668
+ * Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing
669
+ * Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across
670
+ response location visitors.
671
+ * Bug fix: Removed the possibility of creating configuration files with circular dependencies
672
+ * RequestFactory::create() now uses the key of a POST file when setting the POST file name
673
+ * Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set
674
+
675
+ ## 3.3.0 - 2013-03-03
676
+
677
+ * A large number of performance optimizations have been made
678
+ * Bug fix: Added 'wb' as a valid write mode for streams
679
+ * Bug fix: `Guzzle\Http\Message\Response::json()` now allows scalar values to be returned
680
+ * Bug fix: Fixed bug in `Guzzle\Http\Message\Response` where wrapping quotes were stripped from `getEtag()`
681
+ * BC: Removed `Guzzle\Http\Utils` class
682
+ * BC: Setting a service description on a client will no longer modify the client's command factories.
683
+ * BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using
684
+ the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
685
+ * BC: `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getSteamType()` are no longer converted to
686
+ lowercase
687
+ * Operation parameter objects are now lazy loaded internally
688
+ * Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses
689
+ * Added support for instantiating responseType=class responseClass classes. Classes must implement
690
+ `Guzzle\Service\Command\ResponseClassInterface`
691
+ * Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These
692
+ additional properties also support locations and can be used to parse JSON responses where the outermost part of the
693
+ JSON is an array
694
+ * Added support for nested renaming of JSON models (rename sentAs to name)
695
+ * CachePlugin
696
+ * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error
697
+ * Debug headers can now added to cached response in the CachePlugin
698
+
699
+ ## 3.2.0 - 2013-02-14
700
+
701
+ * CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients.
702
+ * URLs with no path no longer contain a "/" by default
703
+ * Guzzle\Http\QueryString does no longer manages the leading "?". This is now handled in Guzzle\Http\Url.
704
+ * BadResponseException no longer includes the full request and response message
705
+ * Adding setData() to Guzzle\Service\Description\ServiceDescriptionInterface
706
+ * Adding getResponseBody() to Guzzle\Http\Message\RequestInterface
707
+ * Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription
708
+ * Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list
709
+ * xmlEncoding can now be customized for the XML declaration of a XML service description operation
710
+ * Guzzle\Http\QueryString now uses Guzzle\Http\QueryAggregator\QueryAggregatorInterface objects to add custom value
711
+ aggregation and no longer uses callbacks
712
+ * The URL encoding implementation of Guzzle\Http\QueryString can now be customized
713
+ * Bug fix: Filters were not always invoked for array service description parameters
714
+ * Bug fix: Redirects now use a target response body rather than a temporary response body
715
+ * Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded
716
+ * Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives
717
+
718
+ ## 3.1.2 - 2013-01-27
719
+
720
+ * Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the
721
+ response body. For example, the XmlVisitor now parses the XML response into an array in the before() method.
722
+ * Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent
723
+ * CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444)
724
+ * Fixed a bug where redirect responses were not chained correctly using getPreviousResponse()
725
+ * Setting default headers on a client after setting the user-agent will not erase the user-agent setting
726
+
727
+ ## 3.1.1 - 2013-01-20
728
+
729
+ * Adding wildcard support to Guzzle\Common\Collection::getPath()
730
+ * Adding alias support to ServiceBuilder configs
731
+ * Adding Guzzle\Service\Resource\CompositeResourceIteratorFactory and cleaning up factory interface
732
+
733
+ ## 3.1.0 - 2013-01-12
734
+
735
+ * BC: CurlException now extends from RequestException rather than BadResponseException
736
+ * BC: Renamed Guzzle\Plugin\Cache\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse()
737
+ * Added getData to ServiceDescriptionInterface
738
+ * Added context array to RequestInterface::setState()
739
+ * Bug: Removing hard dependency on the BackoffPlugin from Guzzle\Http
740
+ * Bug: Adding required content-type when JSON request visitor adds JSON to a command
741
+ * Bug: Fixing the serialization of a service description with custom data
742
+ * Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing
743
+ an array of successful and failed responses
744
+ * Moved getPath from Guzzle\Service\Resource\Model to Guzzle\Common\Collection
745
+ * Added Guzzle\Http\IoEmittingEntityBody
746
+ * Moved command filtration from validators to location visitors
747
+ * Added `extends` attributes to service description parameters
748
+ * Added getModels to ServiceDescriptionInterface
749
+
750
+ ## 3.0.7 - 2012-12-19
751
+
752
+ * Fixing phar detection when forcing a cacert to system if null or true
753
+ * Allowing filename to be passed to `Guzzle\Http\Message\Request::setResponseBody()`
754
+ * Cleaning up `Guzzle\Common\Collection::inject` method
755
+ * Adding a response_body location to service descriptions
756
+
757
+ ## 3.0.6 - 2012-12-09
758
+
759
+ * CurlMulti performance improvements
760
+ * Adding setErrorResponses() to Operation
761
+ * composer.json tweaks
762
+
763
+ ## 3.0.5 - 2012-11-18
764
+
765
+ * Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin
766
+ * Bug: Response body can now be a string containing "0"
767
+ * Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert
768
+ * Bug: QueryString::fromString now properly parses query string parameters that contain equal signs
769
+ * Added support for XML attributes in service description responses
770
+ * DefaultRequestSerializer now supports array URI parameter values for URI template expansion
771
+ * Added better mimetype guessing to requests and post files
772
+
773
+ ## 3.0.4 - 2012-11-11
774
+
775
+ * Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value
776
+ * Bug: Cookies can now be added that have a name, domain, or value set to "0"
777
+ * Bug: Using the system cacert bundle when using the Phar
778
+ * Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures
779
+ * Enhanced cookie jar de-duplication
780
+ * Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added
781
+ * Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies
782
+ * Added the ability to create any sort of hash for a stream rather than just an MD5 hash
783
+
784
+ ## 3.0.3 - 2012-11-04
785
+
786
+ * Implementing redirects in PHP rather than cURL
787
+ * Added PECL URI template extension and using as default parser if available
788
+ * Bug: Fixed Content-Length parsing of Response factory
789
+ * Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams.
790
+ * Adding ToArrayInterface throughout library
791
+ * Fixing OauthPlugin to create unique nonce values per request
792
+
793
+ ## 3.0.2 - 2012-10-25
794
+
795
+ * Magic methods are enabled by default on clients
796
+ * Magic methods return the result of a command
797
+ * Service clients no longer require a base_url option in the factory
798
+ * Bug: Fixed an issue with URI templates where null template variables were being expanded
799
+
800
+ ## 3.0.1 - 2012-10-22
801
+
802
+ * Models can now be used like regular collection objects by calling filter, map, etc.
803
+ * Models no longer require a Parameter structure or initial data in the constructor
804
+ * Added a custom AppendIterator to get around a PHP bug with the `\AppendIterator`
805
+
806
+ ## 3.0.0 - 2012-10-15
807
+
808
+ * Rewrote service description format to be based on Swagger
809
+ * Now based on JSON schema
810
+ * Added nested input structures and nested response models
811
+ * Support for JSON and XML input and output models
812
+ * Renamed `commands` to `operations`
813
+ * Removed dot class notation
814
+ * Removed custom types
815
+ * Broke the project into smaller top-level namespaces to be more component friendly
816
+ * Removed support for XML configs and descriptions. Use arrays or JSON files.
817
+ * Removed the Validation component and Inspector
818
+ * Moved all cookie code to Guzzle\Plugin\Cookie
819
+ * Magic methods on a Guzzle\Service\Client now return the command un-executed.
820
+ * Calling getResult() or getResponse() on a command will lazily execute the command if needed.
821
+ * Now shipping with cURL's CA certs and using it by default
822
+ * Added previousResponse() method to response objects
823
+ * No longer sending Accept and Accept-Encoding headers on every request
824
+ * Only sending an Expect header by default when a payload is greater than 1MB
825
+ * Added/moved client options:
826
+ * curl.blacklist to curl.option.blacklist
827
+ * Added ssl.certificate_authority
828
+ * Added a Guzzle\Iterator component
829
+ * Moved plugins from Guzzle\Http\Plugin to Guzzle\Plugin
830
+ * Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin)
831
+ * Added a more robust caching plugin
832
+ * Added setBody to response objects
833
+ * Updating LogPlugin to use a more flexible MessageFormatter
834
+ * Added a completely revamped build process
835
+ * Cleaning up Collection class and removing default values from the get method
836
+ * Fixed ZF2 cache adapters
837
+
838
+ ## 2.8.8 - 2012-10-15
839
+
840
+ * Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did
841
+
842
+ ## 2.8.7 - 2012-09-30
843
+
844
+ * Bug: Fixed config file aliases for JSON includes
845
+ * Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests
846
+ * Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload
847
+ * Bug: Hardening request and response parsing to account for missing parts
848
+ * Bug: Fixed PEAR packaging
849
+ * Bug: Fixed Request::getInfo
850
+ * Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail
851
+ * Adding the ability for the namespace Iterator factory to look in multiple directories
852
+ * Added more getters/setters/removers from service descriptions
853
+ * Added the ability to remove POST fields from OAuth signatures
854
+ * OAuth plugin now supports 2-legged OAuth
855
+
856
+ ## 2.8.6 - 2012-09-05
857
+
858
+ * Added the ability to modify and build service descriptions
859
+ * Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command
860
+ * Added a `json` parameter location
861
+ * Now allowing dot notation for classes in the CacheAdapterFactory
862
+ * Using the union of two arrays rather than an array_merge when extending service builder services and service params
863
+ * Ensuring that a service is a string before doing strpos() checks on it when substituting services for references
864
+ in service builder config files.
865
+ * Services defined in two different config files that include one another will by default replace the previously
866
+ defined service, but you can now create services that extend themselves and merge their settings over the previous
867
+ * The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like
868
+ '_default' with a default JSON configuration file.
869
+
870
+ ## 2.8.5 - 2012-08-29
871
+
872
+ * Bug: Suppressed empty arrays from URI templates
873
+ * Bug: Added the missing $options argument from ServiceDescription::factory to enable caching
874
+ * Added support for HTTP responses that do not contain a reason phrase in the start-line
875
+ * AbstractCommand commands are now invokable
876
+ * Added a way to get the data used when signing an Oauth request before a request is sent
877
+
878
+ ## 2.8.4 - 2012-08-15
879
+
880
+ * Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin
881
+ * Added the ability to transfer entity bodies as a string rather than streamed. This gets around curl error 65. Set `body_as_string` in a request's curl options to enable.
882
+ * Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\Common\Stream
883
+ * Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream
884
+ * Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5())
885
+ * Added additional response status codes
886
+ * Removed SSL information from the default User-Agent header
887
+ * DELETE requests can now send an entity body
888
+ * Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries
889
+ * Added the ability of the MockPlugin to consume mocked request bodies
890
+ * LogPlugin now exposes request and response objects in the extras array
891
+
892
+ ## 2.8.3 - 2012-07-30
893
+
894
+ * Bug: Fixed a case where empty POST requests were sent as GET requests
895
+ * Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body
896
+ * Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new
897
+ * Added multiple inheritance to service description commands
898
+ * Added an ApiCommandInterface and added `getParamNames()` and `hasParam()`
899
+ * Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything
900
+ * Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles
901
+
902
+ ## 2.8.2 - 2012-07-24
903
+
904
+ * Bug: Query string values set to 0 are no longer dropped from the query string
905
+ * Bug: A Collection object is no longer created each time a call is made to `Guzzle\Service\Command\AbstractCommand::getRequestHeaders()`
906
+ * Bug: `+` is now treated as an encoded space when parsing query strings
907
+ * QueryString and Collection performance improvements
908
+ * Allowing dot notation for class paths in filters attribute of a service descriptions
909
+
910
+ ## 2.8.1 - 2012-07-16
911
+
912
+ * Loosening Event Dispatcher dependency
913
+ * POST redirects can now be customized using CURLOPT_POSTREDIR
914
+
915
+ ## 2.8.0 - 2012-07-15
916
+
917
+ * BC: Guzzle\Http\Query
918
+ * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl)
919
+ * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding()
920
+ * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool)
921
+ * Changed the aggregation functions of QueryString to be static methods
922
+ * Can now use fromString() with querystrings that have a leading ?
923
+ * cURL configuration values can be specified in service descriptions using `curl.` prefixed parameters
924
+ * Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body
925
+ * Cookies are no longer URL decoded by default
926
+ * Bug: URI template variables set to null are no longer expanded
927
+
928
+ ## 2.7.2 - 2012-07-02
929
+
930
+ * BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\Http\Parser to Guzzle\Parser.
931
+ * BC: Removing Guzzle\Common\Batch\Batch::count() and replacing it with isEmpty()
932
+ * CachePlugin now allows for a custom request parameter function to check if a request can be cached
933
+ * Bug fix: CachePlugin now only caches GET and HEAD requests by default
934
+ * Bug fix: Using header glue when transferring headers over the wire
935
+ * Allowing deeply nested arrays for composite variables in URI templates
936
+ * Batch divisors can now return iterators or arrays
937
+
938
+ ## 2.7.1 - 2012-06-26
939
+
940
+ * Minor patch to update version number in UA string
941
+ * Updating build process
942
+
943
+ ## 2.7.0 - 2012-06-25
944
+
945
+ * BC: Inflection classes moved to Guzzle\Inflection. No longer static methods. Can now inject custom inflectors into classes.
946
+ * BC: Removed magic setX methods from commands
947
+ * BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method
948
+ * Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable.
949
+ * Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity)
950
+ * Guzzle\Service\Resource\ResourceIteratorApplyBatched now internally uses the Guzzle\Common\Batch namespace
951
+ * Added Guzzle\Service\Plugin namespace and a PluginCollectionPlugin
952
+ * Added the ability to set POST fields and files in a service description
953
+ * Guzzle\Http\EntityBody::factory() now accepts objects with a __toString() method
954
+ * Adding a command.before_prepare event to clients
955
+ * Added BatchClosureTransfer and BatchClosureDivisor
956
+ * BatchTransferException now includes references to the batch divisor and transfer strategies
957
+ * Fixed some tests so that they pass more reliably
958
+ * Added Guzzle\Common\Log\ArrayLogAdapter
959
+
960
+ ## 2.6.6 - 2012-06-10
961
+
962
+ * BC: Removing Guzzle\Http\Plugin\BatchQueuePlugin
963
+ * BC: Removing Guzzle\Service\Command\CommandSet
964
+ * Adding generic batching system (replaces the batch queue plugin and command set)
965
+ * Updating ZF cache and log adapters and now using ZF's composer repository
966
+ * Bug: Setting the name of each ApiParam when creating through an ApiCommand
967
+ * Adding result_type, result_doc, deprecated, and doc_url to service descriptions
968
+ * Bug: Changed the default cookie header casing back to 'Cookie'
969
+
970
+ ## 2.6.5 - 2012-06-03
971
+
972
+ * BC: Renaming Guzzle\Http\Message\RequestInterface::getResourceUri() to getResource()
973
+ * BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from
974
+ * BC: Guzzle\Http\Cookie is now used to manage Set-Cookie data, not Cookie data
975
+ * BC: Renaming methods in the CookieJarInterface
976
+ * Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations
977
+ * Making the default glue for HTTP headers ';' instead of ','
978
+ * Adding a removeValue to Guzzle\Http\Message\Header
979
+ * Adding getCookies() to request interface.
980
+ * Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber()
981
+
982
+ ## 2.6.4 - 2012-05-30
983
+
984
+ * BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class.
985
+ * BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand
986
+ * Bug: Fixing magic method command calls on clients
987
+ * Bug: Email constraint only validates strings
988
+ * Bug: Aggregate POST fields when POST files are present in curl handle
989
+ * Bug: Fixing default User-Agent header
990
+ * Bug: Only appending or prepending parameters in commands if they are specified
991
+ * Bug: Not requiring response reason phrases or status codes to match a predefined list of codes
992
+ * Allowing the use of dot notation for class namespaces when using instance_of constraint
993
+ * Added any_match validation constraint
994
+ * Added an AsyncPlugin
995
+ * Passing request object to the calculateWait method of the ExponentialBackoffPlugin
996
+ * Allowing the result of a command object to be changed
997
+ * Parsing location and type sub values when instantiating a service description rather than over and over at runtime
998
+
999
+ ## 2.6.3 - 2012-05-23
1000
+
1001
+ * [BC] Guzzle\Common\FromConfigInterface no longer requires any config options.
1002
+ * [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields.
1003
+ * You can now use an array of data when creating PUT request bodies in the request factory.
1004
+ * Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable.
1005
+ * [Http] Adding support for Content-Type in multipart POST uploads per upload
1006
+ * [Http] Added support for uploading multiple files using the same name (foo[0], foo[1])
1007
+ * Adding more POST data operations for easier manipulation of POST data.
1008
+ * You can now set empty POST fields.
1009
+ * The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files.
1010
+ * Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate.
1011
+ * CS updates
1012
+
1013
+ ## 2.6.2 - 2012-05-19
1014
+
1015
+ * [Http] Better handling of nested scope requests in CurlMulti. Requests are now always prepares in the send() method rather than the addRequest() method.
1016
+
1017
+ ## 2.6.1 - 2012-05-19
1018
+
1019
+ * [BC] Removing 'path' support in service descriptions. Use 'uri'.
1020
+ * [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache.
1021
+ * [BC] Removing Guzzle\Common\NullObject. Use https://github.com/mtdowling/NullObject if you need it.
1022
+ * [BC] Removing Guzzle\Common\XmlElement.
1023
+ * All commands, both dynamic and concrete, have ApiCommand objects.
1024
+ * Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits.
1025
+ * Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored.
1026
+ * Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible.
1027
+
1028
+ ## 2.6.0 - 2012-05-15
1029
+
1030
+ * [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder
1031
+ * [BC] Executing a Command returns the result of the command rather than the command
1032
+ * [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed.
1033
+ * [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args.
1034
+ * [BC] Moving ResourceIterator* to Guzzle\Service\Resource
1035
+ * [BC] Completely refactored ResourceIterators to iterate over a cloned command object
1036
+ * [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate
1037
+ * [BC] Guzzle\Guzzle is now deprecated
1038
+ * Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject
1039
+ * Adding Guzzle\Version class to give version information about Guzzle
1040
+ * Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate()
1041
+ * Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data
1042
+ * ServiceDescription and ServiceBuilder are now cacheable using similar configs
1043
+ * Changing the format of XML and JSON service builder configs. Backwards compatible.
1044
+ * Cleaned up Cookie parsing
1045
+ * Trimming the default Guzzle User-Agent header
1046
+ * Adding a setOnComplete() method to Commands that is called when a command completes
1047
+ * Keeping track of requests that were mocked in the MockPlugin
1048
+ * Fixed a caching bug in the CacheAdapterFactory
1049
+ * Inspector objects can be injected into a Command object
1050
+ * Refactoring a lot of code and tests to be case insensitive when dealing with headers
1051
+ * Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL
1052
+ * Adding the ability to set global option overrides to service builder configs
1053
+ * Adding the ability to include other service builder config files from within XML and JSON files
1054
+ * Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method.
1055
+
1056
+ ## 2.5.0 - 2012-05-08
1057
+
1058
+ * Major performance improvements
1059
+ * [BC] Simplifying Guzzle\Common\Collection. Please check to see if you are using features that are now deprecated.
1060
+ * [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component.
1061
+ * [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates. Use "{}"
1062
+ * Added the ability to passed parameters to all requests created by a client
1063
+ * Added callback functionality to the ExponentialBackoffPlugin
1064
+ * Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies.
1065
+ * Rewinding request stream bodies when retrying requests
1066
+ * Exception is thrown when JSON response body cannot be decoded
1067
+ * Added configurable magic method calls to clients and commands. This is off by default.
1068
+ * Fixed a defect that added a hash to every parsed URL part
1069
+ * Fixed duplicate none generation for OauthPlugin.
1070
+ * Emitting an event each time a client is generated by a ServiceBuilder
1071
+ * Using an ApiParams object instead of a Collection for parameters of an ApiCommand
1072
+ * cache.* request parameters should be renamed to params.cache.*
1073
+ * Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle.
1074
+ * Added the ability to disable type validation of service descriptions
1075
+ * ServiceDescriptions and ServiceBuilders are now Serializable
vendor/guzzlehttp/guzzle/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2011-2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/guzzle/README.md ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Guzzle, PHP HTTP client and webservice framework
2
+ ================================================
3
+
4
+ [![Build Status](https://secure.travis-ci.org/guzzle/guzzle.svg?branch=master)](http://travis-ci.org/guzzle/guzzle)
5
+
6
+ Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
7
+ trivial to integrate with web services.
8
+
9
+ - Manages things like persistent connections, represents query strings as
10
+ collections, simplifies sending streaming POST requests with fields and
11
+ files, and abstracts away the underlying HTTP transport layer.
12
+ - Can send both synchronous and asynchronous requests using the same interface
13
+ without requiring a dependency on a specific event loop.
14
+ - Pluggable HTTP adapters allows Guzzle to integrate with any method you choose
15
+ for sending HTTP requests over the wire (e.g., cURL, sockets, PHP's stream
16
+ wrapper, non-blocking event loops like ReactPHP.
17
+ - Guzzle makes it so that you no longer need to fool around with cURL options,
18
+ stream contexts, or sockets.
19
+
20
+ ```php
21
+ $client = new GuzzleHttp\Client();
22
+ $response = $client->get('http://guzzlephp.org');
23
+ $res = $client->get('https://api.github.com/user', ['auth' => ['user', 'pass']]);
24
+ echo $res->getStatusCode();
25
+ // "200"
26
+ echo $res->getHeader('content-type');
27
+ // 'application/json; charset=utf8'
28
+ echo $res->getBody();
29
+ // {"type":"User"...'
30
+ var_export($res->json());
31
+ // Outputs the JSON decoded data
32
+
33
+ // Send an asynchronous request.
34
+ $req = $client->createRequest('GET', 'http://httpbin.org', ['future' => true]);
35
+ $client->send($req)->then(function ($response) {
36
+ echo 'I completed! ' . $response;
37
+ });
38
+ ```
39
+
40
+ Get more information and answers with the
41
+ [Documentation](http://guzzlephp.org/),
42
+ [Forums](https://groups.google.com/forum/?hl=en#!forum/guzzle),
43
+ and [Gitter](https://gitter.im/guzzle/guzzle).
44
+
45
+ ### Installing via Composer
46
+
47
+ The recommended way to install Guzzle is through
48
+ [Composer](http://getcomposer.org).
49
+
50
+ ```bash
51
+ # Install Composer
52
+ curl -sS https://getcomposer.org/installer | php
53
+ ```
54
+
55
+ Next, run the Composer command to install the latest stable version of Guzzle:
56
+
57
+ ```bash
58
+ composer.phar require guzzlehttp/guzzle
59
+ ```
60
+
61
+ After installing, you need to require Composer's autoloader:
62
+
63
+ ```php
64
+ require 'vendor/autoload.php';
65
+ ```
66
+
67
+ ### Documentation
68
+
69
+ More information can be found in the online documentation at
70
+ http://guzzlephp.org/.
vendor/guzzlehttp/guzzle/UPGRADING.md ADDED
@@ -0,0 +1,1050 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Guzzle Upgrade Guide
2
+ ====================
3
+
4
+ 4.x to 5.0
5
+ ----------
6
+
7
+ ## Rewritten Adapter Layer
8
+
9
+ Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send
10
+ HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor
11
+ is still supported, but it has now been renamed to `handler`. Instead of
12
+ passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP
13
+ `callable` that follows the RingPHP specification.
14
+
15
+ ## Removed Fluent Interfaces
16
+
17
+ [Fluent interfaces were removed](http://ocramius.github.io/blog/fluent-interfaces-are-evil)
18
+ from the following classes:
19
+
20
+ - `GuzzleHttp\Collection`
21
+ - `GuzzleHttp\Url`
22
+ - `GuzzleHttp\Query`
23
+ - `GuzzleHttp\Post\PostBody`
24
+ - `GuzzleHttp\Cookie\SetCookie`
25
+
26
+ ## Removed functions.php
27
+
28
+ Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following
29
+ functions can be used as replacements.
30
+
31
+ - `GuzzleHttp\json_decode` -> `GuzzleHttp\Utils::jsonDecode`
32
+ - `GuzzleHttp\get_path` -> `GuzzleHttp\Utils::getPath`
33
+ - `GuzzleHttp\Utils::setPath` -> `GuzzleHttp\set_path`
34
+ - `GuzzleHttp\Pool::batch` -> `GuzzleHttp\batch`. This function is, however,
35
+ deprecated in favor of using `GuzzleHttp\Pool::batch()`.
36
+
37
+ The "procedural" global client has been removed with no replacement (e.g.,
38
+ `GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client`
39
+ object as a replacement.
40
+
41
+ ## `throwImmediately` has been removed
42
+
43
+ The concept of "throwImmediately" has been removed from exceptions and error
44
+ events. This control mechanism was used to stop a transfer of concurrent
45
+ requests from completing. This can now be handled by throwing the exception or
46
+ by cancelling a pool of requests or each outstanding future request
47
+ individually.
48
+
49
+ ## headers event has been removed
50
+
51
+ Removed the "headers" event. This event was only useful for changing the
52
+ body a response once the headers of the response were known. You can implement
53
+ a similar behavior in a number of ways. One example might be to use a
54
+ FnStream that has access to the transaction being sent. For example, when the
55
+ first byte is written, you could check if the response headers match your
56
+ expectations, and if so, change the actual stream body that is being
57
+ written to.
58
+
59
+ ## Updates to HTTP Messages
60
+
61
+ Removed the `asArray` parameter from
62
+ `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
63
+ value as an array, then use the newly added `getHeaderAsArray()` method of
64
+ `MessageInterface`. This change makes the Guzzle interfaces compatible with
65
+ the PSR-7 interfaces.
66
+
67
+ 3.x to 4.0
68
+ ----------
69
+
70
+ ## Overarching changes:
71
+
72
+ - Now requires PHP 5.4 or greater.
73
+ - No longer requires cURL to send requests.
74
+ - Guzzle no longer wraps every exception it throws. Only exceptions that are
75
+ recoverable are now wrapped by Guzzle.
76
+ - Various namespaces have been removed or renamed.
77
+ - No longer requiring the Symfony EventDispatcher. A custom event dispatcher
78
+ based on the Symfony EventDispatcher is
79
+ now utilized in `GuzzleHttp\Event\EmitterInterface` (resulting in significant
80
+ speed and functionality improvements).
81
+
82
+ Changes per Guzzle 3.x namespace are described below.
83
+
84
+ ## Batch
85
+
86
+ The `Guzzle\Batch` namespace has been removed. This is best left to
87
+ third-parties to implement on top of Guzzle's core HTTP library.
88
+
89
+ ## Cache
90
+
91
+ The `Guzzle\Cache` namespace has been removed. (Todo: No suitable replacement
92
+ has been implemented yet, but hoping to utilize a PSR cache interface).
93
+
94
+ ## Common
95
+
96
+ - Removed all of the wrapped exceptions. It's better to use the standard PHP
97
+ library for unrecoverable exceptions.
98
+ - `FromConfigInterface` has been removed.
99
+ - `Guzzle\Common\Version` has been removed. The VERSION constant can be found
100
+ at `GuzzleHttp\ClientInterface::VERSION`.
101
+
102
+ ### Collection
103
+
104
+ - `getAll` has been removed. Use `toArray` to convert a collection to an array.
105
+ - `inject` has been removed.
106
+ - `keySearch` has been removed.
107
+ - `getPath` no longer supports wildcard expressions. Use something better like
108
+ JMESPath for this.
109
+ - `setPath` now supports appending to an existing array via the `[]` notation.
110
+
111
+ ### Events
112
+
113
+ Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses
114
+ `GuzzleHttp\Event\Emitter`.
115
+
116
+ - `Symfony\Component\EventDispatcher\EventDispatcherInterface` is replaced by
117
+ `GuzzleHttp\Event\EmitterInterface`.
118
+ - `Symfony\Component\EventDispatcher\EventDispatcher` is replaced by
119
+ `GuzzleHttp\Event\Emitter`.
120
+ - `Symfony\Component\EventDispatcher\Event` is replaced by
121
+ `GuzzleHttp\Event\Event`, and Guzzle now has an EventInterface in
122
+ `GuzzleHttp\Event\EventInterface`.
123
+ - `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and
124
+ `HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the
125
+ event emitter of a request, client, etc. now uses the `getEmitter` method
126
+ rather than the `getDispatcher` method.
127
+
128
+ #### Emitter
129
+
130
+ - Use the `once()` method to add a listener that automatically removes itself
131
+ the first time it is invoked.
132
+ - Use the `listeners()` method to retrieve a list of event listeners rather than
133
+ the `getListeners()` method.
134
+ - Use `emit()` instead of `dispatch()` to emit an event from an emitter.
135
+ - Use `attach()` instead of `addSubscriber()` and `detach()` instead of
136
+ `removeSubscriber()`.
137
+
138
+ ```php
139
+ $mock = new Mock();
140
+ // 3.x
141
+ $request->getEventDispatcher()->addSubscriber($mock);
142
+ $request->getEventDispatcher()->removeSubscriber($mock);
143
+ // 4.x
144
+ $request->getEmitter()->attach($mock);
145
+ $request->getEmitter()->detach($mock);
146
+ ```
147
+
148
+ Use the `on()` method to add a listener rather than the `addListener()` method.
149
+
150
+ ```php
151
+ // 3.x
152
+ $request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } );
153
+ // 4.x
154
+ $request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } );
155
+ ```
156
+
157
+ ## Http
158
+
159
+ ### General changes
160
+
161
+ - The cacert.pem certificate has been moved to `src/cacert.pem`.
162
+ - Added the concept of adapters that are used to transfer requests over the
163
+ wire.
164
+ - Simplified the event system.
165
+ - Sending requests in parallel is still possible, but batching is no longer a
166
+ concept of the HTTP layer. Instead, you must use the `complete` and `error`
167
+ events to asynchronously manage parallel request transfers.
168
+ - `Guzzle\Http\Url` has moved to `GuzzleHttp\Url`.
169
+ - `Guzzle\Http\QueryString` has moved to `GuzzleHttp\Query`.
170
+ - QueryAggregators have been rewritten so that they are simply callable
171
+ functions.
172
+ - `GuzzleHttp\StaticClient` has been removed. Use the functions provided in
173
+ `functions.php` for an easy to use static client instance.
174
+ - Exceptions in `GuzzleHttp\Exception` have been updated to all extend from
175
+ `GuzzleHttp\Exception\TransferException`.
176
+
177
+ ### Client
178
+
179
+ Calling methods like `get()`, `post()`, `head()`, etc. no longer create and
180
+ return a request, but rather creates a request, sends the request, and returns
181
+ the response.
182
+
183
+ ```php
184
+ // 3.0
185
+ $request = $client->get('/');
186
+ $response = $request->send();
187
+
188
+ // 4.0
189
+ $response = $client->get('/');
190
+
191
+ // or, to mirror the previous behavior
192
+ $request = $client->createRequest('GET', '/');
193
+ $response = $client->send($request);
194
+ ```
195
+
196
+ `GuzzleHttp\ClientInterface` has changed.
197
+
198
+ - The `send` method no longer accepts more than one request. Use `sendAll` to
199
+ send multiple requests in parallel.
200
+ - `setUserAgent()` has been removed. Use a default request option instead. You
201
+ could, for example, do something like:
202
+ `$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`.
203
+ - `setSslVerification()` has been removed. Use default request options instead,
204
+ like `$client->setConfig('defaults/verify', true)`.
205
+
206
+ `GuzzleHttp\Client` has changed.
207
+
208
+ - The constructor now accepts only an associative array. You can include a
209
+ `base_url` string or array to use a URI template as the base URL of a client.
210
+ You can also specify a `defaults` key that is an associative array of default
211
+ request options. You can pass an `adapter` to use a custom adapter,
212
+ `batch_adapter` to use a custom adapter for sending requests in parallel, or
213
+ a `message_factory` to change the factory used to create HTTP requests and
214
+ responses.
215
+ - The client no longer emits a `client.create_request` event.
216
+ - Creating requests with a client no longer automatically utilize a URI
217
+ template. You must pass an array into a creational method (e.g.,
218
+ `createRequest`, `get`, `put`, etc.) in order to expand a URI template.
219
+
220
+ ### Messages
221
+
222
+ Messages no longer have references to their counterparts (i.e., a request no
223
+ longer has a reference to it's response, and a response no loger has a
224
+ reference to its request). This association is now managed through a
225
+ `GuzzleHttp\Adapter\TransactionInterface` object. You can get references to
226
+ these transaction objects using request events that are emitted over the
227
+ lifecycle of a request.
228
+
229
+ #### Requests with a body
230
+
231
+ - `GuzzleHttp\Message\EntityEnclosingRequest` and
232
+ `GuzzleHttp\Message\EntityEnclosingRequestInterface` have been removed. The
233
+ separation between requests that contain a body and requests that do not
234
+ contain a body has been removed, and now `GuzzleHttp\Message\RequestInterface`
235
+ handles both use cases.
236
+ - Any method that previously accepts a `GuzzleHttp\Response` object now accept a
237
+ `GuzzleHttp\Message\ResponseInterface`.
238
+ - `GuzzleHttp\Message\RequestFactoryInterface` has been renamed to
239
+ `GuzzleHttp\Message\MessageFactoryInterface`. This interface is used to create
240
+ both requests and responses and is implemented in
241
+ `GuzzleHttp\Message\MessageFactory`.
242
+ - POST field and file methods have been removed from the request object. You
243
+ must now use the methods made available to `GuzzleHttp\Post\PostBodyInterface`
244
+ to control the format of a POST body. Requests that are created using a
245
+ standard `GuzzleHttp\Message\MessageFactoryInterface` will automatically use
246
+ a `GuzzleHttp\Post\PostBody` body if the body was passed as an array or if
247
+ the method is POST and no body is provided.
248
+
249
+ ```php
250
+ $request = $client->createRequest('POST', '/');
251
+ $request->getBody()->setField('foo', 'bar');
252
+ $request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r')));
253
+ ```
254
+
255
+ #### Headers
256
+
257
+ - `GuzzleHttp\Message\Header` has been removed. Header values are now simply
258
+ represented by an array of values or as a string. Header values are returned
259
+ as a string by default when retrieving a header value from a message. You can
260
+ pass an optional argument of `true` to retrieve a header value as an array
261
+ of strings instead of a single concatenated string.
262
+ - `GuzzleHttp\PostFile` and `GuzzleHttp\PostFileInterface` have been moved to
263
+ `GuzzleHttp\Post`. This interface has been simplified and now allows the
264
+ addition of arbitrary headers.
265
+ - Custom headers like `GuzzleHttp\Message\Header\Link` have been removed. Most
266
+ of the custom headers are now handled separately in specific
267
+ subscribers/plugins, and `GuzzleHttp\Message\HeaderValues::parseParams()` has
268
+ been updated to properly handle headers that contain parameters (like the
269
+ `Link` header).
270
+
271
+ #### Responses
272
+
273
+ - `GuzzleHttp\Message\Response::getInfo()` and
274
+ `GuzzleHttp\Message\Response::setInfo()` have been removed. Use the event
275
+ system to retrieve this type of information.
276
+ - `GuzzleHttp\Message\Response::getRawHeaders()` has been removed.
277
+ - `GuzzleHttp\Message\Response::getMessage()` has been removed.
278
+ - `GuzzleHttp\Message\Response::calculateAge()` and other cache specific
279
+ methods have moved to the CacheSubscriber.
280
+ - Header specific helper functions like `getContentMd5()` have been removed.
281
+ Just use `getHeader('Content-MD5')` instead.
282
+ - `GuzzleHttp\Message\Response::setRequest()` and
283
+ `GuzzleHttp\Message\Response::getRequest()` have been removed. Use the event
284
+ system to work with request and response objects as a transaction.
285
+ - `GuzzleHttp\Message\Response::getRedirectCount()` has been removed. Use the
286
+ Redirect subscriber instead.
287
+ - `GuzzleHttp\Message\Response::isSuccessful()` and other related methods have
288
+ been removed. Use `getStatusCode()` instead.
289
+
290
+ #### Streaming responses
291
+
292
+ Streaming requests can now be created by a client directly, returning a
293
+ `GuzzleHttp\Message\ResponseInterface` object that contains a body stream
294
+ referencing an open PHP HTTP stream.
295
+
296
+ ```php
297
+ // 3.0
298
+ use Guzzle\Stream\PhpStreamRequestFactory;
299
+ $request = $client->get('/');
300
+ $factory = new PhpStreamRequestFactory();
301
+ $stream = $factory->fromRequest($request);
302
+ $data = $stream->read(1024);
303
+
304
+ // 4.0
305
+ $response = $client->get('/', ['stream' => true]);
306
+ // Read some data off of the stream in the response body
307
+ $data = $response->getBody()->read(1024);
308
+ ```
309
+
310
+ #### Redirects
311
+
312
+ The `configureRedirects()` method has been removed in favor of a
313
+ `allow_redirects` request option.
314
+
315
+ ```php
316
+ // Standard redirects with a default of a max of 5 redirects
317
+ $request = $client->createRequest('GET', '/', ['allow_redirects' => true]);
318
+
319
+ // Strict redirects with a custom number of redirects
320
+ $request = $client->createRequest('GET', '/', [
321
+ 'allow_redirects' => ['max' => 5, 'strict' => true]
322
+ ]);
323
+ ```
324
+
325
+ #### EntityBody
326
+
327
+ EntityBody interfaces and classes have been removed or moved to
328
+ `GuzzleHttp\Stream`. All classes and interfaces that once required
329
+ `GuzzleHttp\EntityBodyInterface` now require
330
+ `GuzzleHttp\Stream\StreamInterface`. Creating a new body for a request no
331
+ longer uses `GuzzleHttp\EntityBody::factory` but now uses
332
+ `GuzzleHttp\Stream\Stream::factory` or even better:
333
+ `GuzzleHttp\Stream\create()`.
334
+
335
+ - `Guzzle\Http\EntityBodyInterface` is now `GuzzleHttp\Stream\StreamInterface`
336
+ - `Guzzle\Http\EntityBody` is now `GuzzleHttp\Stream\Stream`
337
+ - `Guzzle\Http\CachingEntityBody` is now `GuzzleHttp\Stream\CachingStream`
338
+ - `Guzzle\Http\ReadLimitEntityBody` is now `GuzzleHttp\Stream\LimitStream`
339
+ - `Guzzle\Http\IoEmittyinEntityBody` has been removed.
340
+
341
+ #### Request lifecycle events
342
+
343
+ Requests previously submitted a large number of requests. The number of events
344
+ emitted over the lifecycle of a request has been significantly reduced to make
345
+ it easier to understand how to extend the behavior of a request. All events
346
+ emitted during the lifecycle of a request now emit a custom
347
+ `GuzzleHttp\Event\EventInterface` object that contains context providing
348
+ methods and a way in which to modify the transaction at that specific point in
349
+ time (e.g., intercept the request and set a response on the transaction).
350
+
351
+ - `request.before_send` has been renamed to `before` and now emits a
352
+ `GuzzleHttp\Event\BeforeEvent`
353
+ - `request.complete` has been renamed to `complete` and now emits a
354
+ `GuzzleHttp\Event\CompleteEvent`.
355
+ - `request.sent` has been removed. Use `complete`.
356
+ - `request.success` has been removed. Use `complete`.
357
+ - `error` is now an event that emits a `GuzzleHttp\Event\ErrorEvent`.
358
+ - `request.exception` has been removed. Use `error`.
359
+ - `request.receive.status_line` has been removed.
360
+ - `curl.callback.progress` has been removed. Use a custom `StreamInterface` to
361
+ maintain a status update.
362
+ - `curl.callback.write` has been removed. Use a custom `StreamInterface` to
363
+ intercept writes.
364
+ - `curl.callback.read` has been removed. Use a custom `StreamInterface` to
365
+ intercept reads.
366
+
367
+ `headers` is a new event that is emitted after the response headers of a
368
+ request have been received before the body of the response is downloaded. This
369
+ event emits a `GuzzleHttp\Event\HeadersEvent`.
370
+
371
+ You can intercept a request and inject a response using the `intercept()` event
372
+ of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and
373
+ `GuzzleHttp\Event\ErrorEvent` event.
374
+
375
+ See: http://docs.guzzlephp.org/en/latest/events.html
376
+
377
+ ## Inflection
378
+
379
+ The `Guzzle\Inflection` namespace has been removed. This is not a core concern
380
+ of Guzzle.
381
+
382
+ ## Iterator
383
+
384
+ The `Guzzle\Iterator` namespace has been removed.
385
+
386
+ - `Guzzle\Iterator\AppendIterator`, `Guzzle\Iterator\ChunkedIterator`, and
387
+ `Guzzle\Iterator\MethodProxyIterator` are nice, but not a core requirement of
388
+ Guzzle itself.
389
+ - `Guzzle\Iterator\FilterIterator` is no longer needed because an equivalent
390
+ class is shipped with PHP 5.4.
391
+ - `Guzzle\Iterator\MapIterator` is not really needed when using PHP 5.5 because
392
+ it's easier to just wrap an iterator in a generator that maps values.
393
+
394
+ For a replacement of these iterators, see https://github.com/nikic/iter
395
+
396
+ ## Log
397
+
398
+ The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The
399
+ `Guzzle\Log` namespace has been removed. Guzzle now relies on
400
+ `Psr\Log\LoggerInterface` for all logging. The MessageFormatter class has been
401
+ moved to `GuzzleHttp\Subscriber\Log\Formatter`.
402
+
403
+ ## Parser
404
+
405
+ The `Guzzle\Parser` namespace has been removed. This was previously used to
406
+ make it possible to plug in custom parsers for cookies, messages, URI
407
+ templates, and URLs; however, this level of complexity is not needed in Guzzle
408
+ so it has been removed.
409
+
410
+ - Cookie: Cookie parsing logic has been moved to
411
+ `GuzzleHttp\Cookie\SetCookie::fromString`.
412
+ - Message: Message parsing logic for both requests and responses has been moved
413
+ to `GuzzleHttp\Message\MessageFactory::fromMessage`. Message parsing is only
414
+ used in debugging or deserializing messages, so it doesn't make sense for
415
+ Guzzle as a library to add this level of complexity to parsing messages.
416
+ - UriTemplate: URI template parsing has been moved to
417
+ `GuzzleHttp\UriTemplate`. The Guzzle library will automatically use the PECL
418
+ URI template library if it is installed.
419
+ - Url: URL parsing is now performed in `GuzzleHttp\Url::fromString` (previously
420
+ it was `Guzzle\Http\Url::factory()`). If custom URL parsing is necessary,
421
+ then developers are free to subclass `GuzzleHttp\Url`.
422
+
423
+ ## Plugin
424
+
425
+ The `Guzzle\Plugin` namespace has been renamed to `GuzzleHttp\Subscriber`.
426
+ Several plugins are shipping with the core Guzzle library under this namespace.
427
+
428
+ - `GuzzleHttp\Subscriber\Cookie`: Replaces the old CookiePlugin. Cookie jar
429
+ code has moved to `GuzzleHttp\Cookie`.
430
+ - `GuzzleHttp\Subscriber\History`: Replaces the old HistoryPlugin.
431
+ - `GuzzleHttp\Subscriber\HttpError`: Throws errors when a bad HTTP response is
432
+ received.
433
+ - `GuzzleHttp\Subscriber\Mock`: Replaces the old MockPlugin.
434
+ - `GuzzleHttp\Subscriber\Prepare`: Prepares the body of a request just before
435
+ sending. This subscriber is attached to all requests by default.
436
+ - `GuzzleHttp\Subscriber\Redirect`: Replaces the RedirectPlugin.
437
+
438
+ The following plugins have been removed (third-parties are free to re-implement
439
+ these if needed):
440
+
441
+ - `GuzzleHttp\Plugin\Async` has been removed.
442
+ - `GuzzleHttp\Plugin\CurlAuth` has been removed.
443
+ - `GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin` has been removed. This
444
+ functionality should instead be implemented with event listeners that occur
445
+ after normal response parsing occurs in the guzzle/command package.
446
+
447
+ The following plugins are not part of the core Guzzle package, but are provided
448
+ in separate repositories:
449
+
450
+ - `Guzzle\Http\Plugin\BackoffPlugin` has been rewritten to be muchs simpler
451
+ to build custom retry policies using simple functions rather than various
452
+ chained classes. See: https://github.com/guzzle/retry-subscriber
453
+ - `Guzzle\Http\Plugin\Cache\CachePlugin` has moved to
454
+ https://github.com/guzzle/cache-subscriber
455
+ - `Guzzle\Http\Plugin\Log\LogPlugin` has moved to
456
+ https://github.com/guzzle/log-subscriber
457
+ - `Guzzle\Http\Plugin\Md5\Md5Plugin` has moved to
458
+ https://github.com/guzzle/message-integrity-subscriber
459
+ - `Guzzle\Http\Plugin\Mock\MockPlugin` has moved to
460
+ `GuzzleHttp\Subscriber\MockSubscriber`.
461
+ - `Guzzle\Http\Plugin\Oauth\OauthPlugin` has moved to
462
+ https://github.com/guzzle/oauth-subscriber
463
+
464
+ ## Service
465
+
466
+ The service description layer of Guzzle has moved into two separate packages:
467
+
468
+ - http://github.com/guzzle/command Provides a high level abstraction over web
469
+ services by representing web service operations using commands.
470
+ - http://github.com/guzzle/guzzle-services Provides an implementation of
471
+ guzzle/command that provides request serialization and response parsing using
472
+ Guzzle service descriptions.
473
+
474
+ ## Stream
475
+
476
+ Stream have moved to a separate package available at
477
+ https://github.com/guzzle/streams.
478
+
479
+ `Guzzle\Stream\StreamInterface` has been given a large update to cleanly take
480
+ on the responsibilities of `Guzzle\Http\EntityBody` and
481
+ `Guzzle\Http\EntityBodyInterface` now that they have been removed. The number
482
+ of methods implemented by the `StreamInterface` has been drastically reduced to
483
+ allow developers to more easily extend and decorate stream behavior.
484
+
485
+ ## Removed methods from StreamInterface
486
+
487
+ - `getStream` and `setStream` have been removed to better encapsulate streams.
488
+ - `getMetadata` and `setMetadata` have been removed in favor of
489
+ `GuzzleHttp\Stream\MetadataStreamInterface`.
490
+ - `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been
491
+ removed. This data is accessible when
492
+ using streams that implement `GuzzleHttp\Stream\MetadataStreamInterface`.
493
+ - `rewind` has been removed. Use `seek(0)` for a similar behavior.
494
+
495
+ ## Renamed methods
496
+
497
+ - `detachStream` has been renamed to `detach`.
498
+ - `feof` has been renamed to `eof`.
499
+ - `ftell` has been renamed to `tell`.
500
+ - `readLine` has moved from an instance method to a static class method of
501
+ `GuzzleHttp\Stream\Stream`.
502
+
503
+ ## Metadata streams
504
+
505
+ `GuzzleHttp\Stream\MetadataStreamInterface` has been added to denote streams
506
+ that contain additional metadata accessible via `getMetadata()`.
507
+ `GuzzleHttp\Stream\StreamInterface::getMetadata` and
508
+ `GuzzleHttp\Stream\StreamInterface::setMetadata` have been removed.
509
+
510
+ ## StreamRequestFactory
511
+
512
+ The entire concept of the StreamRequestFactory has been removed. The way this
513
+ was used in Guzzle 3 broke the actual interface of sending streaming requests
514
+ (instead of getting back a Response, you got a StreamInterface). Streeaming
515
+ PHP requests are now implemented throught the `GuzzleHttp\Adapter\StreamAdapter`.
516
+
517
+ 3.6 to 3.7
518
+ ----------
519
+
520
+ ### Deprecations
521
+
522
+ - You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.:
523
+
524
+ ```php
525
+ \Guzzle\Common\Version::$emitWarnings = true;
526
+ ```
527
+
528
+ The following APIs and options have been marked as deprecated:
529
+
530
+ - Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead.
531
+ - Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
532
+ - Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
533
+ - Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
534
+ - Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
535
+ - Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
536
+ - Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
537
+ - Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
538
+ - Marked `Guzzle\Common\Collection::inject()` as deprecated.
539
+ - Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use
540
+ `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or
541
+ `$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));`
542
+
543
+ 3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational
544
+ request methods. When paired with a client's configuration settings, these options allow you to specify default settings
545
+ for various aspects of a request. Because these options make other previous configuration options redundant, several
546
+ configuration options and methods of a client and AbstractCommand have been deprecated.
547
+
548
+ - Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`.
549
+ - Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`.
550
+ - Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')`
551
+ - Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0
552
+
553
+ $command = $client->getCommand('foo', array(
554
+ 'command.headers' => array('Test' => '123'),
555
+ 'command.response_body' => '/path/to/file'
556
+ ));
557
+
558
+ // Should be changed to:
559
+
560
+ $command = $client->getCommand('foo', array(
561
+ 'command.request_options' => array(
562
+ 'headers' => array('Test' => '123'),
563
+ 'save_as' => '/path/to/file'
564
+ )
565
+ ));
566
+
567
+ ### Interface changes
568
+
569
+ Additions and changes (you will need to update any implementations or subclasses you may have created):
570
+
571
+ - Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
572
+ createRequest, head, delete, put, patch, post, options, prepareRequest
573
+ - Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
574
+ - Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
575
+ - Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
576
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
577
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
578
+ - Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
579
+ default `array()`
580
+ - Added `Guzzle\Stream\StreamInterface::isRepeatable`
581
+ - Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
582
+
583
+ The following methods were removed from interfaces. All of these methods are still available in the concrete classes
584
+ that implement them, but you should update your code to use alternative methods:
585
+
586
+ - Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
587
+ `$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
588
+ `$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or
589
+ `$client->setDefaultOption('headers/{header_name}', 'value')`. or
590
+ `$client->setDefaultOption('headers', array('header_name' => 'value'))`.
591
+ - Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`.
592
+ - Removed `Guzzle\Http\ClientInterface::expandTemplate()`. This is an implementation detail.
593
+ - Removed `Guzzle\Http\ClientInterface::setRequestFactory()`. This is an implementation detail.
594
+ - Removed `Guzzle\Http\ClientInterface::getCurlMulti()`. This is a very specific implementation detail.
595
+ - Removed `Guzzle\Http\Message\RequestInterface::canCache`. Use the CachePlugin.
596
+ - Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`. Use the HistoryPlugin.
597
+ - Removed `Guzzle\Http\Message\RequestInterface::isRedirect`. Use the HistoryPlugin.
598
+
599
+ ### Cache plugin breaking changes
600
+
601
+ - CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
602
+ CacheStorageInterface. These two objects and interface will be removed in a future version.
603
+ - Always setting X-cache headers on cached responses
604
+ - Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
605
+ - `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
606
+ $request, Response $response);`
607
+ - `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
608
+ - `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
609
+ - Added `CacheStorageInterface::purge($url)`
610
+ - `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
611
+ $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
612
+ CanCacheStrategyInterface $canCache = null)`
613
+ - Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
614
+
615
+ 3.5 to 3.6
616
+ ----------
617
+
618
+ * Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
619
+ * Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
620
+ * Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
621
+ For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader().
622
+ Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request.
623
+ * Specific header implementations can be created for complex headers. When a message creates a header, it uses a
624
+ HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
625
+ CacheControl header implementation.
626
+ * Moved getLinks() from Response to just be used on a Link header object.
627
+
628
+ If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the
629
+ HeaderInterface (e.g. toArray(), getAll(), etc.).
630
+
631
+ ### Interface changes
632
+
633
+ * Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
634
+ * Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
635
+ * Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
636
+ Guzzle\Http\Curl\RequestMediator
637
+ * Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
638
+ * Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
639
+ * Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
640
+
641
+ ### Removed deprecated functions
642
+
643
+ * Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
644
+ * Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
645
+
646
+ ### Deprecations
647
+
648
+ * The ability to case-insensitively search for header values
649
+ * Guzzle\Http\Message\Header::hasExactHeader
650
+ * Guzzle\Http\Message\Header::raw. Use getAll()
651
+ * Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
652
+ instead.
653
+
654
+ ### Other changes
655
+
656
+ * All response header helper functions return a string rather than mixing Header objects and strings inconsistently
657
+ * Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
658
+ directly via interfaces
659
+ * Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
660
+ but are a no-op until removed.
661
+ * Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
662
+ `Guzzle\Service\Command\ArrayCommandInterface`.
663
+ * Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
664
+ on a request while the request is still being transferred
665
+ * `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
666
+
667
+ 3.3 to 3.4
668
+ ----------
669
+
670
+ Base URLs of a client now follow the rules of http://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs.
671
+
672
+ 3.2 to 3.3
673
+ ----------
674
+
675
+ ### Response::getEtag() quote stripping removed
676
+
677
+ `Guzzle\Http\Message\Response::getEtag()` no longer strips quotes around the ETag response header
678
+
679
+ ### Removed `Guzzle\Http\Utils`
680
+
681
+ The `Guzzle\Http\Utils` class was removed. This class was only used for testing.
682
+
683
+ ### Stream wrapper and type
684
+
685
+ `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getStreamType()` are no longer converted to lowercase.
686
+
687
+ ### curl.emit_io became emit_io
688
+
689
+ Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the
690
+ 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
691
+
692
+ 3.1 to 3.2
693
+ ----------
694
+
695
+ ### CurlMulti is no longer reused globally
696
+
697
+ Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added
698
+ to a single client can pollute requests dispatched from other clients.
699
+
700
+ If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the
701
+ ServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is
702
+ created.
703
+
704
+ ```php
705
+ $multi = new Guzzle\Http\Curl\CurlMulti();
706
+ $builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json');
707
+ $builder->addListener('service_builder.create_client', function ($event) use ($multi) {
708
+ $event['client']->setCurlMulti($multi);
709
+ }
710
+ });
711
+ ```
712
+
713
+ ### No default path
714
+
715
+ URLs no longer have a default path value of '/' if no path was specified.
716
+
717
+ Before:
718
+
719
+ ```php
720
+ $request = $client->get('http://www.foo.com');
721
+ echo $request->getUrl();
722
+ // >> http://www.foo.com/
723
+ ```
724
+
725
+ After:
726
+
727
+ ```php
728
+ $request = $client->get('http://www.foo.com');
729
+ echo $request->getUrl();
730
+ // >> http://www.foo.com
731
+ ```
732
+
733
+ ### Less verbose BadResponseException
734
+
735
+ The exception message for `Guzzle\Http\Exception\BadResponseException` no longer contains the full HTTP request and
736
+ response information. You can, however, get access to the request and response object by calling `getRequest()` or
737
+ `getResponse()` on the exception object.
738
+
739
+ ### Query parameter aggregation
740
+
741
+ Multi-valued query parameters are no longer aggregated using a callback function. `Guzzle\Http\Query` now has a
742
+ setAggregator() method that accepts a `Guzzle\Http\QueryAggregator\QueryAggregatorInterface` object. This object is
743
+ responsible for handling the aggregation of multi-valued query string variables into a flattened hash.
744
+
745
+ 2.8 to 3.x
746
+ ----------
747
+
748
+ ### Guzzle\Service\Inspector
749
+
750
+ Change `\Guzzle\Service\Inspector::fromConfig` to `\Guzzle\Common\Collection::fromConfig`
751
+
752
+ **Before**
753
+
754
+ ```php
755
+ use Guzzle\Service\Inspector;
756
+
757
+ class YourClient extends \Guzzle\Service\Client
758
+ {
759
+ public static function factory($config = array())
760
+ {
761
+ $default = array();
762
+ $required = array('base_url', 'username', 'api_key');
763
+ $config = Inspector::fromConfig($config, $default, $required);
764
+
765
+ $client = new self(
766
+ $config->get('base_url'),
767
+ $config->get('username'),
768
+ $config->get('api_key')
769
+ );
770
+ $client->setConfig($config);
771
+
772
+ $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
773
+
774
+ return $client;
775
+ }
776
+ ```
777
+
778
+ **After**
779
+
780
+ ```php
781
+ use Guzzle\Common\Collection;
782
+
783
+ class YourClient extends \Guzzle\Service\Client
784
+ {
785
+ public static function factory($config = array())
786
+ {
787
+ $default = array();
788
+ $required = array('base_url', 'username', 'api_key');
789
+ $config = Collection::fromConfig($config, $default, $required);
790
+
791
+ $client = new self(
792
+ $config->get('base_url'),
793
+ $config->get('username'),
794
+ $config->get('api_key')
795
+ );
796
+ $client->setConfig($config);
797
+
798
+ $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
799
+
800
+ return $client;
801
+ }
802
+ ```
803
+
804
+ ### Convert XML Service Descriptions to JSON
805
+
806
+ **Before**
807
+
808
+ ```xml
809
+ <?xml version="1.0" encoding="UTF-8"?>
810
+ <client>
811
+ <commands>
812
+ <!-- Groups -->
813
+ <command name="list_groups" method="GET" uri="groups.json">
814
+ <doc>Get a list of groups</doc>
815
+ </command>
816
+ <command name="search_groups" method="GET" uri='search.json?query="{{query}} type:group"'>
817
+ <doc>Uses a search query to get a list of groups</doc>
818
+ <param name="query" type="string" required="true" />
819
+ </command>
820
+ <command name="create_group" method="POST" uri="groups.json">
821
+ <doc>Create a group</doc>
822
+ <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
823
+ <param name="Content-Type" location="header" static="application/json"/>
824
+ </command>
825
+ <command name="delete_group" method="DELETE" uri="groups/{{id}}.json">
826
+ <doc>Delete a group by ID</doc>
827
+ <param name="id" type="integer" required="true"/>
828
+ </command>
829
+ <command name="get_group" method="GET" uri="groups/{{id}}.json">
830
+ <param name="id" type="integer" required="true"/>
831
+ </command>
832
+ <command name="update_group" method="PUT" uri="groups/{{id}}.json">
833
+ <doc>Update a group</doc>
834
+ <param name="id" type="integer" required="true"/>
835
+ <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
836
+ <param name="Content-Type" location="header" static="application/json"/>
837
+ </command>
838
+ </commands>
839
+ </client>
840
+ ```
841
+
842
+ **After**
843
+
844
+ ```json
845
+ {
846
+ "name": "Zendesk REST API v2",
847
+ "apiVersion": "2012-12-31",
848
+ "description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users",
849
+ "operations": {
850
+ "list_groups": {
851
+ "httpMethod":"GET",
852
+ "uri": "groups.json",
853
+ "summary": "Get a list of groups"
854
+ },
855
+ "search_groups":{
856
+ "httpMethod":"GET",
857
+ "uri": "search.json?query=\"{query} type:group\"",
858
+ "summary": "Uses a search query to get a list of groups",
859
+ "parameters":{
860
+ "query":{
861
+ "location": "uri",
862
+ "description":"Zendesk Search Query",
863
+ "type": "string",
864
+ "required": true
865
+ }
866
+ }
867
+ },
868
+ "create_group": {
869
+ "httpMethod":"POST",
870
+ "uri": "groups.json",
871
+ "summary": "Create a group",
872
+ "parameters":{
873
+ "data": {
874
+ "type": "array",
875
+ "location": "body",
876
+ "description":"Group JSON",
877
+ "filters": "json_encode",
878
+ "required": true
879
+ },
880
+ "Content-Type":{
881
+ "type": "string",
882
+ "location":"header",
883
+ "static": "application/json"
884
+ }
885
+ }
886
+ },
887
+ "delete_group": {
888
+ "httpMethod":"DELETE",
889
+ "uri": "groups/{id}.json",
890
+ "summary": "Delete a group",
891
+ "parameters":{
892
+ "id":{
893
+ "location": "uri",
894
+ "description":"Group to delete by ID",
895
+ "type": "integer",
896
+ "required": true
897
+ }
898
+ }
899
+ },
900
+ "get_group": {
901
+ "httpMethod":"GET",
902
+ "uri": "groups/{id}.json",
903
+ "summary": "Get a ticket",
904
+ "parameters":{
905
+ "id":{
906
+ "location": "uri",
907
+ "description":"Group to get by ID",
908
+ "type": "integer",
909
+ "required": true
910
+ }
911
+ }
912
+ },
913
+ "update_group": {
914
+ "httpMethod":"PUT",
915
+ "uri": "groups/{id}.json",
916
+ "summary": "Update a group",
917
+ "parameters":{
918
+ "id": {
919
+ "location": "uri",
920
+ "description":"Group to update by ID",
921
+ "type": "integer",
922
+ "required": true
923
+ },
924
+ "data": {
925
+ "type": "array",
926
+ "location": "body",
927
+ "description":"Group JSON",
928
+ "filters": "json_encode",
929
+ "required": true
930
+ },
931
+ "Content-Type":{
932
+ "type": "string",
933
+ "location":"header",
934
+ "static": "application/json"
935
+ }
936
+ }
937
+ }
938
+ }
939
+ ```
940
+
941
+ ### Guzzle\Service\Description\ServiceDescription
942
+
943
+ Commands are now called Operations
944
+
945
+ **Before**
946
+
947
+ ```php
948
+ use Guzzle\Service\Description\ServiceDescription;
949
+
950
+ $sd = new ServiceDescription();
951
+ $sd->getCommands(); // @returns ApiCommandInterface[]
952
+ $sd->hasCommand($name);
953
+ $sd->getCommand($name); // @returns ApiCommandInterface|null
954
+ $sd->addCommand($command); // @param ApiCommandInterface $command
955
+ ```
956
+
957
+ **After**
958
+
959
+ ```php
960
+ use Guzzle\Service\Description\ServiceDescription;
961
+
962
+ $sd = new ServiceDescription();
963
+ $sd->getOperations(); // @returns OperationInterface[]
964
+ $sd->hasOperation($name);
965
+ $sd->getOperation($name); // @returns OperationInterface|null
966
+ $sd->addOperation($operation); // @param OperationInterface $operation
967
+ ```
968
+
969
+ ### Guzzle\Common\Inflection\Inflector
970
+
971
+ Namespace is now `Guzzle\Inflection\Inflector`
972
+
973
+ ### Guzzle\Http\Plugin
974
+
975
+ Namespace is now `Guzzle\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below.
976
+
977
+ ### Guzzle\Http\Plugin\LogPlugin and Guzzle\Common\Log
978
+
979
+ Now `Guzzle\Plugin\Log\LogPlugin` and `Guzzle\Log` respectively.
980
+
981
+ **Before**
982
+
983
+ ```php
984
+ use Guzzle\Common\Log\ClosureLogAdapter;
985
+ use Guzzle\Http\Plugin\LogPlugin;
986
+
987
+ /** @var \Guzzle\Http\Client */
988
+ $client;
989
+
990
+ // $verbosity is an integer indicating desired message verbosity level
991
+ $client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE);
992
+ ```
993
+
994
+ **After**
995
+
996
+ ```php
997
+ use Guzzle\Log\ClosureLogAdapter;
998
+ use Guzzle\Log\MessageFormatter;
999
+ use Guzzle\Plugin\Log\LogPlugin;
1000
+
1001
+ /** @var \Guzzle\Http\Client */
1002
+ $client;
1003
+
1004
+ // $format is a string indicating desired message format -- @see MessageFormatter
1005
+ $client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT);
1006
+ ```
1007
+
1008
+ ### Guzzle\Http\Plugin\CurlAuthPlugin
1009
+
1010
+ Now `Guzzle\Plugin\CurlAuth\CurlAuthPlugin`.
1011
+
1012
+ ### Guzzle\Http\Plugin\ExponentialBackoffPlugin
1013
+
1014
+ Now `Guzzle\Plugin\Backoff\BackoffPlugin`, and other changes.
1015
+
1016
+ **Before**
1017
+
1018
+ ```php
1019
+ use Guzzle\Http\Plugin\ExponentialBackoffPlugin;
1020
+
1021
+ $backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge(
1022
+ ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429)
1023
+ ));
1024
+
1025
+ $client->addSubscriber($backoffPlugin);
1026
+ ```
1027
+
1028
+ **After**
1029
+
1030
+ ```php
1031
+ use Guzzle\Plugin\Backoff\BackoffPlugin;
1032
+ use Guzzle\Plugin\Backoff\HttpBackoffStrategy;
1033
+
1034
+ // Use convenient factory method instead -- see implementation for ideas of what
1035
+ // you can do with chaining backoff strategies
1036
+ $backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge(
1037
+ HttpBackoffStrategy::getDefaultFailureCodes(), array(429)
1038
+ ));
1039
+ $client->addSubscriber($backoffPlugin);
1040
+ ```
1041
+
1042
+ ### Known Issues
1043
+
1044
+ #### [BUG] Accept-Encoding header behavior changed unintentionally.
1045
+
1046
+ (See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e)
1047
+
1048
+ In version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to
1049
+ properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen.
1050
+ See issue #217 for a workaround, or use a version containing the fix.
vendor/guzzlehttp/guzzle/composer.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "guzzlehttp/guzzle",
3
+ "type": "library",
4
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
5
+ "keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"],
6
+ "homepage": "http://guzzlephp.org/",
7
+ "license": "MIT",
8
+ "authors": [
9
+ {
10
+ "name": "Michael Dowling",
11
+ "email": "mtdowling@gmail.com",
12
+ "homepage": "https://github.com/mtdowling"
13
+ }
14
+ ],
15
+ "require": {
16
+ "php": ">=5.4.0",
17
+ "guzzlehttp/ringphp": "^1.1",
18
+ "react/promise": "^2.2"
19
+ },
20
+ "require-dev": {
21
+ "ext-curl": "*",
22
+ "phpunit/phpunit": "^4.0"
23
+ },
24
+ "autoload": {
25
+ "psr-4": {
26
+ "GuzzleHttp\\": "src/"
27
+ }
28
+ },
29
+ "autoload-dev": {
30
+ "psr-4": {
31
+ "GuzzleHttp\\Tests\\": "tests/"
32
+ }
33
+ },
34
+ "scripts": {
35
+ "test": "make test",
36
+ "test-ci": "make coverage"
37
+ }
38
+ }
vendor/guzzlehttp/guzzle/src/BatchResults.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Represents the result of a batch operation. This result container is
6
+ * iterable, countable, and you can can get a result by value using the
7
+ * getResult function.
8
+ *
9
+ * Successful results are anything other than exceptions. Failure results are
10
+ * exceptions.
11
+ *
12
+ * @package GuzzleHttp
13
+ */
14
+ class BatchResults implements \Countable, \IteratorAggregate, \ArrayAccess
15
+ {
16
+ private $hash;
17
+
18
+ /**
19
+ * @param \SplObjectStorage $hash Hash of key objects to result values.
20
+ */
21
+ public function __construct(\SplObjectStorage $hash)
22
+ {
23
+ $this->hash = $hash;
24
+ }
25
+
26
+ /**
27
+ * Get the keys that are available on the batch result.
28
+ *
29
+ * @return array
30
+ */
31
+ public function getKeys()
32
+ {
33
+ return iterator_to_array($this->hash);
34
+ }
35
+
36
+ /**
37
+ * Gets a result from the container for the given object. When getting
38
+ * results for a batch of requests, provide the request object.
39
+ *
40
+ * @param object $forObject Object to retrieve the result for.
41
+ *
42
+ * @return mixed|null
43
+ */
44
+ public function getResult($forObject)
45
+ {
46
+ return isset($this->hash[$forObject]) ? $this->hash[$forObject] : null;
47
+ }
48
+
49
+ /**
50
+ * Get an array of successful results.
51
+ *
52
+ * @return array
53
+ */
54
+ public function getSuccessful()
55
+ {
56
+ $results = [];
57
+ foreach ($this->hash as $key) {
58
+ if (!($this->hash[$key] instanceof \Exception)) {
59
+ $results[] = $this->hash[$key];
60
+ }
61
+ }
62
+
63
+ return $results;
64
+ }
65
+
66
+ /**
67
+ * Get an array of failed results.
68
+ *
69
+ * @return array
70
+ */
71
+ public function getFailures()
72
+ {
73
+ $results = [];
74
+ foreach ($this->hash as $key) {
75
+ if ($this->hash[$key] instanceof \Exception) {
76
+ $results[] = $this->hash[$key];
77
+ }
78
+ }
79
+
80
+ return $results;
81
+ }
82
+
83
+ /**
84
+ * Allows iteration over all batch result values.
85
+ *
86
+ * @return \ArrayIterator
87
+ */
88
+ public function getIterator()
89
+ {
90
+ $results = [];
91
+ foreach ($this->hash as $key) {
92
+ $results[] = $this->hash[$key];
93
+ }
94
+
95
+ return new \ArrayIterator($results);
96
+ }
97
+
98
+ /**
99
+ * Counts the number of elements in the batch result.
100
+ *
101
+ * @return int
102
+ */
103
+ public function count()
104
+ {
105
+ return count($this->hash);
106
+ }
107
+
108
+ /**
109
+ * Checks if the batch contains a specific numerical array index.
110
+ *
111
+ * @param int $key Index to access
112
+ *
113
+ * @return bool
114
+ */
115
+ public function offsetExists($key)
116
+ {
117
+ return $key < count($this->hash);
118
+ }
119
+
120
+ /**
121
+ * Allows access of the batch using a numerical array index.
122
+ *
123
+ * @param int $key Index to access.
124
+ *
125
+ * @return mixed|null
126
+ */
127
+ public function offsetGet($key)
128
+ {
129
+ $i = -1;
130
+ foreach ($this->hash as $obj) {
131
+ if ($key === ++$i) {
132
+ return $this->hash[$obj];
133
+ }
134
+ }
135
+
136
+ return null;
137
+ }
138
+
139
+ public function offsetUnset($key)
140
+ {
141
+ throw new \RuntimeException('Not implemented');
142
+ }
143
+
144
+ public function offsetSet($key, $value)
145
+ {
146
+ throw new \RuntimeException('Not implemented');
147
+ }
148
+ }
vendor/guzzlehttp/guzzle/src/Client.php ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Event\HasEmitterTrait;
5
+ use GuzzleHttp\Message\MessageFactory;
6
+ use GuzzleHttp\Message\MessageFactoryInterface;
7
+ use GuzzleHttp\Message\RequestInterface;
8
+ use GuzzleHttp\Message\FutureResponse;
9
+ use GuzzleHttp\Ring\Core;
10
+ use GuzzleHttp\Ring\Future\FutureInterface;
11
+ use GuzzleHttp\Exception\RequestException;
12
+ use React\Promise\FulfilledPromise;
13
+ use React\Promise\RejectedPromise;
14
+
15
+ /**
16
+ * HTTP client
17
+ */
18
+ class Client implements ClientInterface
19
+ {
20
+ use HasEmitterTrait;
21
+
22
+ /** @var MessageFactoryInterface Request factory used by the client */
23
+ private $messageFactory;
24
+
25
+ /** @var Url Base URL of the client */
26
+ private $baseUrl;
27
+
28
+ /** @var array Default request options */
29
+ private $defaults;
30
+
31
+ /** @var callable Request state machine */
32
+ private $fsm;
33
+
34
+ /**
35
+ * Clients accept an array of constructor parameters.
36
+ *
37
+ * Here's an example of creating a client using an URI template for the
38
+ * client's base_url and an array of default request options to apply
39
+ * to each request:
40
+ *
41
+ * $client = new Client([
42
+ * 'base_url' => [
43
+ * 'http://www.foo.com/{version}/',
44
+ * ['version' => '123']
45
+ * ],
46
+ * 'defaults' => [
47
+ * 'timeout' => 10,
48
+ * 'allow_redirects' => false,
49
+ * 'proxy' => '192.168.16.1:10'
50
+ * ]
51
+ * ]);
52
+ *
53
+ * @param array $config Client configuration settings
54
+ * - base_url: Base URL of the client that is merged into relative URLs.
55
+ * Can be a string or an array that contains a URI template followed
56
+ * by an associative array of expansion variables to inject into the
57
+ * URI template.
58
+ * - handler: callable RingPHP handler used to transfer requests
59
+ * - message_factory: Factory used to create request and response object
60
+ * - defaults: Default request options to apply to each request
61
+ * - emitter: Event emitter used for request events
62
+ * - fsm: (internal use only) The request finite state machine. A
63
+ * function that accepts a transaction and optional final state. The
64
+ * function is responsible for transitioning a request through its
65
+ * lifecycle events.
66
+ */
67
+ public function __construct(array $config = [])
68
+ {
69
+ $this->configureBaseUrl($config);
70
+ $this->configureDefaults($config);
71
+
72
+ if (isset($config['emitter'])) {
73
+ $this->emitter = $config['emitter'];
74
+ }
75
+
76
+ $this->messageFactory = isset($config['message_factory'])
77
+ ? $config['message_factory']
78
+ : new MessageFactory();
79
+
80
+ if (isset($config['fsm'])) {
81
+ $this->fsm = $config['fsm'];
82
+ } else {
83
+ if (isset($config['handler'])) {
84
+ $handler = $config['handler'];
85
+ } elseif (isset($config['adapter'])) {
86
+ $handler = $config['adapter'];
87
+ } else {
88
+ $handler = Utils::getDefaultHandler();
89
+ }
90
+ $this->fsm = new RequestFsm($handler, $this->messageFactory);
91
+ }
92
+ }
93
+
94
+ public function getDefaultOption($keyOrPath = null)
95
+ {
96
+ return $keyOrPath === null
97
+ ? $this->defaults
98
+ : Utils::getPath($this->defaults, $keyOrPath);
99
+ }
100
+
101
+ public function setDefaultOption($keyOrPath, $value)
102
+ {
103
+ Utils::setPath($this->defaults, $keyOrPath, $value);
104
+ }
105
+
106
+ public function getBaseUrl()
107
+ {
108
+ return (string) $this->baseUrl;
109
+ }
110
+
111
+ public function createRequest($method, $url = null, array $options = [])
112
+ {
113
+ $options = $this->mergeDefaults($options);
114
+ // Use a clone of the client's emitter
115
+ $options['config']['emitter'] = clone $this->getEmitter();
116
+ $url = $url || (is_string($url) && strlen($url))
117
+ ? $this->buildUrl($url)
118
+ : (string) $this->baseUrl;
119
+
120
+ return $this->messageFactory->createRequest($method, $url, $options);
121
+ }
122
+
123
+ public function get($url = null, $options = [])
124
+ {
125
+ return $this->send($this->createRequest('GET', $url, $options));
126
+ }
127
+
128
+ public function head($url = null, array $options = [])
129
+ {
130
+ return $this->send($this->createRequest('HEAD', $url, $options));
131
+ }
132
+
133
+ public function delete($url = null, array $options = [])
134
+ {
135
+ return $this->send($this->createRequest('DELETE', $url, $options));
136
+ }
137
+
138
+ public function put($url = null, array $options = [])
139
+ {
140
+ return $this->send($this->createRequest('PUT', $url, $options));
141
+ }
142
+
143
+ public function patch($url = null, array $options = [])
144
+ {
145
+ return $this->send($this->createRequest('PATCH', $url, $options));
146
+ }
147
+
148
+ public function post($url = null, array $options = [])
149
+ {
150
+ return $this->send($this->createRequest('POST', $url, $options));
151
+ }
152
+
153
+ public function options($url = null, array $options = [])
154
+ {
155
+ return $this->send($this->createRequest('OPTIONS', $url, $options));
156
+ }
157
+
158
+ public function send(RequestInterface $request)
159
+ {
160
+ $isFuture = $request->getConfig()->get('future');
161
+ $trans = new Transaction($this, $request, $isFuture);
162
+ $fn = $this->fsm;
163
+
164
+ try {
165
+ $fn($trans);
166
+ if ($isFuture) {
167
+ // Turn the normal response into a future if needed.
168
+ return $trans->response instanceof FutureInterface
169
+ ? $trans->response
170
+ : new FutureResponse(new FulfilledPromise($trans->response));
171
+ }
172
+ // Resolve deep futures if this is not a future
173
+ // transaction. This accounts for things like retries
174
+ // that do not have an immediate side-effect.
175
+ while ($trans->response instanceof FutureInterface) {
176
+ $trans->response = $trans->response->wait();
177
+ }
178
+ return $trans->response;
179
+ } catch (\Exception $e) {
180
+ if ($isFuture) {
181
+ // Wrap the exception in a promise
182
+ return new FutureResponse(new RejectedPromise($e));
183
+ }
184
+ throw RequestException::wrapException($trans->request, $e);
185
+ } catch (\TypeError $error) {
186
+ $exception = new \Exception($error->getMessage(), $error->getCode(), $error);
187
+ if ($isFuture) {
188
+ // Wrap the exception in a promise
189
+ return new FutureResponse(new RejectedPromise($exception));
190
+ }
191
+ throw RequestException::wrapException($trans->request, $exception);
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Get an array of default options to apply to the client
197
+ *
198
+ * @return array
199
+ */
200
+ protected function getDefaultOptions()
201
+ {
202
+ $settings = [
203
+ 'allow_redirects' => true,
204
+ 'exceptions' => true,
205
+ 'decode_content' => true,
206
+ 'verify' => true
207
+ ];
208
+
209
+ // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
210
+ // We can only trust the HTTP_PROXY environment variable in a CLI
211
+ // process due to the fact that PHP has no reliable mechanism to
212
+ // get environment variables that start with "HTTP_".
213
+ if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) {
214
+ $settings['proxy']['http'] = getenv('HTTP_PROXY');
215
+ }
216
+
217
+ if ($proxy = getenv('HTTPS_PROXY')) {
218
+ $settings['proxy']['https'] = $proxy;
219
+ }
220
+
221
+ return $settings;
222
+ }
223
+
224
+ /**
225
+ * Expand a URI template and inherit from the base URL if it's relative
226
+ *
227
+ * @param string|array $url URL or an array of the URI template to expand
228
+ * followed by a hash of template varnames.
229
+ * @return string
230
+ * @throws \InvalidArgumentException
231
+ */
232
+ private function buildUrl($url)
233
+ {
234
+ // URI template (absolute or relative)
235
+ if (!is_array($url)) {
236
+ return strpos($url, '://')
237
+ ? (string) $url
238
+ : (string) $this->baseUrl->combine($url);
239
+ }
240
+
241
+ if (!isset($url[1])) {
242
+ throw new \InvalidArgumentException('You must provide a hash of '
243
+ . 'varname options in the second element of a URL array.');
244
+ }
245
+
246
+ // Absolute URL
247
+ if (strpos($url[0], '://')) {
248
+ return Utils::uriTemplate($url[0], $url[1]);
249
+ }
250
+
251
+ // Combine the relative URL with the base URL
252
+ return (string) $this->baseUrl->combine(
253
+ Utils::uriTemplate($url[0], $url[1])
254
+ );
255
+ }
256
+
257
+ private function configureBaseUrl(&$config)
258
+ {
259
+ if (!isset($config['base_url'])) {
260
+ $this->baseUrl = new Url('', '');
261
+ } elseif (!is_array($config['base_url'])) {
262
+ $this->baseUrl = Url::fromString($config['base_url']);
263
+ } elseif (count($config['base_url']) < 2) {
264
+ throw new \InvalidArgumentException('You must provide a hash of '
265
+ . 'varname options in the second element of a base_url array.');
266
+ } else {
267
+ $this->baseUrl = Url::fromString(
268
+ Utils::uriTemplate(
269
+ $config['base_url'][0],
270
+ $config['base_url'][1]
271
+ )
272
+ );
273
+ $config['base_url'] = (string) $this->baseUrl;
274
+ }
275
+ }
276
+
277
+ private function configureDefaults($config)
278
+ {
279
+ if (!isset($config['defaults'])) {
280
+ $this->defaults = $this->getDefaultOptions();
281
+ } else {
282
+ $this->defaults = array_replace(
283
+ $this->getDefaultOptions(),
284
+ $config['defaults']
285
+ );
286
+ }
287
+
288
+ // Add the default user-agent header
289
+ if (!isset($this->defaults['headers'])) {
290
+ $this->defaults['headers'] = [
291
+ 'User-Agent' => Utils::getDefaultUserAgent()
292
+ ];
293
+ } elseif (!Core::hasHeader($this->defaults, 'User-Agent')) {
294
+ // Add the User-Agent header if one was not already set
295
+ $this->defaults['headers']['User-Agent'] = Utils::getDefaultUserAgent();
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Merges default options into the array passed by reference.
301
+ *
302
+ * @param array $options Options to modify by reference
303
+ *
304
+ * @return array
305
+ */
306
+ private function mergeDefaults($options)
307
+ {
308
+ $defaults = $this->defaults;
309
+
310
+ // Case-insensitively merge in default headers if both defaults and
311
+ // options have headers specified.
312
+ if (!empty($defaults['headers']) && !empty($options['headers'])) {
313
+ // Create a set of lowercased keys that are present.
314
+ $lkeys = [];
315
+ foreach (array_keys($options['headers']) as $k) {
316
+ $lkeys[strtolower($k)] = true;
317
+ }
318
+ // Merge in lowercase default keys when not present in above set.
319
+ foreach ($defaults['headers'] as $key => $value) {
320
+ if (!isset($lkeys[strtolower($key)])) {
321
+ $options['headers'][$key] = $value;
322
+ }
323
+ }
324
+ // No longer need to merge in headers.
325
+ unset($defaults['headers']);
326
+ }
327
+
328
+ $result = array_replace_recursive($defaults, $options);
329
+ foreach ($options as $k => $v) {
330
+ if ($v === null) {
331
+ unset($result[$k]);
332
+ }
333
+ }
334
+
335
+ return $result;
336
+ }
337
+
338
+ /**
339
+ * @deprecated Use {@see GuzzleHttp\Pool} instead.
340
+ * @see GuzzleHttp\Pool
341
+ */
342
+ public function sendAll($requests, array $options = [])
343
+ {
344
+ Pool::send($this, $requests, $options);
345
+ }
346
+
347
+ /**
348
+ * @deprecated Use GuzzleHttp\Utils::getDefaultHandler
349
+ */
350
+ public static function getDefaultHandler()
351
+ {
352
+ return Utils::getDefaultHandler();
353
+ }
354
+
355
+ /**
356
+ * @deprecated Use GuzzleHttp\Utils::getDefaultUserAgent
357
+ */
358
+ public static function getDefaultUserAgent()
359
+ {
360
+ return Utils::getDefaultUserAgent();
361
+ }
362
+ }
vendor/guzzlehttp/guzzle/src/ClientInterface.php ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Event\HasEmitterInterface;
5
+ use GuzzleHttp\Exception\RequestException;
6
+ use GuzzleHttp\Message\RequestInterface;
7
+ use GuzzleHttp\Message\ResponseInterface;
8
+
9
+ /**
10
+ * Client interface for sending HTTP requests
11
+ */
12
+ interface ClientInterface extends HasEmitterInterface
13
+ {
14
+ const VERSION = '5.3.1';
15
+
16
+ /**
17
+ * Create and return a new {@see RequestInterface} object.
18
+ *
19
+ * Use an absolute path to override the base path of the client, or a
20
+ * relative path to append to the base path of the client. The URL can
21
+ * contain the query string as well. Use an array to provide a URL
22
+ * template and additional variables to use in the URL template expansion.
23
+ *
24
+ * @param string $method HTTP method
25
+ * @param string|array|Url $url URL or URI template
26
+ * @param array $options Array of request options to apply.
27
+ *
28
+ * @return RequestInterface
29
+ */
30
+ public function createRequest($method, $url = null, array $options = []);
31
+
32
+ /**
33
+ * Send a GET request
34
+ *
35
+ * @param string|array|Url $url URL or URI template
36
+ * @param array $options Array of request options to apply.
37
+ *
38
+ * @return ResponseInterface
39
+ * @throws RequestException When an error is encountered
40
+ */
41
+ public function get($url = null, $options = []);
42
+
43
+ /**
44
+ * Send a HEAD request
45
+ *
46
+ * @param string|array|Url $url URL or URI template
47
+ * @param array $options Array of request options to apply.
48
+ *
49
+ * @return ResponseInterface
50
+ * @throws RequestException When an error is encountered
51
+ */
52
+ public function head($url = null, array $options = []);
53
+
54
+ /**
55
+ * Send a DELETE request
56
+ *
57
+ * @param string|array|Url $url URL or URI template
58
+ * @param array $options Array of request options to apply.
59
+ *
60
+ * @return ResponseInterface
61
+ * @throws RequestException When an error is encountered
62
+ */
63
+ public function delete($url = null, array $options = []);
64
+
65
+ /**
66
+ * Send a PUT request
67
+ *
68
+ * @param string|array|Url $url URL or URI template
69
+ * @param array $options Array of request options to apply.
70
+ *
71
+ * @return ResponseInterface
72
+ * @throws RequestException When an error is encountered
73
+ */
74
+ public function put($url = null, array $options = []);
75
+
76
+ /**
77
+ * Send a PATCH request
78
+ *
79
+ * @param string|array|Url $url URL or URI template
80
+ * @param array $options Array of request options to apply.
81
+ *
82
+ * @return ResponseInterface
83
+ * @throws RequestException When an error is encountered
84
+ */
85
+ public function patch($url = null, array $options = []);
86
+
87
+ /**
88
+ * Send a POST request
89
+ *
90
+ * @param string|array|Url $url URL or URI template
91
+ * @param array $options Array of request options to apply.
92
+ *
93
+ * @return ResponseInterface
94
+ * @throws RequestException When an error is encountered
95
+ */
96
+ public function post($url = null, array $options = []);
97
+
98
+ /**
99
+ * Send an OPTIONS request
100
+ *
101
+ * @param string|array|Url $url URL or URI template
102
+ * @param array $options Array of request options to apply.
103
+ *
104
+ * @return ResponseInterface
105
+ * @throws RequestException When an error is encountered
106
+ */
107
+ public function options($url = null, array $options = []);
108
+
109
+ /**
110
+ * Sends a single request
111
+ *
112
+ * @param RequestInterface $request Request to send
113
+ *
114
+ * @return \GuzzleHttp\Message\ResponseInterface
115
+ * @throws \LogicException When the handler does not populate a response
116
+ * @throws RequestException When an error is encountered
117
+ */
118
+ public function send(RequestInterface $request);
119
+
120
+ /**
121
+ * Get default request options of the client.
122
+ *
123
+ * @param string|null $keyOrPath The Path to a particular default request
124
+ * option to retrieve or pass null to retrieve all default request
125
+ * options. The syntax uses "/" to denote a path through nested PHP
126
+ * arrays. For example, "headers/content-type".
127
+ *
128
+ * @return mixed
129
+ */
130
+ public function getDefaultOption($keyOrPath = null);
131
+
132
+ /**
133
+ * Set a default request option on the client so that any request created
134
+ * by the client will use the provided default value unless overridden
135
+ * explicitly when creating a request.
136
+ *
137
+ * @param string|null $keyOrPath The Path to a particular configuration
138
+ * value to set. The syntax uses a path notation that allows you to
139
+ * specify nested configuration values (e.g., 'headers/content-type').
140
+ * @param mixed $value Default request option value to set
141
+ */
142
+ public function setDefaultOption($keyOrPath, $value);
143
+
144
+ /**
145
+ * Get the base URL of the client.
146
+ *
147
+ * @return string Returns the base URL if present
148
+ */
149
+ public function getBaseUrl();
150
+ }
vendor/guzzlehttp/guzzle/src/Collection.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Key value pair collection object
6
+ */
7
+ class Collection implements
8
+ \ArrayAccess,
9
+ \IteratorAggregate,
10
+ \Countable,
11
+ ToArrayInterface
12
+ {
13
+ use HasDataTrait;
14
+
15
+ /**
16
+ * @param array $data Associative array of data to set
17
+ */
18
+ public function __construct(array $data = [])
19
+ {
20
+ $this->data = $data;
21
+ }
22
+
23
+ /**
24
+ * Create a new collection from an array, validate the keys, and add default
25
+ * values where missing
26
+ *
27
+ * @param array $config Configuration values to apply.
28
+ * @param array $defaults Default parameters
29
+ * @param array $required Required parameter names
30
+ *
31
+ * @return self
32
+ * @throws \InvalidArgumentException if a parameter is missing
33
+ */
34
+ public static function fromConfig(
35
+ array $config = [],
36
+ array $defaults = [],
37
+ array $required = []
38
+ ) {
39
+ $data = $config + $defaults;
40
+
41
+ if ($missing = array_diff($required, array_keys($data))) {
42
+ throw new \InvalidArgumentException(
43
+ 'Config is missing the following keys: ' .
44
+ implode(', ', $missing));
45
+ }
46
+
47
+ return new self($data);
48
+ }
49
+
50
+ /**
51
+ * Removes all key value pairs
52
+ */
53
+ public function clear()
54
+ {
55
+ $this->data = [];
56
+ }
57
+
58
+ /**
59
+ * Get a specific key value.
60
+ *
61
+ * @param string $key Key to retrieve.
62
+ *
63
+ * @return mixed|null Value of the key or NULL
64
+ */
65
+ public function get($key)
66
+ {
67
+ return isset($this->data[$key]) ? $this->data[$key] : null;
68
+ }
69
+
70
+ /**
71
+ * Set a key value pair
72
+ *
73
+ * @param string $key Key to set
74
+ * @param mixed $value Value to set
75
+ */
76
+ public function set($key, $value)
77
+ {
78
+ $this->data[$key] = $value;
79
+ }
80
+
81
+ /**
82
+ * Add a value to a key. If a key of the same name has already been added,
83
+ * the key value will be converted into an array and the new value will be
84
+ * pushed to the end of the array.
85
+ *
86
+ * @param string $key Key to add
87
+ * @param mixed $value Value to add to the key
88
+ */
89
+ public function add($key, $value)
90
+ {
91
+ if (!array_key_exists($key, $this->data)) {
92
+ $this->data[$key] = $value;
93
+ } elseif (is_array($this->data[$key])) {
94
+ $this->data[$key][] = $value;
95
+ } else {
96
+ $this->data[$key] = array($this->data[$key], $value);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Remove a specific key value pair
102
+ *
103
+ * @param string $key A key to remove
104
+ */
105
+ public function remove($key)
106
+ {
107
+ unset($this->data[$key]);
108
+ }
109
+
110
+ /**
111
+ * Get all keys in the collection
112
+ *
113
+ * @return array
114
+ */
115
+ public function getKeys()
116
+ {
117
+ return array_keys($this->data);
118
+ }
119
+
120
+ /**
121
+ * Returns whether or not the specified key is present.
122
+ *
123
+ * @param string $key The key for which to check the existence.
124
+ *
125
+ * @return bool
126
+ */
127
+ public function hasKey($key)
128
+ {
129
+ return array_key_exists($key, $this->data);
130
+ }
131
+
132
+ /**
133
+ * Checks if any keys contains a certain value
134
+ *
135
+ * @param string $value Value to search for
136
+ *
137
+ * @return mixed Returns the key if the value was found FALSE if the value
138
+ * was not found.
139
+ */
140
+ public function hasValue($value)
141
+ {
142
+ return array_search($value, $this->data, true);
143
+ }
144
+
145
+ /**
146
+ * Replace the data of the object with the value of an array
147
+ *
148
+ * @param array $data Associative array of data
149
+ */
150
+ public function replace(array $data)
151
+ {
152
+ $this->data = $data;
153
+ }
154
+
155
+ /**
156
+ * Add and merge in a Collection or array of key value pair data.
157
+ *
158
+ * @param Collection|array $data Associative array of key value pair data
159
+ */
160
+ public function merge($data)
161
+ {
162
+ foreach ($data as $key => $value) {
163
+ $this->add($key, $value);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Overwrite key value pairs in this collection with all of the data from
169
+ * an array or collection.
170
+ *
171
+ * @param array|\Traversable $data Values to override over this config
172
+ */
173
+ public function overwriteWith($data)
174
+ {
175
+ if (is_array($data)) {
176
+ $this->data = $data + $this->data;
177
+ } elseif ($data instanceof Collection) {
178
+ $this->data = $data->toArray() + $this->data;
179
+ } else {
180
+ foreach ($data as $key => $value) {
181
+ $this->data[$key] = $value;
182
+ }
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Returns a Collection containing all the elements of the collection after
188
+ * applying the callback function to each one.
189
+ *
190
+ * The callable should accept three arguments:
191
+ * - (string) $key
192
+ * - (string) $value
193
+ * - (array) $context
194
+ *
195
+ * The callable must return a the altered or unaltered value.
196
+ *
197
+ * @param callable $closure Map function to apply
198
+ * @param array $context Context to pass to the callable
199
+ *
200
+ * @return Collection
201
+ */
202
+ public function map(callable $closure, array $context = [])
203
+ {
204
+ $collection = new static();
205
+ foreach ($this as $key => $value) {
206
+ $collection[$key] = $closure($key, $value, $context);
207
+ }
208
+
209
+ return $collection;
210
+ }
211
+
212
+ /**
213
+ * Iterates over each key value pair in the collection passing them to the
214
+ * callable. If the callable returns true, the current value from input is
215
+ * returned into the result Collection.
216
+ *
217
+ * The callable must accept two arguments:
218
+ * - (string) $key
219
+ * - (string) $value
220
+ *
221
+ * @param callable $closure Evaluation function
222
+ *
223
+ * @return Collection
224
+ */
225
+ public function filter(callable $closure)
226
+ {
227
+ $collection = new static();
228
+ foreach ($this->data as $key => $value) {
229
+ if ($closure($key, $value)) {
230
+ $collection[$key] = $value;
231
+ }
232
+ }
233
+
234
+ return $collection;
235
+ }
236
+ }
vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use GuzzleHttp\Message\RequestInterface;
5
+ use GuzzleHttp\Message\ResponseInterface;
6
+ use GuzzleHttp\ToArrayInterface;
7
+
8
+ /**
9
+ * Cookie jar that stores cookies an an array
10
+ */
11
+ class CookieJar implements CookieJarInterface, ToArrayInterface
12
+ {
13
+ /** @var SetCookie[] Loaded cookie data */
14
+ private $cookies = [];
15
+
16
+ /** @var bool */
17
+ private $strictMode;
18
+
19
+ /**
20
+ * @param bool $strictMode Set to true to throw exceptions when invalid
21
+ * cookies are added to the cookie jar.
22
+ * @param array $cookieArray Array of SetCookie objects or a hash of arrays
23
+ * that can be used with the SetCookie constructor
24
+ */
25
+ public function __construct($strictMode = false, $cookieArray = [])
26
+ {
27
+ $this->strictMode = $strictMode;
28
+
29
+ foreach ($cookieArray as $cookie) {
30
+ if (!($cookie instanceof SetCookie)) {
31
+ $cookie = new SetCookie($cookie);
32
+ }
33
+ $this->setCookie($cookie);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Create a new Cookie jar from an associative array and domain.
39
+ *
40
+ * @param array $cookies Cookies to create the jar from
41
+ * @param string $domain Domain to set the cookies to
42
+ *
43
+ * @return self
44
+ */
45
+ public static function fromArray(array $cookies, $domain)
46
+ {
47
+ $cookieJar = new self();
48
+ foreach ($cookies as $name => $value) {
49
+ $cookieJar->setCookie(new SetCookie([
50
+ 'Domain' => $domain,
51
+ 'Name' => $name,
52
+ 'Value' => $value,
53
+ 'Discard' => true
54
+ ]));
55
+ }
56
+
57
+ return $cookieJar;
58
+ }
59
+
60
+ /**
61
+ * Quote the cookie value if it is not already quoted and it contains
62
+ * problematic characters.
63
+ *
64
+ * @param string $value Value that may or may not need to be quoted
65
+ *
66
+ * @return string
67
+ */
68
+ public static function getCookieValue($value)
69
+ {
70
+ if (substr($value, 0, 1) !== '"' &&
71
+ substr($value, -1, 1) !== '"' &&
72
+ strpbrk($value, ';,')
73
+ ) {
74
+ $value = '"' . $value . '"';
75
+ }
76
+
77
+ return $value;
78
+ }
79
+
80
+ public function toArray()
81
+ {
82
+ return array_map(function (SetCookie $cookie) {
83
+ return $cookie->toArray();
84
+ }, $this->getIterator()->getArrayCopy());
85
+ }
86
+
87
+ public function clear($domain = null, $path = null, $name = null)
88
+ {
89
+ if (!$domain) {
90
+ $this->cookies = [];
91
+ return;
92
+ } elseif (!$path) {
93
+ $this->cookies = array_filter(
94
+ $this->cookies,
95
+ function (SetCookie $cookie) use ($path, $domain) {
96
+ return !$cookie->matchesDomain($domain);
97
+ }
98
+ );
99
+ } elseif (!$name) {
100
+ $this->cookies = array_filter(
101
+ $this->cookies,
102
+ function (SetCookie $cookie) use ($path, $domain) {
103
+ return !($cookie->matchesPath($path) &&
104
+ $cookie->matchesDomain($domain));
105
+ }
106
+ );
107
+ } else {
108
+ $this->cookies = array_filter(
109
+ $this->cookies,
110
+ function (SetCookie $cookie) use ($path, $domain, $name) {
111
+ return !($cookie->getName() == $name &&
112
+ $cookie->matchesPath($path) &&
113
+ $cookie->matchesDomain($domain));
114
+ }
115
+ );
116
+ }
117
+ }
118
+
119
+ public function clearSessionCookies()
120
+ {
121
+ $this->cookies = array_filter(
122
+ $this->cookies,
123
+ function (SetCookie $cookie) {
124
+ return !$cookie->getDiscard() && $cookie->getExpires();
125
+ }
126
+ );
127
+ }
128
+
129
+ public function setCookie(SetCookie $cookie)
130
+ {
131
+ // Only allow cookies with set and valid domain, name, value
132
+ $result = $cookie->validate();
133
+ if ($result !== true) {
134
+ if ($this->strictMode) {
135
+ throw new \RuntimeException('Invalid cookie: ' . $result);
136
+ } else {
137
+ $this->removeCookieIfEmpty($cookie);
138
+ return false;
139
+ }
140
+ }
141
+
142
+ // Resolve conflicts with previously set cookies
143
+ foreach ($this->cookies as $i => $c) {
144
+
145
+ // Two cookies are identical, when their path, and domain are
146
+ // identical.
147
+ if ($c->getPath() != $cookie->getPath() ||
148
+ $c->getDomain() != $cookie->getDomain() ||
149
+ $c->getName() != $cookie->getName()
150
+ ) {
151
+ continue;
152
+ }
153
+
154
+ // The previously set cookie is a discard cookie and this one is
155
+ // not so allow the new cookie to be set
156
+ if (!$cookie->getDiscard() && $c->getDiscard()) {
157
+ unset($this->cookies[$i]);
158
+ continue;
159
+ }
160
+
161
+ // If the new cookie's expiration is further into the future, then
162
+ // replace the old cookie
163
+ if ($cookie->getExpires() > $c->getExpires()) {
164
+ unset($this->cookies[$i]);
165
+ continue;
166
+ }
167
+
168
+ // If the value has changed, we better change it
169
+ if ($cookie->getValue() !== $c->getValue()) {
170
+ unset($this->cookies[$i]);
171
+ continue;
172
+ }
173
+
174
+ // The cookie exists, so no need to continue
175
+ return false;
176
+ }
177
+
178
+ $this->cookies[] = $cookie;
179
+
180
+ return true;
181
+ }
182
+
183
+ public function count()
184
+ {
185
+ return count($this->cookies);
186
+ }
187
+
188
+ public function getIterator()
189
+ {
190
+ return new \ArrayIterator(array_values($this->cookies));
191
+ }
192
+
193
+ public function extractCookies(
194
+ RequestInterface $request,
195
+ ResponseInterface $response
196
+ ) {
197
+ if ($cookieHeader = $response->getHeaderAsArray('Set-Cookie')) {
198
+ foreach ($cookieHeader as $cookie) {
199
+ $sc = SetCookie::fromString($cookie);
200
+ if (!$sc->getDomain()) {
201
+ $sc->setDomain($request->getHost());
202
+ }
203
+ $this->setCookie($sc);
204
+ }
205
+ }
206
+ }
207
+
208
+ public function addCookieHeader(RequestInterface $request)
209
+ {
210
+ $values = [];
211
+ $scheme = $request->getScheme();
212
+ $host = $request->getHost();
213
+ $path = $request->getPath();
214
+
215
+ foreach ($this->cookies as $cookie) {
216
+ if ($cookie->matchesPath($path) &&
217
+ $cookie->matchesDomain($host) &&
218
+ !$cookie->isExpired() &&
219
+ (!$cookie->getSecure() || $scheme == 'https')
220
+ ) {
221
+ $values[] = $cookie->getName() . '='
222
+ . self::getCookieValue($cookie->getValue());
223
+ }
224
+ }
225
+
226
+ if ($values) {
227
+ $request->setHeader('Cookie', implode('; ', $values));
228
+ }
229
+ }
230
+
231
+ /**
232
+ * If a cookie already exists and the server asks to set it again with a
233
+ * null value, the cookie must be deleted.
234
+ *
235
+ * @param SetCookie $cookie
236
+ */
237
+ private function removeCookieIfEmpty(SetCookie $cookie)
238
+ {
239
+ $cookieValue = $cookie->getValue();
240
+ if ($cookieValue === null || $cookieValue === '') {
241
+ $this->clear(
242
+ $cookie->getDomain(),
243
+ $cookie->getPath(),
244
+ $cookie->getName()
245
+ );
246
+ }
247
+ }
248
+ }
vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use GuzzleHttp\Message\RequestInterface;
5
+ use GuzzleHttp\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Stores HTTP cookies.
9
+ *
10
+ * It extracts cookies from HTTP requests, and returns them in HTTP responses.
11
+ * CookieJarInterface instances automatically expire contained cookies when
12
+ * necessary. Subclasses are also responsible for storing and retrieving
13
+ * cookies from a file, database, etc.
14
+ *
15
+ * @link http://docs.python.org/2/library/cookielib.html Inspiration
16
+ */
17
+ interface CookieJarInterface extends \Countable, \IteratorAggregate
18
+ {
19
+ /**
20
+ * Add a Cookie header to a request.
21
+ *
22
+ * If no matching cookies are found in the cookie jar, then no Cookie
23
+ * header is added to the request.
24
+ *
25
+ * @param RequestInterface $request Request object to update
26
+ */
27
+ public function addCookieHeader(RequestInterface $request);
28
+
29
+ /**
30
+ * Extract cookies from an HTTP response and store them in the CookieJar.
31
+ *
32
+ * @param RequestInterface $request Request that was sent
33
+ * @param ResponseInterface $response Response that was received
34
+ */
35
+ public function extractCookies(
36
+ RequestInterface $request,
37
+ ResponseInterface $response
38
+ );
39
+
40
+ /**
41
+ * Sets a cookie in the cookie jar.
42
+ *
43
+ * @param SetCookie $cookie Cookie to set.
44
+ *
45
+ * @return bool Returns true on success or false on failure
46
+ */
47
+ public function setCookie(SetCookie $cookie);
48
+
49
+ /**
50
+ * Remove cookies currently held in the cookie jar.
51
+ *
52
+ * Invoking this method without arguments will empty the whole cookie jar.
53
+ * If given a $domain argument only cookies belonging to that domain will
54
+ * be removed. If given a $domain and $path argument, cookies belonging to
55
+ * the specified path within that domain are removed. If given all three
56
+ * arguments, then the cookie with the specified name, path and domain is
57
+ * removed.
58
+ *
59
+ * @param string $domain Clears cookies matching a domain
60
+ * @param string $path Clears cookies matching a domain and path
61
+ * @param string $name Clears cookies matching a domain, path, and name
62
+ *
63
+ * @return CookieJarInterface
64
+ */
65
+ public function clear($domain = null, $path = null, $name = null);
66
+
67
+ /**
68
+ * Discard all sessions cookies.
69
+ *
70
+ * Removes cookies that don't have an expire field or a have a discard
71
+ * field set to true. To be called when the user agent shuts down according
72
+ * to RFC 2965.
73
+ */
74
+ public function clearSessionCookies();
75
+ }
vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use GuzzleHttp\Utils;
5
+
6
+ /**
7
+ * Persists non-session cookies using a JSON formatted file
8
+ */
9
+ class FileCookieJar extends CookieJar
10
+ {
11
+ /** @var string filename */
12
+ private $filename;
13
+
14
+ /**
15
+ * Create a new FileCookieJar object
16
+ *
17
+ * @param string $cookieFile File to store the cookie data
18
+ *
19
+ * @throws \RuntimeException if the file cannot be found or created
20
+ */
21
+ public function __construct($cookieFile)
22
+ {
23
+ $this->filename = $cookieFile;
24
+
25
+ if (file_exists($cookieFile)) {
26
+ $this->load($cookieFile);
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Saves the file when shutting down
32
+ */
33
+ public function __destruct()
34
+ {
35
+ $this->save($this->filename);
36
+ }
37
+
38
+ /**
39
+ * Saves the cookies to a file.
40
+ *
41
+ * @param string $filename File to save
42
+ * @throws \RuntimeException if the file cannot be found or created
43
+ */
44
+ public function save($filename)
45
+ {
46
+ $json = [];
47
+ foreach ($this as $cookie) {
48
+ if ($cookie->getExpires() && !$cookie->getDiscard()) {
49
+ $json[] = $cookie->toArray();
50
+ }
51
+ }
52
+
53
+ if (false === file_put_contents($filename, json_encode($json), LOCK_EX)) {
54
+ // @codeCoverageIgnoreStart
55
+ throw new \RuntimeException("Unable to save file {$filename}");
56
+ // @codeCoverageIgnoreEnd
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Load cookies from a JSON formatted file.
62
+ *
63
+ * Old cookies are kept unless overwritten by newly loaded ones.
64
+ *
65
+ * @param string $filename Cookie file to load.
66
+ * @throws \RuntimeException if the file cannot be loaded.
67
+ */
68
+ public function load($filename)
69
+ {
70
+ $json = file_get_contents($filename);
71
+ if (false === $json) {
72
+ // @codeCoverageIgnoreStart
73
+ throw new \RuntimeException("Unable to load file {$filename}");
74
+ // @codeCoverageIgnoreEnd
75
+ }
76
+
77
+ $data = Utils::jsonDecode($json, true);
78
+ if (is_array($data)) {
79
+ foreach (Utils::jsonDecode($json, true) as $cookie) {
80
+ $this->setCookie(new SetCookie($cookie));
81
+ }
82
+ } elseif (strlen($data)) {
83
+ throw new \RuntimeException("Invalid cookie file: {$filename}");
84
+ }
85
+ }
86
+ }
vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use GuzzleHttp\Utils;
5
+
6
+ /**
7
+ * Persists cookies in the client session
8
+ */
9
+ class SessionCookieJar extends CookieJar
10
+ {
11
+ /** @var string session key */
12
+ private $sessionKey;
13
+
14
+ /**
15
+ * Create a new SessionCookieJar object
16
+ *
17
+ * @param string $sessionKey Session key name to store the cookie data in session
18
+ */
19
+ public function __construct($sessionKey)
20
+ {
21
+ $this->sessionKey = $sessionKey;
22
+ $this->load();
23
+ }
24
+
25
+ /**
26
+ * Saves cookies to session when shutting down
27
+ */
28
+ public function __destruct()
29
+ {
30
+ $this->save();
31
+ }
32
+
33
+ /**
34
+ * Save cookies to the client session
35
+ */
36
+ public function save()
37
+ {
38
+ $json = [];
39
+ foreach ($this as $cookie) {
40
+ if ($cookie->getExpires() && !$cookie->getDiscard()) {
41
+ $json[] = $cookie->toArray();
42
+ }
43
+ }
44
+
45
+ $_SESSION[$this->sessionKey] = json_encode($json);
46
+ }
47
+
48
+ /**
49
+ * Load the contents of the client session into the data array
50
+ */
51
+ protected function load()
52
+ {
53
+ $cookieJar = isset($_SESSION[$this->sessionKey])
54
+ ? $_SESSION[$this->sessionKey]
55
+ : null;
56
+
57
+ $data = Utils::jsonDecode($cookieJar, true);
58
+ if (is_array($data)) {
59
+ foreach ($data as $cookie) {
60
+ $this->setCookie(new SetCookie($cookie));
61
+ }
62
+ } elseif (strlen($data)) {
63
+ throw new \RuntimeException("Invalid cookie data");
64
+ }
65
+ }
66
+ }
vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use GuzzleHttp\ToArrayInterface;
5
+
6
+ /**
7
+ * Set-Cookie object
8
+ */
9
+ class SetCookie implements ToArrayInterface
10
+ {
11
+ /** @var array */
12
+ private static $defaults = [
13
+ 'Name' => null,
14
+ 'Value' => null,
15
+ 'Domain' => null,
16
+ 'Path' => '/',
17
+ 'Max-Age' => null,
18
+ 'Expires' => null,
19
+ 'Secure' => false,
20
+ 'Discard' => false,
21
+ 'HttpOnly' => false
22
+ ];
23
+
24
+ /** @var array Cookie data */
25
+ private $data;
26
+
27
+ /**
28
+ * Create a new SetCookie object from a string
29
+ *
30
+ * @param string $cookie Set-Cookie header string
31
+ *
32
+ * @return self
33
+ */
34
+ public static function fromString($cookie)
35
+ {
36
+ // Create the default return array
37
+ $data = self::$defaults;
38
+ // Explode the cookie string using a series of semicolons
39
+ $pieces = array_filter(array_map('trim', explode(';', $cookie)));
40
+ // The name of the cookie (first kvp) must include an equal sign.
41
+ if (empty($pieces) || !strpos($pieces[0], '=')) {
42
+ return new self($data);
43
+ }
44
+
45
+ // Add the cookie pieces into the parsed data array
46
+ foreach ($pieces as $part) {
47
+
48
+ $cookieParts = explode('=', $part, 2);
49
+ $key = trim($cookieParts[0]);
50
+ $value = isset($cookieParts[1])
51
+ ? trim($cookieParts[1], " \n\r\t\0\x0B\"")
52
+ : true;
53
+
54
+ // Only check for non-cookies when cookies have been found
55
+ if (empty($data['Name'])) {
56
+ $data['Name'] = $key;
57
+ $data['Value'] = $value;
58
+ } else {
59
+ foreach (array_keys(self::$defaults) as $search) {
60
+ if (!strcasecmp($search, $key)) {
61
+ $data[$search] = $value;
62
+ continue 2;
63
+ }
64
+ }
65
+ $data[$key] = $value;
66
+ }
67
+ }
68
+
69
+ return new self($data);
70
+ }
71
+
72
+ /**
73
+ * @param array $data Array of cookie data provided by a Cookie parser
74
+ */
75
+ public function __construct(array $data = [])
76
+ {
77
+ $this->data = array_replace(self::$defaults, $data);
78
+ // Extract the Expires value and turn it into a UNIX timestamp if needed
79
+ if (!$this->getExpires() && $this->getMaxAge()) {
80
+ // Calculate the Expires date
81
+ $this->setExpires(time() + $this->getMaxAge());
82
+ } elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
83
+ $this->setExpires($this->getExpires());
84
+ }
85
+ }
86
+
87
+ public function __toString()
88
+ {
89
+ $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
90
+ foreach ($this->data as $k => $v) {
91
+ if ($k != 'Name' && $k != 'Value' && $v !== null && $v !== false) {
92
+ if ($k == 'Expires') {
93
+ $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
94
+ } else {
95
+ $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
96
+ }
97
+ }
98
+ }
99
+
100
+ return rtrim($str, '; ');
101
+ }
102
+
103
+ public function toArray()
104
+ {
105
+ return $this->data;
106
+ }
107
+
108
+ /**
109
+ * Get the cookie name
110
+ *
111
+ * @return string
112
+ */
113
+ public function getName()
114
+ {
115
+ return $this->data['Name'];
116
+ }
117
+
118
+ /**
119
+ * Set the cookie name
120
+ *
121
+ * @param string $name Cookie name
122
+ */
123
+ public function setName($name)
124
+ {
125
+ $this->data['Name'] = $name;
126
+ }
127
+
128
+ /**
129
+ * Get the cookie value
130
+ *
131
+ * @return string
132
+ */
133
+ public function getValue()
134
+ {
135
+ return $this->data['Value'];
136
+ }
137
+
138
+ /**
139
+ * Set the cookie value
140
+ *
141
+ * @param string $value Cookie value
142
+ */
143
+ public function setValue($value)
144
+ {
145
+ $this->data['Value'] = $value;
146
+ }
147
+
148
+ /**
149
+ * Get the domain
150
+ *
151
+ * @return string|null
152
+ */
153
+ public function getDomain()
154
+ {
155
+ return $this->data['Domain'];
156
+ }
157
+
158
+ /**
159
+ * Set the domain of the cookie
160
+ *
161
+ * @param string $domain
162
+ */
163
+ public function setDomain($domain)
164
+ {
165
+ $this->data['Domain'] = $domain;
166
+ }
167
+
168
+ /**
169
+ * Get the path
170
+ *
171
+ * @return string
172
+ */
173
+ public function getPath()
174
+ {
175
+ return $this->data['Path'];
176
+ }
177
+
178
+ /**
179
+ * Set the path of the cookie
180
+ *
181
+ * @param string $path Path of the cookie
182
+ */
183
+ public function setPath($path)
184
+ {
185
+ $this->data['Path'] = $path;
186
+ }
187
+
188
+ /**
189
+ * Maximum lifetime of the cookie in seconds
190
+ *
191
+ * @return int|null
192
+ */
193
+ public function getMaxAge()
194
+ {
195
+ return $this->data['Max-Age'];
196
+ }
197
+
198
+ /**
199
+ * Set the max-age of the cookie
200
+ *
201
+ * @param int $maxAge Max age of the cookie in seconds
202
+ */
203
+ public function setMaxAge($maxAge)
204
+ {
205
+ $this->data['Max-Age'] = $maxAge;
206
+ }
207
+
208
+ /**
209
+ * The UNIX timestamp when the cookie Expires
210
+ *
211
+ * @return mixed
212
+ */
213
+ public function getExpires()
214
+ {
215
+ return $this->data['Expires'];
216
+ }
217
+
218
+ /**
219
+ * Set the unix timestamp for which the cookie will expire
220
+ *
221
+ * @param int $timestamp Unix timestamp
222
+ */
223
+ public function setExpires($timestamp)
224
+ {
225
+ $this->data['Expires'] = is_numeric($timestamp)
226
+ ? (int) $timestamp
227
+ : strtotime($timestamp);
228
+ }
229
+
230
+ /**
231
+ * Get whether or not this is a secure cookie
232
+ *
233
+ * @return null|bool
234
+ */
235
+ public function getSecure()
236
+ {
237
+ return $this->data['Secure'];
238
+ }
239
+
240
+ /**
241
+ * Set whether or not the cookie is secure
242
+ *
243
+ * @param bool $secure Set to true or false if secure
244
+ */
245
+ public function setSecure($secure)
246
+ {
247
+ $this->data['Secure'] = $secure;
248
+ }
249
+
250
+ /**
251
+ * Get whether or not this is a session cookie
252
+ *
253
+ * @return null|bool
254
+ */
255
+ public function getDiscard()
256
+ {
257
+ return $this->data['Discard'];
258
+ }
259
+
260
+ /**
261
+ * Set whether or not this is a session cookie
262
+ *
263
+ * @param bool $discard Set to true or false if this is a session cookie
264
+ */
265
+ public function setDiscard($discard)
266
+ {
267
+ $this->data['Discard'] = $discard;
268
+ }
269
+
270
+ /**
271
+ * Get whether or not this is an HTTP only cookie
272
+ *
273
+ * @return bool
274
+ */
275
+ public function getHttpOnly()
276
+ {
277
+ return $this->data['HttpOnly'];
278
+ }
279
+
280
+ /**
281
+ * Set whether or not this is an HTTP only cookie
282
+ *
283
+ * @param bool $httpOnly Set to true or false if this is HTTP only
284
+ */
285
+ public function setHttpOnly($httpOnly)
286
+ {
287
+ $this->data['HttpOnly'] = $httpOnly;
288
+ }
289
+
290
+ /**
291
+ * Check if the cookie matches a path value
292
+ *
293
+ * @param string $path Path to check against
294
+ *
295
+ * @return bool
296
+ */
297
+ public function matchesPath($path)
298
+ {
299
+ return !$this->getPath() || 0 === stripos($path, $this->getPath());
300
+ }
301
+
302
+ /**
303
+ * Check if the cookie matches a domain value
304
+ *
305
+ * @param string $domain Domain to check against
306
+ *
307
+ * @return bool
308
+ */
309
+ public function matchesDomain($domain)
310
+ {
311
+ // Remove the leading '.' as per spec in RFC 6265.
312
+ // http://tools.ietf.org/html/rfc6265#section-5.2.3
313
+ $cookieDomain = ltrim($this->getDomain(), '.');
314
+
315
+ // Domain not set or exact match.
316
+ if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
317
+ return true;
318
+ }
319
+
320
+ // Matching the subdomain according to RFC 6265.
321
+ // http://tools.ietf.org/html/rfc6265#section-5.1.3
322
+ if (filter_var($domain, FILTER_VALIDATE_IP)) {
323
+ return false;
324
+ }
325
+
326
+ return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/i', $domain);
327
+ }
328
+
329
+ /**
330
+ * Check if the cookie is expired
331
+ *
332
+ * @return bool
333
+ */
334
+ public function isExpired()
335
+ {
336
+ return $this->getExpires() !== null && time() > $this->getExpires();
337
+ }
338
+
339
+ /**
340
+ * Check if the cookie is valid according to RFC 6265
341
+ *
342
+ * @return bool|string Returns true if valid or an error message if invalid
343
+ */
344
+ public function validate()
345
+ {
346
+ // Names must not be empty, but can be 0
347
+ $name = $this->getName();
348
+ if (empty($name) && !is_numeric($name)) {
349
+ return 'The cookie name must not be empty';
350
+ }
351
+
352
+ // Check if any of the invalid characters are present in the cookie name
353
+ if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
354
+ return "Cookie name must not cannot invalid characters: =,; \\t\\r\\n\\013\\014";
355
+ }
356
+
357
+ // Value must not be empty, but can be 0
358
+ $value = $this->getValue();
359
+ if (empty($value) && !is_numeric($value)) {
360
+ return 'The cookie value must not be empty';
361
+ }
362
+
363
+ // Domains must not be empty, but can be 0
364
+ // A "0" is not a valid internet domain, but may be used as server name
365
+ // in a private network.
366
+ $domain = $this->getDomain();
367
+ if (empty($domain) && !is_numeric($domain)) {
368
+ return 'The cookie domain must not be empty';
369
+ }
370
+
371
+ return true;
372
+ }
373
+ }
vendor/guzzlehttp/guzzle/src/Event/AbstractEvent.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Basic event class that can be extended.
6
+ */
7
+ abstract class AbstractEvent implements EventInterface
8
+ {
9
+ private $propagationStopped = false;
10
+
11
+ public function isPropagationStopped()
12
+ {
13
+ return $this->propagationStopped;
14
+ }
15
+
16
+ public function stopPropagation()
17
+ {
18
+ $this->propagationStopped = true;
19
+ }
20
+ }
vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ use GuzzleHttp\Transaction;
5
+ use GuzzleHttp\ClientInterface;
6
+ use GuzzleHttp\Message\RequestInterface;
7
+
8
+ /**
9
+ * Base class for request events, providing a request and client getter.
10
+ */
11
+ abstract class AbstractRequestEvent extends AbstractEvent
12
+ {
13
+ /** @var Transaction */
14
+ protected $transaction;
15
+
16
+ /**
17
+ * @param Transaction $transaction
18
+ */
19
+ public function __construct(Transaction $transaction)
20
+ {
21
+ $this->transaction = $transaction;
22
+ }
23
+
24
+ /**
25
+ * Get the HTTP client associated with the event.
26
+ *
27
+ * @return ClientInterface
28
+ */
29
+ public function getClient()
30
+ {
31
+ return $this->transaction->client;
32
+ }
33
+
34
+ /**
35
+ * Get the request object
36
+ *
37
+ * @return RequestInterface
38
+ */
39
+ public function getRequest()
40
+ {
41
+ return $this->transaction->request;
42
+ }
43
+
44
+ /**
45
+ * Get the number of transaction retries.
46
+ *
47
+ * @return int
48
+ */
49
+ public function getRetryCount()
50
+ {
51
+ return $this->transaction->retries;
52
+ }
53
+
54
+ /**
55
+ * @return Transaction
56
+ */
57
+ public function getTransaction()
58
+ {
59
+ return $this->transaction;
60
+ }
61
+ }
vendor/guzzlehttp/guzzle/src/Event/AbstractRetryableEvent.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Abstract request event that can be retried.
6
+ */
7
+ class AbstractRetryableEvent extends AbstractTransferEvent
8
+ {
9
+ /**
10
+ * Mark the request as needing a retry and stop event propagation.
11
+ *
12
+ * This action allows you to retry a request without emitting the "end"
13
+ * event multiple times for a given request. When retried, the request
14
+ * emits a before event and is then sent again using the client that sent
15
+ * the original request.
16
+ *
17
+ * When retrying, it is important to limit the number of retries you allow
18
+ * to prevent infinite loops.
19
+ *
20
+ * This action can only be taken during the "complete" and "error" events.
21
+ *
22
+ * @param int $afterDelay If specified, the amount of time in milliseconds
23
+ * to delay before retrying. Note that this must
24
+ * be supported by the underlying RingPHP handler
25
+ * to work properly. Set to 0 or provide no value
26
+ * to retry immediately.
27
+ */
28
+ public function retry($afterDelay = 0)
29
+ {
30
+ // Setting the transition state to 'retry' will cause the next state
31
+ // transition of the transaction to retry the request.
32
+ $this->transaction->state = 'retry';
33
+
34
+ if ($afterDelay) {
35
+ $this->transaction->request->getConfig()->set('delay', $afterDelay);
36
+ }
37
+
38
+ $this->stopPropagation();
39
+ }
40
+ }
vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ use GuzzleHttp\Message\ResponseInterface;
5
+ use GuzzleHttp\Ring\Future\FutureInterface;
6
+
7
+ /**
8
+ * Event that contains transfer statistics, and can be intercepted.
9
+ */
10
+ abstract class AbstractTransferEvent extends AbstractRequestEvent
11
+ {
12
+ /**
13
+ * Get all transfer information as an associative array if no $name
14
+ * argument is supplied, or gets a specific transfer statistic if
15
+ * a $name attribute is supplied (e.g., 'total_time').
16
+ *
17
+ * @param string $name Name of the transfer stat to retrieve
18
+ *
19
+ * @return mixed|null|array
20
+ */
21
+ public function getTransferInfo($name = null)
22
+ {
23
+ if (!$name) {
24
+ return $this->transaction->transferInfo;
25
+ }
26
+
27
+ return isset($this->transaction->transferInfo[$name])
28
+ ? $this->transaction->transferInfo[$name]
29
+ : null;
30
+ }
31
+
32
+ /**
33
+ * Returns true/false if a response is available.
34
+ *
35
+ * @return bool
36
+ */
37
+ public function hasResponse()
38
+ {
39
+ return !($this->transaction->response instanceof FutureInterface);
40
+ }
41
+
42
+ /**
43
+ * Get the response.
44
+ *
45
+ * @return ResponseInterface|null
46
+ */
47
+ public function getResponse()
48
+ {
49
+ return $this->hasResponse() ? $this->transaction->response : null;
50
+ }
51
+
52
+ /**
53
+ * Intercept the request and associate a response
54
+ *
55
+ * @param ResponseInterface $response Response to set
56
+ */
57
+ public function intercept(ResponseInterface $response)
58
+ {
59
+ $this->transaction->response = $response;
60
+ $this->transaction->exception = null;
61
+ $this->stopPropagation();
62
+ }
63
+ }
vendor/guzzlehttp/guzzle/src/Event/BeforeEvent.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ use GuzzleHttp\Message\ResponseInterface;
5
+
6
+ /**
7
+ * Event object emitted before a request is sent.
8
+ *
9
+ * This event MAY be emitted multiple times (i.e., if a request is retried).
10
+ * You MAY change the Response associated with the request using the
11
+ * intercept() method of the event.
12
+ */
13
+ class BeforeEvent extends AbstractRequestEvent
14
+ {
15
+ /**
16
+ * Intercept the request and associate a response
17
+ *
18
+ * @param ResponseInterface $response Response to set
19
+ */
20
+ public function intercept(ResponseInterface $response)
21
+ {
22
+ $this->transaction->response = $response;
23
+ $this->transaction->exception = null;
24
+ $this->stopPropagation();
25
+ }
26
+ }
vendor/guzzlehttp/guzzle/src/Event/CompleteEvent.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Event object emitted after a request has been completed.
6
+ *
7
+ * This event MAY be emitted multiple times for a single request. You MAY
8
+ * change the Response associated with the request using the intercept()
9
+ * method of the event.
10
+ *
11
+ * This event allows the request to be retried if necessary using the retry()
12
+ * method of the event.
13
+ */
14
+ class CompleteEvent extends AbstractRetryableEvent {}
vendor/guzzlehttp/guzzle/src/Event/Emitter.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Guzzle event emitter.
6
+ *
7
+ * Some of this class is based on the Symfony EventDispatcher component, which
8
+ * ships with the following license:
9
+ *
10
+ * This file is part of the Symfony package.
11
+ *
12
+ * (c) Fabien Potencier <fabien@symfony.com>
13
+ *
14
+ * For the full copyright and license information, please view the LICENSE
15
+ * file that was distributed with this source code.
16
+ *
17
+ * @link https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher
18
+ */
19
+ class Emitter implements EmitterInterface
20
+ {
21
+ /** @var array */
22
+ private $listeners = [];
23
+
24
+ /** @var array */
25
+ private $sorted = [];
26
+
27
+ public function on($eventName, callable $listener, $priority = 0)
28
+ {
29
+ if ($priority === 'first') {
30
+ $priority = isset($this->listeners[$eventName])
31
+ ? max(array_keys($this->listeners[$eventName])) + 1
32
+ : 1;
33
+ } elseif ($priority === 'last') {
34
+ $priority = isset($this->listeners[$eventName])
35
+ ? min(array_keys($this->listeners[$eventName])) - 1
36
+ : -1;
37
+ }
38
+
39
+ $this->listeners[$eventName][$priority][] = $listener;
40
+ unset($this->sorted[$eventName]);
41
+ }
42
+
43
+ public function once($eventName, callable $listener, $priority = 0)
44
+ {
45
+ $onceListener = function (
46
+ EventInterface $event
47
+ ) use (&$onceListener, $eventName, $listener, $priority) {
48
+ $this->removeListener($eventName, $onceListener);
49
+ $listener($event, $eventName);
50
+ };
51
+
52
+ $this->on($eventName, $onceListener, $priority);
53
+ }
54
+
55
+ public function removeListener($eventName, callable $listener)
56
+ {
57
+ if (empty($this->listeners[$eventName])) {
58
+ return;
59
+ }
60
+
61
+ foreach ($this->listeners[$eventName] as $priority => $listeners) {
62
+ if (false !== ($key = array_search($listener, $listeners, true))) {
63
+ unset(
64
+ $this->listeners[$eventName][$priority][$key],
65
+ $this->sorted[$eventName]
66
+ );
67
+ }
68
+ }
69
+ }
70
+
71
+ public function listeners($eventName = null)
72
+ {
73
+ // Return all events in a sorted priority order
74
+ if ($eventName === null) {
75
+ foreach (array_keys($this->listeners) as $eventName) {
76
+ if (empty($this->sorted[$eventName])) {
77
+ $this->listeners($eventName);
78
+ }
79
+ }
80
+ return $this->sorted;
81
+ }
82
+
83
+ // Return the listeners for a specific event, sorted in priority order
84
+ if (empty($this->sorted[$eventName])) {
85
+ $this->sorted[$eventName] = [];
86
+ if (isset($this->listeners[$eventName])) {
87
+ krsort($this->listeners[$eventName], SORT_NUMERIC);
88
+ foreach ($this->listeners[$eventName] as $listeners) {
89
+ foreach ($listeners as $listener) {
90
+ $this->sorted[$eventName][] = $listener;
91
+ }
92
+ }
93
+ }
94
+ }
95
+
96
+ return $this->sorted[$eventName];
97
+ }
98
+
99
+ public function hasListeners($eventName)
100
+ {
101
+ return !empty($this->listeners[$eventName]);
102
+ }
103
+
104
+ public function emit($eventName, EventInterface $event)
105
+ {
106
+ if (isset($this->listeners[$eventName])) {
107
+ foreach ($this->listeners($eventName) as $listener) {
108
+ $listener($event, $eventName);
109
+ if ($event->isPropagationStopped()) {
110
+ break;
111
+ }
112
+ }
113
+ }
114
+
115
+ return $event;
116
+ }
117
+
118
+ public function attach(SubscriberInterface $subscriber)
119
+ {
120
+ foreach ($subscriber->getEvents() as $eventName => $listeners) {
121
+ if (is_array($listeners[0])) {
122
+ foreach ($listeners as $listener) {
123
+ $this->on(
124
+ $eventName,
125
+ [$subscriber, $listener[0]],
126
+ isset($listener[1]) ? $listener[1] : 0
127
+ );
128
+ }
129
+ } else {
130
+ $this->on(
131
+ $eventName,
132
+ [$subscriber, $listeners[0]],
133
+ isset($listeners[1]) ? $listeners[1] : 0
134
+ );
135
+ }
136
+ }
137
+ }
138
+
139
+ public function detach(SubscriberInterface $subscriber)
140
+ {
141
+ foreach ($subscriber->getEvents() as $eventName => $listener) {
142
+ $this->removeListener($eventName, [$subscriber, $listener[0]]);
143
+ }
144
+ }
145
+ }
vendor/guzzlehttp/guzzle/src/Event/EmitterInterface.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Guzzle event emitter.
6
+ */
7
+ interface EmitterInterface
8
+ {
9
+ /**
10
+ * Binds a listener to a specific event.
11
+ *
12
+ * @param string $eventName Name of the event to bind to.
13
+ * @param callable $listener Listener to invoke when triggered.
14
+ * @param int|string $priority The higher this value, the earlier an event
15
+ * listener will be triggered in the chain (defaults to 0). You can
16
+ * pass "first" or "last" to dynamically specify the event priority
17
+ * based on the current event priorities associated with the given
18
+ * event name in the emitter. Use "first" to set the priority to the
19
+ * current highest priority plus one. Use "last" to set the priority to
20
+ * the current lowest event priority minus one.
21
+ */
22
+ public function on($eventName, callable $listener, $priority = 0);
23
+
24
+ /**
25
+ * Binds a listener to a specific event. After the listener is triggered
26
+ * once, it is removed as a listener.
27
+ *
28
+ * @param string $eventName Name of the event to bind to.
29
+ * @param callable $listener Listener to invoke when triggered.
30
+ * @param int $priority The higher this value, the earlier an event
31
+ * listener will be triggered in the chain (defaults to 0)
32
+ */
33
+ public function once($eventName, callable $listener, $priority = 0);
34
+
35
+ /**
36
+ * Removes an event listener from the specified event.
37
+ *
38
+ * @param string $eventName The event to remove a listener from
39
+ * @param callable $listener The listener to remove
40
+ */
41
+ public function removeListener($eventName, callable $listener);
42
+
43
+ /**
44
+ * Gets the listeners of a specific event or all listeners if no event is
45
+ * specified.
46
+ *
47
+ * @param string $eventName The name of the event. Pass null (the default)
48
+ * to retrieve all listeners.
49
+ *
50
+ * @return array The event listeners for the specified event, or all event
51
+ * listeners by event name. The format of the array when retrieving a
52
+ * specific event list is an array of callables. The format of the array
53
+ * when retrieving all listeners is an associative array of arrays of
54
+ * callables.
55
+ */
56
+ public function listeners($eventName = null);
57
+
58
+ /**
59
+ * Checks if the emitter has listeners by the given name.
60
+ *
61
+ * @param string $eventName The name of the event to check.
62
+ *
63
+ * @return bool
64
+ */
65
+ public function hasListeners($eventName);
66
+
67
+ /**
68
+ * Emits an event to all registered listeners.
69
+ *
70
+ * Each event that is bound to the emitted eventName receives a
71
+ * EventInterface, the name of the event, and the event emitter.
72
+ *
73
+ * @param string $eventName The name of the event to dispatch.
74
+ * @param EventInterface $event The event to pass to the event handlers/listeners.
75
+ *
76
+ * @return EventInterface Returns the provided event object
77
+ */
78
+ public function emit($eventName, EventInterface $event);
79
+
80
+ /**
81
+ * Attaches an event subscriber.
82
+ *
83
+ * The subscriber is asked for all the events it is interested in and added
84
+ * as an event listener for each event.
85
+ *
86
+ * @param SubscriberInterface $subscriber Subscriber to attach.
87
+ */
88
+ public function attach(SubscriberInterface $subscriber);
89
+
90
+ /**
91
+ * Detaches an event subscriber.
92
+ *
93
+ * @param SubscriberInterface $subscriber Subscriber to detach.
94
+ */
95
+ public function detach(SubscriberInterface $subscriber);
96
+ }
vendor/guzzlehttp/guzzle/src/Event/EndEvent.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * A terminal event that is emitted when a request transaction has ended.
6
+ *
7
+ * This event is emitted for both successful responses and responses that
8
+ * encountered an exception. You need to check if an exception is present
9
+ * in your listener to know the difference.
10
+ *
11
+ * You MAY intercept the response associated with the event if needed, but keep
12
+ * in mind that the "complete" event will not be triggered as a result.
13
+ */
14
+ class EndEvent extends AbstractTransferEvent
15
+ {
16
+ /**
17
+ * Get the exception that was encountered (if any).
18
+ *
19
+ * This method should be used to check if the request was sent successfully
20
+ * or if it encountered errors.
21
+ *
22
+ * @return \Exception|null
23
+ */
24
+ public function getException()
25
+ {
26
+ return $this->transaction->exception;
27
+ }
28
+ }
vendor/guzzlehttp/guzzle/src/Event/ErrorEvent.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ use GuzzleHttp\Exception\RequestException;
5
+
6
+ /**
7
+ * Event emitted when an error occurs while sending a request.
8
+ *
9
+ * This event MAY be emitted multiple times. You MAY intercept the exception
10
+ * and inject a response into the event to rescue the request using the
11
+ * intercept() method of the event.
12
+ *
13
+ * This event allows the request to be retried using the "retry" method of the
14
+ * event.
15
+ */
16
+ class ErrorEvent extends AbstractRetryableEvent
17
+ {
18
+ /**
19
+ * Get the exception that was encountered
20
+ *
21
+ * @return RequestException
22
+ */
23
+ public function getException()
24
+ {
25
+ return $this->transaction->exception;
26
+ }
27
+ }
vendor/guzzlehttp/guzzle/src/Event/EventInterface.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Base event interface used when dispatching events to listeners using an
6
+ * event emitter.
7
+ */
8
+ interface EventInterface
9
+ {
10
+ /**
11
+ * Returns whether or not stopPropagation was called on the event.
12
+ *
13
+ * @return bool
14
+ * @see Event::stopPropagation
15
+ */
16
+ public function isPropagationStopped();
17
+
18
+ /**
19
+ * Stops the propagation of the event, preventing subsequent listeners
20
+ * registered to the same event from being invoked.
21
+ */
22
+ public function stopPropagation();
23
+ }
vendor/guzzlehttp/guzzle/src/Event/HasEmitterInterface.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Holds an event emitter
6
+ */
7
+ interface HasEmitterInterface
8
+ {
9
+ /**
10
+ * Get the event emitter of the object
11
+ *
12
+ * @return EmitterInterface
13
+ */
14
+ public function getEmitter();
15
+ }
vendor/guzzlehttp/guzzle/src/Event/HasEmitterTrait.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Trait that implements the methods of HasEmitterInterface
6
+ */
7
+ trait HasEmitterTrait
8
+ {
9
+ /** @var EmitterInterface */
10
+ private $emitter;
11
+
12
+ public function getEmitter()
13
+ {
14
+ if (!$this->emitter) {
15
+ $this->emitter = new Emitter();
16
+ }
17
+
18
+ return $this->emitter;
19
+ }
20
+ }
vendor/guzzlehttp/guzzle/src/Event/ListenerAttacherTrait.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Trait that provides methods for extract event listeners specified in an array
6
+ * and attaching them to an emitter owned by the object or one of its direct
7
+ * dependencies.
8
+ */
9
+ trait ListenerAttacherTrait
10
+ {
11
+ /**
12
+ * Attaches event listeners and properly sets their priorities and whether
13
+ * or not they are are only executed once.
14
+ *
15
+ * @param HasEmitterInterface $object Object that has the event emitter.
16
+ * @param array $listeners Array of hashes representing event
17
+ * event listeners. Each item contains
18
+ * "name", "fn", "priority", & "once".
19
+ */
20
+ private function attachListeners(HasEmitterInterface $object, array $listeners)
21
+ {
22
+ $emitter = $object->getEmitter();
23
+ foreach ($listeners as $el) {
24
+ if ($el['once']) {
25
+ $emitter->once($el['name'], $el['fn'], $el['priority']);
26
+ } else {
27
+ $emitter->on($el['name'], $el['fn'], $el['priority']);
28
+ }
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Extracts the allowed events from the provided array, and ignores anything
34
+ * else in the array. The event listener must be specified as a callable or
35
+ * as an array of event listener data ("name", "fn", "priority", "once").
36
+ *
37
+ * @param array $source Array containing callables or hashes of data to be
38
+ * prepared as event listeners.
39
+ * @param array $events Names of events to look for in the provided $source
40
+ * array. Other keys are ignored.
41
+ * @return array
42
+ */
43
+ private function prepareListeners(array $source, array $events)
44
+ {
45
+ $listeners = [];
46
+ foreach ($events as $name) {
47
+ if (isset($source[$name])) {
48
+ $this->buildListener($name, $source[$name], $listeners);
49
+ }
50
+ }
51
+
52
+ return $listeners;
53
+ }
54
+
55
+ /**
56
+ * Creates a complete event listener definition from the provided array of
57
+ * listener data. Also works recursively if more than one listeners are
58
+ * contained in the provided array.
59
+ *
60
+ * @param string $name Name of the event the listener is for.
61
+ * @param array|callable $data Event listener data to prepare.
62
+ * @param array $listeners Array of listeners, passed by reference.
63
+ *
64
+ * @throws \InvalidArgumentException if the event data is malformed.
65
+ */
66
+ private function buildListener($name, $data, &$listeners)
67
+ {
68
+ static $defaults = ['priority' => 0, 'once' => false];
69
+
70
+ // If a callable is provided, normalize it to the array format.
71
+ if (is_callable($data)) {
72
+ $data = ['fn' => $data];
73
+ }
74
+
75
+ // Prepare the listener and add it to the array, recursively.
76
+ if (isset($data['fn'])) {
77
+ $data['name'] = $name;
78
+ $listeners[] = $data + $defaults;
79
+ } elseif (is_array($data)) {
80
+ foreach ($data as $listenerData) {
81
+ $this->buildListener($name, $listenerData, $listeners);
82
+ }
83
+ } else {
84
+ throw new \InvalidArgumentException('Each event listener must be a '
85
+ . 'callable or an associative array containing a "fn" key.');
86
+ }
87
+ }
88
+ }
vendor/guzzlehttp/guzzle/src/Event/ProgressEvent.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ use GuzzleHttp\Transaction;
5
+
6
+ /**
7
+ * Event object emitted when upload or download progress is made.
8
+ *
9
+ * You can access the progress values using their corresponding public
10
+ * properties:
11
+ *
12
+ * - $downloadSize: The number of bytes that will be downloaded (if known)
13
+ * - $downloaded: The number of bytes that have been downloaded
14
+ * - $uploadSize: The number of bytes that will be uploaded (if known)
15
+ * - $uploaded: The number of bytes that have been uploaded
16
+ */
17
+ class ProgressEvent extends AbstractRequestEvent
18
+ {
19
+ /** @var int Amount of data to be downloaded */
20
+ public $downloadSize;
21
+
22
+ /** @var int Amount of data that has been downloaded */
23
+ public $downloaded;
24
+
25
+ /** @var int Amount of data to upload */
26
+ public $uploadSize;
27
+
28
+ /** @var int Amount of data that has been uploaded */
29
+ public $uploaded;
30
+
31
+ /**
32
+ * @param Transaction $transaction Transaction being sent.
33
+ * @param int $downloadSize Amount of data to download (if known)
34
+ * @param int $downloaded Amount of data that has been downloaded
35
+ * @param int $uploadSize Amount of data to upload (if known)
36
+ * @param int $uploaded Amount of data that had been uploaded
37
+ */
38
+ public function __construct(
39
+ Transaction $transaction,
40
+ $downloadSize,
41
+ $downloaded,
42
+ $uploadSize,
43
+ $uploaded
44
+ ) {
45
+ parent::__construct($transaction);
46
+ $this->downloadSize = $downloadSize;
47
+ $this->downloaded = $downloaded;
48
+ $this->uploadSize = $uploadSize;
49
+ $this->uploaded = $uploaded;
50
+ }
51
+ }
vendor/guzzlehttp/guzzle/src/Event/RequestEvents.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * Contains methods used to manage the request event lifecycle.
6
+ */
7
+ final class RequestEvents
8
+ {
9
+ // Generic event priorities
10
+ const EARLY = 10000;
11
+ const LATE = -10000;
12
+
13
+ // "before" priorities
14
+ const PREPARE_REQUEST = -100;
15
+ const SIGN_REQUEST = -10000;
16
+
17
+ // "complete" and "error" response priorities
18
+ const VERIFY_RESPONSE = 100;
19
+ const REDIRECT_RESPONSE = 200;
20
+
21
+ /**
22
+ * Converts an array of event options into a formatted array of valid event
23
+ * configuration.
24
+ *
25
+ * @param array $options Event array to convert
26
+ * @param array $events Event names to convert in the options array.
27
+ * @param mixed $handler Event handler to utilize
28
+ *
29
+ * @return array
30
+ * @throws \InvalidArgumentException if the event config is invalid
31
+ * @internal
32
+ */
33
+ public static function convertEventArray(
34
+ array $options,
35
+ array $events,
36
+ $handler
37
+ ) {
38
+ foreach ($events as $name) {
39
+ if (!isset($options[$name])) {
40
+ $options[$name] = [$handler];
41
+ } elseif (is_callable($options[$name])) {
42
+ $options[$name] = [$options[$name], $handler];
43
+ } elseif (is_array($options[$name])) {
44
+ if (isset($options[$name]['fn'])) {
45
+ $options[$name] = [$options[$name], $handler];
46
+ } else {
47
+ $options[$name][] = $handler;
48
+ }
49
+ } else {
50
+ throw new \InvalidArgumentException('Invalid event format');
51
+ }
52
+ }
53
+
54
+ return $options;
55
+ }
56
+ }
vendor/guzzlehttp/guzzle/src/Event/SubscriberInterface.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Event;
3
+
4
+ /**
5
+ * SubscriberInterface provides an array of events to an
6
+ * EventEmitterInterface when it is registered. The emitter then binds the
7
+ * listeners specified by the EventSubscriber.
8
+ *
9
+ * This interface is based on the SubscriberInterface of the Symfony.
10
+ * @link https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher
11
+ */
12
+ interface SubscriberInterface
13
+ {
14
+ /**
15
+ * Returns an array of event names this subscriber wants to listen to.
16
+ *
17
+ * The returned array keys MUST map to an event name. Each array value
18
+ * MUST be an array in which the first element is the name of a function
19
+ * on the EventSubscriber OR an array of arrays in the aforementioned
20
+ * format. The second element in the array is optional, and if specified,
21
+ * designates the event priority.
22
+ *
23
+ * For example, the following are all valid:
24
+ *
25
+ * - ['eventName' => ['methodName']]
26
+ * - ['eventName' => ['methodName', $priority]]
27
+ * - ['eventName' => [['methodName'], ['otherMethod']]
28
+ * - ['eventName' => [['methodName'], ['otherMethod', $priority]]
29
+ * - ['eventName' => [['methodName', $priority], ['otherMethod', $priority]]
30
+ *
31
+ * @return array
32
+ */
33
+ public function getEvents();
34
+ }
vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when an HTTP error occurs (4xx or 5xx error)
6
+ */
7
+ class BadResponseException extends RequestException {}
vendor/guzzlehttp/guzzle/src/Exception/ClientException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a client error is encountered (4xx codes)
6
+ */
7
+ class ClientException extends BadResponseException {}
vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class ConnectException extends RequestException {}
vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class CouldNotRewindStreamException extends RequestException {}
vendor/guzzlehttp/guzzle/src/Exception/ParseException.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use GuzzleHttp\Message\ResponseInterface;
5
+
6
+ /**
7
+ * Exception when a client is unable to parse the response body as XML or JSON
8
+ */
9
+ class ParseException extends TransferException
10
+ {
11
+ /** @var ResponseInterface */
12
+ private $response;
13
+
14
+ public function __construct(
15
+ $message = '',
16
+ ResponseInterface $response = null,
17
+ \Exception $previous = null
18
+ ) {
19
+ parent::__construct($message, 0, $previous);
20
+ $this->response = $response;
21
+ }
22
+ /**
23
+ * Get the associated response
24
+ *
25
+ * @return ResponseInterface|null
26
+ */
27
+ public function getResponse()
28
+ {
29
+ return $this->response;
30
+ }
31
+ }
vendor/guzzlehttp/guzzle/src/Exception/RequestException.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use GuzzleHttp\Message\RequestInterface;
5
+ use GuzzleHttp\Message\ResponseInterface;
6
+ use GuzzleHttp\Ring\Exception\ConnectException;
7
+ use GuzzleHttp\Exception\ConnectException as HttpConnectException;
8
+ use GuzzleHttp\Ring\Future\FutureInterface;
9
+
10
+ /**
11
+ * HTTP Request exception
12
+ */
13
+ class RequestException extends TransferException
14
+ {
15
+ /** @var RequestInterface */
16
+ private $request;
17
+
18
+ /** @var ResponseInterface */
19
+ private $response;
20
+
21
+ public function __construct(
22
+ $message,
23
+ RequestInterface $request,
24
+ ResponseInterface $response = null,
25
+ \Exception $previous = null
26
+ ) {
27
+ // Set the code of the exception if the response is set and not future.
28
+ $code = $response && !($response instanceof FutureInterface)
29
+ ? $response->getStatusCode()
30
+ : 0;
31
+ parent::__construct($message, $code, $previous);
32
+ $this->request = $request;
33
+ $this->response = $response;
34
+ }
35
+
36
+ /**
37
+ * Wrap non-RequestExceptions with a RequestException
38
+ *
39
+ * @param RequestInterface $request
40
+ * @param \Exception $e
41
+ *
42
+ * @return RequestException
43
+ */
44
+ public static function wrapException(RequestInterface $request, \Exception $e)
45
+ {
46
+ if ($e instanceof RequestException) {
47
+ return $e;
48
+ } elseif ($e instanceof ConnectException) {
49
+ return new HttpConnectException($e->getMessage(), $request, null, $e);
50
+ } else {
51
+ return new RequestException($e->getMessage(), $request, null, $e);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Factory method to create a new exception with a normalized error message
57
+ *
58
+ * @param RequestInterface $request Request
59
+ * @param ResponseInterface $response Response received
60
+ * @param \Exception $previous Previous exception
61
+ *
62
+ * @return self
63
+ */
64
+ public static function create(
65
+ RequestInterface $request,
66
+ ResponseInterface $response = null,
67
+ \Exception $previous = null
68
+ ) {
69
+ if (!$response) {
70
+ return new self('Error completing request', $request, null, $previous);
71
+ }
72
+
73
+ $level = floor($response->getStatusCode() / 100);
74
+ if ($level == '4') {
75
+ $label = 'Client error response';
76
+ $className = __NAMESPACE__ . '\\ClientException';
77
+ } elseif ($level == '5') {
78
+ $label = 'Server error response';
79
+ $className = __NAMESPACE__ . '\\ServerException';
80
+ } else {
81
+ $label = 'Unsuccessful response';
82
+ $className = __CLASS__;
83
+ }
84
+
85
+ $message = $label . ' [url] ' . $request->getUrl()
86
+ . ' [status code] ' . $response->getStatusCode()
87
+ . ' [reason phrase] ' . $response->getReasonPhrase();
88
+
89
+ return new $className($message, $request, $response, $previous);
90
+ }
91
+
92
+ /**
93
+ * Get the request that caused the exception
94
+ *
95
+ * @return RequestInterface
96
+ */
97
+ public function getRequest()
98
+ {
99
+ return $this->request;
100
+ }
101
+
102
+ /**
103
+ * Get the associated response
104
+ *
105
+ * @return ResponseInterface|null
106
+ */
107
+ public function getResponse()
108
+ {
109
+ return $this->response;
110
+ }
111
+
112
+ /**
113
+ * Check if a response was received
114
+ *
115
+ * @return bool
116
+ */
117
+ public function hasResponse()
118
+ {
119
+ return $this->response !== null;
120
+ }
121
+ }
vendor/guzzlehttp/guzzle/src/Exception/ServerException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a server error is encountered (5xx codes)
6
+ */
7
+ class ServerException extends BadResponseException {}
vendor/guzzlehttp/guzzle/src/Exception/StateException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class StateException extends TransferException {};
vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TooManyRedirectsException extends RequestException {}
vendor/guzzlehttp/guzzle/src/Exception/TransferException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TransferException extends \RuntimeException {}
vendor/guzzlehttp/guzzle/src/Exception/XmlParseException.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Exception;
4
+
5
+ use GuzzleHttp\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Exception when a client is unable to parse the response body as XML
9
+ */
10
+ class XmlParseException extends ParseException
11
+ {
12
+ /** @var \LibXMLError */
13
+ protected $error;
14
+
15
+ public function __construct(
16
+ $message = '',
17
+ ResponseInterface $response = null,
18
+ \Exception $previous = null,
19
+ \LibXMLError $error = null
20
+ ) {
21
+ parent::__construct($message, $response, $previous);
22
+ $this->error = $error;
23
+ }
24
+
25
+ /**
26
+ * Get the associated error
27
+ *
28
+ * @return \LibXMLError|null
29
+ */
30
+ public function getError()
31
+ {
32
+ return $this->error;
33
+ }
34
+ }
vendor/guzzlehttp/guzzle/src/HasDataTrait.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Trait implementing ToArrayInterface, \ArrayAccess, \Countable,
6
+ * \IteratorAggregate, and some path style methods.
7
+ */
8
+ trait HasDataTrait
9
+ {
10
+ /** @var array */
11
+ protected $data = [];
12
+
13
+ public function getIterator()
14
+ {
15
+ return new \ArrayIterator($this->data);
16
+ }
17
+
18
+ public function offsetGet($offset)
19
+ {
20
+ return isset($this->data[$offset]) ? $this->data[$offset] : null;
21
+ }
22
+
23
+ public function offsetSet($offset, $value)
24
+ {
25
+ $this->data[$offset] = $value;
26
+ }
27
+
28
+ public function offsetExists($offset)
29
+ {
30
+ return isset($this->data[$offset]);
31
+ }
32
+
33
+ public function offsetUnset($offset)
34
+ {
35
+ unset($this->data[$offset]);
36
+ }
37
+
38
+ public function toArray()
39
+ {
40
+ return $this->data;
41
+ }
42
+
43
+ public function count()
44
+ {
45
+ return count($this->data);
46
+ }
47
+
48
+ /**
49
+ * Get a value from the collection using a path syntax to retrieve nested
50
+ * data.
51
+ *
52
+ * @param string $path Path to traverse and retrieve a value from
53
+ *
54
+ * @return mixed|null
55
+ */
56
+ public function getPath($path)
57
+ {
58
+ return Utils::getPath($this->data, $path);
59
+ }
60
+
61
+ /**
62
+ * Set a value into a nested array key. Keys will be created as needed to
63
+ * set the value.
64
+ *
65
+ * @param string $path Path to set
66
+ * @param mixed $value Value to set at the key
67
+ *
68
+ * @throws \RuntimeException when trying to setPath using a nested path
69
+ * that travels through a scalar value
70
+ */
71
+ public function setPath($path, $value)
72
+ {
73
+ Utils::setPath($this->data, $path, $value);
74
+ }
75
+ }
vendor/guzzlehttp/guzzle/src/Message/AbstractMessage.php ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Stream\StreamInterface;
5
+
6
+ abstract class AbstractMessage implements MessageInterface
7
+ {
8
+ /** @var array HTTP header collection */
9
+ private $headers = [];
10
+
11
+ /** @var array mapping a lowercase header name to its name over the wire */
12
+ private $headerNames = [];
13
+
14
+ /** @var StreamInterface Message body */
15
+ private $body;
16
+
17
+ /** @var string HTTP protocol version of the message */
18
+ private $protocolVersion = '1.1';
19
+
20
+ public function __toString()
21
+ {
22
+ return static::getStartLineAndHeaders($this)
23
+ . "\r\n\r\n" . $this->getBody();
24
+ }
25
+
26
+ public function getProtocolVersion()
27
+ {
28
+ return $this->protocolVersion;
29
+ }
30
+
31
+ public function getBody()
32
+ {
33
+ return $this->body;
34
+ }
35
+
36
+ public function setBody(StreamInterface $body = null)
37
+ {
38
+ if ($body === null) {
39
+ // Setting a null body will remove the body of the request
40
+ $this->removeHeader('Content-Length');
41
+ $this->removeHeader('Transfer-Encoding');
42
+ }
43
+
44
+ $this->body = $body;
45
+ }
46
+
47
+ public function addHeader($header, $value)
48
+ {
49
+ if (is_array($value)) {
50
+ $current = array_merge($this->getHeaderAsArray($header), $value);
51
+ } else {
52
+ $current = $this->getHeaderAsArray($header);
53
+ $current[] = (string) $value;
54
+ }
55
+
56
+ $this->setHeader($header, $current);
57
+ }
58
+
59
+ public function addHeaders(array $headers)
60
+ {
61
+ foreach ($headers as $name => $header) {
62
+ $this->addHeader($name, $header);
63
+ }
64
+ }
65
+
66
+ public function getHeader($header)
67
+ {
68
+ $name = strtolower($header);
69
+ return isset($this->headers[$name])
70
+ ? implode(', ', $this->headers[$name])
71
+ : '';
72
+ }
73
+
74
+ public function getHeaderAsArray($header)
75
+ {
76
+ $name = strtolower($header);
77
+ return isset($this->headers[$name]) ? $this->headers[$name] : [];
78
+ }
79
+
80
+ public function getHeaders()
81
+ {
82
+ $headers = [];
83
+ foreach ($this->headers as $name => $values) {
84
+ $headers[$this->headerNames[$name]] = $values;
85
+ }
86
+
87
+ return $headers;
88
+ }
89
+
90
+ public function setHeader($header, $value)
91
+ {
92
+ $header = trim($header);
93
+ $name = strtolower($header);
94
+ $this->headerNames[$name] = $header;
95
+
96
+ if (is_array($value)) {
97
+ foreach ($value as &$v) {
98
+ $v = trim($v);
99
+ }
100
+ $this->headers[$name] = $value;
101
+ } else {
102
+ $this->headers[$name] = [trim($value)];
103
+ }
104
+ }
105
+
106
+ public function setHeaders(array $headers)
107
+ {
108
+ $this->headers = $this->headerNames = [];
109
+ foreach ($headers as $key => $value) {
110
+ $this->addHeader($key, $value);
111
+ }
112
+ }
113
+
114
+ public function hasHeader($header)
115
+ {
116
+ return isset($this->headers[strtolower($header)]);
117
+ }
118
+
119
+ public function removeHeader($header)
120
+ {
121
+ $name = strtolower($header);
122
+ unset($this->headers[$name], $this->headerNames[$name]);
123
+ }
124
+
125
+ /**
126
+ * Parse an array of header values containing ";" separated data into an
127
+ * array of associative arrays representing the header key value pair
128
+ * data of the header. When a parameter does not contain a value, but just
129
+ * contains a key, this function will inject a key with a '' string value.
130
+ *
131
+ * @param MessageInterface $message That contains the header
132
+ * @param string $header Header to retrieve from the message
133
+ *
134
+ * @return array Returns the parsed header values.
135
+ */
136
+ public static function parseHeader(MessageInterface $message, $header)
137
+ {
138
+ static $trimmed = "\"' \n\t\r";
139
+ $params = $matches = [];
140
+
141
+ foreach (self::normalizeHeader($message, $header) as $val) {
142
+ $part = [];
143
+ foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
144
+ if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
145
+ $m = $matches[0];
146
+ if (isset($m[1])) {
147
+ $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);
148
+ } else {
149
+ $part[] = trim($m[0], $trimmed);
150
+ }
151
+ }
152
+ }
153
+ if ($part) {
154
+ $params[] = $part;
155
+ }
156
+ }
157
+
158
+ return $params;
159
+ }
160
+
161
+ /**
162
+ * Converts an array of header values that may contain comma separated
163
+ * headers into an array of headers with no comma separated values.
164
+ *
165
+ * @param MessageInterface $message That contains the header
166
+ * @param string $header Header to retrieve from the message
167
+ *
168
+ * @return array Returns the normalized header field values.
169
+ */
170
+ public static function normalizeHeader(MessageInterface $message, $header)
171
+ {
172
+ $h = $message->getHeaderAsArray($header);
173
+ for ($i = 0, $total = count($h); $i < $total; $i++) {
174
+ if (strpos($h[$i], ',') === false) {
175
+ continue;
176
+ }
177
+ foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $h[$i]) as $v) {
178
+ $h[] = trim($v);
179
+ }
180
+ unset($h[$i]);
181
+ }
182
+
183
+ return $h;
184
+ }
185
+
186
+ /**
187
+ * Gets the start-line and headers of a message as a string
188
+ *
189
+ * @param MessageInterface $message
190
+ *
191
+ * @return string
192
+ */
193
+ public static function getStartLineAndHeaders(MessageInterface $message)
194
+ {
195
+ return static::getStartLine($message)
196
+ . self::getHeadersAsString($message);
197
+ }
198
+
199
+ /**
200
+ * Gets the headers of a message as a string
201
+ *
202
+ * @param MessageInterface $message
203
+ *
204
+ * @return string
205
+ */
206
+ public static function getHeadersAsString(MessageInterface $message)
207
+ {
208
+ $result = '';
209
+ foreach ($message->getHeaders() as $name => $values) {
210
+ $result .= "\r\n{$name}: " . implode(', ', $values);
211
+ }
212
+
213
+ return $result;
214
+ }
215
+
216
+ /**
217
+ * Gets the start line of a message
218
+ *
219
+ * @param MessageInterface $message
220
+ *
221
+ * @return string
222
+ * @throws \InvalidArgumentException
223
+ */
224
+ public static function getStartLine(MessageInterface $message)
225
+ {
226
+ if ($message instanceof RequestInterface) {
227
+ return trim($message->getMethod() . ' '
228
+ . $message->getResource())
229
+ . ' HTTP/' . $message->getProtocolVersion();
230
+ } elseif ($message instanceof ResponseInterface) {
231
+ return 'HTTP/' . $message->getProtocolVersion() . ' '
232
+ . $message->getStatusCode() . ' '
233
+ . $message->getReasonPhrase();
234
+ } else {
235
+ throw new \InvalidArgumentException('Unknown message type');
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Accepts and modifies the options provided to the message in the
241
+ * constructor.
242
+ *
243
+ * Can be overridden in subclasses as necessary.
244
+ *
245
+ * @param array $options Options array passed by reference.
246
+ */
247
+ protected function handleOptions(array &$options)
248
+ {
249
+ if (isset($options['protocol_version'])) {
250
+ $this->protocolVersion = $options['protocol_version'];
251
+ }
252
+ }
253
+ }
vendor/guzzlehttp/guzzle/src/Message/AppliesHeadersInterface.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ /**
5
+ * Applies headers to a request.
6
+ *
7
+ * This interface can be used with Guzzle streams to apply body specific
8
+ * headers to a request during the PREPARE_REQUEST priority of the before event
9
+ *
10
+ * NOTE: a body that implements this interface will prevent a default
11
+ * content-type from being added to a request during the before event. If you
12
+ * want a default content-type to be added, then it will need to be done
13
+ * manually (e.g., using {@see GuzzleHttp\Mimetypes}).
14
+ */
15
+ interface AppliesHeadersInterface
16
+ {
17
+ /**
18
+ * Apply headers to a request appropriate for the current state of the
19
+ * object.
20
+ *
21
+ * @param RequestInterface $request Request
22
+ */
23
+ public function applyRequestHeaders(RequestInterface $request);
24
+ }
vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Ring\Future\MagicFutureTrait;
5
+ use GuzzleHttp\Ring\Future\FutureInterface;
6
+ use GuzzleHttp\Stream\StreamInterface;
7
+
8
+ /**
9
+ * Represents a response that has not been fulfilled.
10
+ *
11
+ * When created, you must provide a function that is used to dereference the
12
+ * future result and return it's value. The function has no arguments and MUST
13
+ * return an instance of a {@see GuzzleHttp\Message\ResponseInterface} object.
14
+ *
15
+ * You can optionally provide a function in the constructor that can be used to
16
+ * cancel the future from completing if possible. This function has no
17
+ * arguments and returns a boolean value representing whether or not the
18
+ * response could be cancelled.
19
+ *
20
+ * @property ResponseInterface $_value
21
+ */
22
+ class FutureResponse implements ResponseInterface, FutureInterface
23
+ {
24
+ use MagicFutureTrait;
25
+
26
+ /**
27
+ * Returns a FutureResponse that wraps another future.
28
+ *
29
+ * @param FutureInterface $future Future to wrap with a new future
30
+ * @param callable $onFulfilled Invoked when the future fulfilled
31
+ * @param callable $onRejected Invoked when the future rejected
32
+ * @param callable $onProgress Invoked when the future progresses
33
+ *
34
+ * @return FutureResponse
35
+ */
36
+ public static function proxy(
37
+ FutureInterface $future,
38
+ callable $onFulfilled = null,
39
+ callable $onRejected = null,
40
+ callable $onProgress = null
41
+ ) {
42
+ return new FutureResponse(
43
+ $future->then($onFulfilled, $onRejected, $onProgress),
44
+ [$future, 'wait'],
45
+ [$future, 'cancel']
46
+ );
47
+ }
48
+
49
+ public function getStatusCode()
50
+ {
51
+ return $this->_value->getStatusCode();
52
+ }
53
+
54
+ public function setStatusCode($code)
55
+ {
56
+ $this->_value->setStatusCode($code);
57
+ }
58
+
59
+ public function getReasonPhrase()
60
+ {
61
+ return $this->_value->getReasonPhrase();
62
+ }
63
+
64
+ public function setReasonPhrase($phrase)
65
+ {
66
+ $this->_value->setReasonPhrase($phrase);
67
+ }
68
+
69
+ public function getEffectiveUrl()
70
+ {
71
+ return $this->_value->getEffectiveUrl();
72
+ }
73
+
74
+ public function setEffectiveUrl($url)
75
+ {
76
+ $this->_value->setEffectiveUrl($url);
77
+ }
78
+
79
+ public function json(array $config = [])
80
+ {
81
+ return $this->_value->json($config);
82
+ }
83
+
84
+ public function xml(array $config = [])
85
+ {
86
+ return $this->_value->xml($config);
87
+ }
88
+
89
+ public function __toString()
90
+ {
91
+ try {
92
+ return $this->_value->__toString();
93
+ } catch (\Exception $e) {
94
+ trigger_error($e->getMessage(), E_USER_WARNING);
95
+ return '';
96
+ }
97
+ }
98
+
99
+ public function getProtocolVersion()
100
+ {
101
+ return $this->_value->getProtocolVersion();
102
+ }
103
+
104
+ public function setBody(StreamInterface $body = null)
105
+ {
106
+ $this->_value->setBody($body);
107
+ }
108
+
109
+ public function getBody()
110
+ {
111
+ return $this->_value->getBody();
112
+ }
113
+
114
+ public function getHeaders()
115
+ {
116
+ return $this->_value->getHeaders();
117
+ }
118
+
119
+ public function getHeader($header)
120
+ {
121
+ return $this->_value->getHeader($header);
122
+ }
123
+
124
+ public function getHeaderAsArray($header)
125
+ {
126
+ return $this->_value->getHeaderAsArray($header);
127
+ }
128
+
129
+ public function hasHeader($header)
130
+ {
131
+ return $this->_value->hasHeader($header);
132
+ }
133
+
134
+ public function removeHeader($header)
135
+ {
136
+ $this->_value->removeHeader($header);
137
+ }
138
+
139
+ public function addHeader($header, $value)
140
+ {
141
+ $this->_value->addHeader($header, $value);
142
+ }
143
+
144
+ public function addHeaders(array $headers)
145
+ {
146
+ $this->_value->addHeaders($headers);
147
+ }
148
+
149
+ public function setHeader($header, $value)
150
+ {
151
+ $this->_value->setHeader($header, $value);
152
+ }
153
+
154
+ public function setHeaders(array $headers)
155
+ {
156
+ $this->_value->setHeaders($headers);
157
+ }
158
+ }
vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Cookie\CookieJar;
5
+ use GuzzleHttp\Cookie\CookieJarInterface;
6
+ use GuzzleHttp\Event\ListenerAttacherTrait;
7
+ use GuzzleHttp\Post\PostBody;
8
+ use GuzzleHttp\Post\PostFile;
9
+ use GuzzleHttp\Post\PostFileInterface;
10
+ use GuzzleHttp\Query;
11
+ use GuzzleHttp\Stream\Stream;
12
+ use GuzzleHttp\Subscriber\Cookie;
13
+ use GuzzleHttp\Subscriber\HttpError;
14
+ use GuzzleHttp\Subscriber\Redirect;
15
+ use GuzzleHttp\Url;
16
+ use \InvalidArgumentException as Iae;
17
+
18
+ /**
19
+ * Default HTTP request factory used to create Request and Response objects.
20
+ */
21
+ class MessageFactory implements MessageFactoryInterface
22
+ {
23
+ use ListenerAttacherTrait;
24
+
25
+ /** @var HttpError */
26
+ private $errorPlugin;
27
+
28
+ /** @var Redirect */
29
+ private $redirectPlugin;
30
+
31
+ /** @var array */
32
+ private $customOptions;
33
+
34
+ /** @var array Request options passed through to request Config object */
35
+ private static $configMap = [
36
+ 'connect_timeout' => 1, 'timeout' => 1, 'verify' => 1, 'ssl_key' => 1,
37
+ 'cert' => 1, 'proxy' => 1, 'debug' => 1, 'save_to' => 1, 'stream' => 1,
38
+ 'expect' => 1, 'future' => 1
39
+ ];
40
+
41
+ /** @var array Default allow_redirects request option settings */
42
+ private static $defaultRedirect = [
43
+ 'max' => 5,
44
+ 'strict' => false,
45
+ 'referer' => false,
46
+ 'protocols' => ['http', 'https']
47
+ ];
48
+
49
+ /**
50
+ * @param array $customOptions Associative array of custom request option
51
+ * names mapping to functions used to apply
52
+ * the option. The function accepts the request
53
+ * and the option value to apply.
54
+ */
55
+ public function __construct(array $customOptions = [])
56
+ {
57
+ $this->errorPlugin = new HttpError();
58
+ $this->redirectPlugin = new Redirect();
59
+ $this->customOptions = $customOptions;
60
+ }
61
+
62
+ public function createResponse(
63
+ $statusCode,
64
+ array $headers = [],
65
+ $body = null,
66
+ array $options = []
67
+ ) {
68
+ if (null !== $body) {
69
+ $body = Stream::factory($body);
70
+ }
71
+
72
+ return new Response($statusCode, $headers, $body, $options);
73
+ }
74
+
75
+ public function createRequest($method, $url, array $options = [])
76
+ {
77
+ // Handle the request protocol version option that needs to be
78
+ // specified in the request constructor.
79
+ if (isset($options['version'])) {
80
+ $options['config']['protocol_version'] = $options['version'];
81
+ unset($options['version']);
82
+ }
83
+
84
+ $request = new Request($method, $url, [], null,
85
+ isset($options['config']) ? $options['config'] : []);
86
+
87
+ unset($options['config']);
88
+
89
+ // Use a POST body by default
90
+ if (strtoupper($method) == 'POST'
91
+ && !isset($options['body'])
92
+ && !isset($options['json'])
93
+ ) {
94
+ $options['body'] = [];
95
+ }
96
+
97
+ if ($options) {
98
+ $this->applyOptions($request, $options);
99
+ }
100
+
101
+ return $request;
102
+ }
103
+
104
+ /**
105
+ * Create a request or response object from an HTTP message string
106
+ *
107
+ * @param string $message Message to parse
108
+ *
109
+ * @return RequestInterface|ResponseInterface
110
+ * @throws \InvalidArgumentException if unable to parse a message
111
+ */
112
+ public function fromMessage($message)
113
+ {
114
+ static $parser;
115
+ if (!$parser) {
116
+ $parser = new MessageParser();
117
+ }
118
+
119
+ // Parse a response
120
+ if (strtoupper(substr($message, 0, 4)) == 'HTTP') {
121
+ $data = $parser->parseResponse($message);
122
+ return $this->createResponse(
123
+ $data['code'],
124
+ $data['headers'],
125
+ $data['body'] === '' ? null : $data['body'],
126
+ $data
127
+ );
128
+ }
129
+
130
+ // Parse a request
131
+ if (!($data = ($parser->parseRequest($message)))) {
132
+ throw new \InvalidArgumentException('Unable to parse request');
133
+ }
134
+
135
+ return $this->createRequest(
136
+ $data['method'],
137
+ Url::buildUrl($data['request_url']),
138
+ [
139
+ 'headers' => $data['headers'],
140
+ 'body' => $data['body'] === '' ? null : $data['body'],
141
+ 'config' => [
142
+ 'protocol_version' => $data['protocol_version']
143
+ ]
144
+ ]
145
+ );
146
+ }
147
+
148
+ /**
149
+ * Apply POST fields and files to a request to attempt to give an accurate
150
+ * representation.
151
+ *
152
+ * @param RequestInterface $request Request to update
153
+ * @param array $body Body to apply
154
+ */
155
+ protected function addPostData(RequestInterface $request, array $body)
156
+ {
157
+ static $fields = ['string' => true, 'array' => true, 'NULL' => true,
158
+ 'boolean' => true, 'double' => true, 'integer' => true];
159
+
160
+ $post = new PostBody();
161
+ foreach ($body as $key => $value) {
162
+ if (isset($fields[gettype($value)])) {
163
+ $post->setField($key, $value);
164
+ } elseif ($value instanceof PostFileInterface) {
165
+ $post->addFile($value);
166
+ } else {
167
+ $post->addFile(new PostFile($key, $value));
168
+ }
169
+ }
170
+
171
+ if ($request->getHeader('Content-Type') == 'multipart/form-data') {
172
+ $post->forceMultipartUpload(true);
173
+ }
174
+
175
+ $request->setBody($post);
176
+ }
177
+
178
+ protected function applyOptions(
179
+ RequestInterface $request,
180
+ array $options = []
181
+ ) {
182
+ $config = $request->getConfig();
183
+ $emitter = $request->getEmitter();
184
+
185
+ foreach ($options as $key => $value) {
186
+
187
+ if (isset(self::$configMap[$key])) {
188
+ $config[$key] = $value;
189
+ continue;
190
+ }
191
+
192
+ switch ($key) {
193
+
194
+ case 'allow_redirects':
195
+
196
+ if ($value === false) {
197
+ continue 2;
198
+ }
199
+
200
+ if ($value === true) {
201
+ $value = self::$defaultRedirect;
202
+ } elseif (!is_array($value)) {
203
+ throw new Iae('allow_redirects must be true, false, or array');
204
+ } else {
205
+ // Merge the default settings with the provided settings
206
+ $value += self::$defaultRedirect;
207
+ }
208
+
209
+ $config['redirect'] = $value;
210
+ $emitter->attach($this->redirectPlugin);
211
+ break;
212
+
213
+ case 'decode_content':
214
+
215
+ if ($value === false) {
216
+ continue 2;
217
+ }
218
+
219
+ $config['decode_content'] = true;
220
+ if ($value !== true) {
221
+ $request->setHeader('Accept-Encoding', $value);
222
+ }
223
+ break;
224
+
225
+ case 'headers':
226
+
227
+ if (!is_array($value)) {
228
+ throw new Iae('header value must be an array');
229
+ }
230
+ foreach ($value as $k => $v) {
231
+ $request->setHeader($k, $v);
232
+ }
233
+ break;
234
+
235
+ case 'exceptions':
236
+
237
+ if ($value === true) {
238
+ $emitter->attach($this->errorPlugin);
239
+ }
240
+ break;
241
+
242
+ case 'body':
243
+
244
+ if (is_array($value)) {
245
+ $this->addPostData($request, $value);
246
+ } elseif ($value !== null) {
247
+ $request->setBody(Stream::factory($value));
248
+ }
249
+ break;
250
+
251
+ case 'auth':
252
+
253
+ if (!$value) {
254
+ continue 2;
255
+ }
256
+
257
+ if (is_array($value)) {
258
+ $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
259
+ } else {
260
+ $type = strtolower($value);
261
+ }
262
+
263
+ $config['auth'] = $value;
264
+
265
+ if ($type == 'basic') {
266
+ $request->setHeader(
267
+ 'Authorization',
268
+ 'Basic ' . base64_encode("$value[0]:$value[1]")
269
+ );
270
+ } elseif ($type == 'digest') {
271
+ // @todo: Do not rely on curl
272
+ $config->setPath('curl/' . CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
273
+ $config->setPath('curl/' . CURLOPT_USERPWD, "$value[0]:$value[1]");
274
+ }
275
+ break;
276
+
277
+ case 'query':
278
+
279
+ if ($value instanceof Query) {
280
+ $original = $request->getQuery();
281
+ // Do not overwrite existing query string variables by
282
+ // overwriting the object with the query string data passed
283
+ // in the URL
284
+ $value->overwriteWith($original->toArray());
285
+ $request->setQuery($value);
286
+ } elseif (is_array($value)) {
287
+ // Do not overwrite existing query string variables
288
+ $query = $request->getQuery();
289
+ foreach ($value as $k => $v) {
290
+ if (!isset($query[$k])) {
291
+ $query[$k] = $v;
292
+ }
293
+ }
294
+ } else {
295
+ throw new Iae('query must be an array or Query object');
296
+ }
297
+ break;
298
+
299
+ case 'cookies':
300
+
301
+ if ($value === true) {
302
+ static $cookie = null;
303
+ if (!$cookie) {
304
+ $cookie = new Cookie();
305
+ }
306
+ $emitter->attach($cookie);
307
+ } elseif (is_array($value)) {
308
+ $emitter->attach(
309
+ new Cookie(CookieJar::fromArray($value, $request->getHost()))
310
+ );
311
+ } elseif ($value instanceof CookieJarInterface) {
312
+ $emitter->attach(new Cookie($value));
313
+ } elseif ($value !== false) {
314
+ throw new Iae('cookies must be an array, true, or CookieJarInterface');
315
+ }
316
+ break;
317
+
318
+ case 'events':
319
+
320
+ if (!is_array($value)) {
321
+ throw new Iae('events must be an array');
322
+ }
323
+
324
+ $this->attachListeners($request,
325
+ $this->prepareListeners(
326
+ $value,
327
+ ['before', 'complete', 'error', 'progress', 'end']
328
+ )
329
+ );
330
+ break;
331
+
332
+ case 'subscribers':
333
+
334
+ if (!is_array($value)) {
335
+ throw new Iae('subscribers must be an array');
336
+ }
337
+
338
+ foreach ($value as $subscribers) {
339
+ $emitter->attach($subscribers);
340
+ }
341
+ break;
342
+
343
+ case 'json':
344
+
345
+ $request->setBody(Stream::factory(json_encode($value)));
346
+ if (!$request->hasHeader('Content-Type')) {
347
+ $request->setHeader('Content-Type', 'application/json');
348
+ }
349
+ break;
350
+
351
+ default:
352
+
353
+ // Check for custom handler functions.
354
+ if (isset($this->customOptions[$key])) {
355
+ $fn = $this->customOptions[$key];
356
+ $fn($request, $value);
357
+ continue 2;
358
+ }
359
+
360
+ throw new Iae("No method can handle the {$key} config key");
361
+ }
362
+ }
363
+ }
364
+ }
vendor/guzzlehttp/guzzle/src/Message/MessageFactoryInterface.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Url;
5
+
6
+ /**
7
+ * Request and response factory
8
+ */
9
+ interface MessageFactoryInterface
10
+ {
11
+ /**
12
+ * Creates a response
13
+ *
14
+ * @param string $statusCode HTTP status code
15
+ * @param array $headers Response headers
16
+ * @param mixed $body Response body
17
+ * @param array $options Response options
18
+ * - protocol_version: HTTP protocol version
19
+ * - header_factory: Factory used to create headers
20
+ * - And any other options used by a concrete message implementation
21
+ *
22
+ * @return ResponseInterface
23
+ */
24
+ public function createResponse(
25
+ $statusCode,
26
+ array $headers = [],
27
+ $body = null,
28
+ array $options = []
29
+ );
30
+
31
+ /**
32
+ * Create a new request based on the HTTP method.
33
+ *
34
+ * This method accepts an associative array of request options. Below is a
35
+ * brief description of each parameter. See
36
+ * http://docs.guzzlephp.org/en/latest/clients.html#request-options for a much more
37
+ * in-depth description of each parameter.
38
+ *
39
+ * - headers: Associative array of headers to add to the request
40
+ * - body: string|resource|array|StreamInterface request body to send
41
+ * - json: mixed Uploads JSON encoded data using an application/json Content-Type header.
42
+ * - query: Associative array of query string values to add to the request
43
+ * - auth: array|string HTTP auth settings (user, pass[, type="basic"])
44
+ * - version: The HTTP protocol version to use with the request
45
+ * - cookies: true|false|CookieJarInterface To enable or disable cookies
46
+ * - allow_redirects: true|false|array Controls HTTP redirects
47
+ * - save_to: string|resource|StreamInterface Where the response is saved
48
+ * - events: Associative array of event names to callables or arrays
49
+ * - subscribers: Array of event subscribers to add to the request
50
+ * - exceptions: Specifies whether or not exceptions are thrown for HTTP protocol errors
51
+ * - timeout: Timeout of the request in seconds. Use 0 to wait indefinitely
52
+ * - connect_timeout: Number of seconds to wait while trying to connect. (0 to wait indefinitely)
53
+ * - verify: SSL validation. True/False or the path to a PEM file
54
+ * - cert: Path a SSL cert or array of (path, pwd)
55
+ * - ssl_key: Path to a private SSL key or array of (path, pwd)
56
+ * - proxy: Specify an HTTP proxy or hash of protocols to proxies
57
+ * - debug: Set to true or a resource to view handler specific debug info
58
+ * - stream: Set to true to stream a response body rather than download it all up front
59
+ * - expect: true/false/integer Controls the "Expect: 100-Continue" header
60
+ * - config: Associative array of request config collection options
61
+ * - decode_content: true/false/string to control decoding content-encoding responses
62
+ *
63
+ * @param string $method HTTP method (GET, POST, PUT, etc.)
64
+ * @param string|Url $url HTTP URL to connect to
65
+ * @param array $options Array of options to apply to the request
66
+ *
67
+ * @return RequestInterface
68
+ * @link http://docs.guzzlephp.org/en/latest/clients.html#request-options
69
+ */
70
+ public function createRequest($method, $url, array $options = []);
71
+ }
vendor/guzzlehttp/guzzle/src/Message/MessageInterface.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Stream\StreamInterface;
5
+
6
+ /**
7
+ * Request and response message interface
8
+ */
9
+ interface MessageInterface
10
+ {
11
+ /**
12
+ * Get a string representation of the message
13
+ *
14
+ * @return string
15
+ */
16
+ public function __toString();
17
+
18
+ /**
19
+ * Get the HTTP protocol version of the message
20
+ *
21
+ * @return string
22
+ */
23
+ public function getProtocolVersion();
24
+
25
+ /**
26
+ * Sets the body of the message.
27
+ *
28
+ * The body MUST be a StreamInterface object. Setting the body to null MUST
29
+ * remove the existing body.
30
+ *
31
+ * @param StreamInterface|null $body Body.
32
+ */
33
+ public function setBody(StreamInterface $body = null);
34
+
35
+ /**
36
+ * Get the body of the message
37
+ *
38
+ * @return StreamInterface|null
39
+ */
40
+ public function getBody();
41
+
42
+ /**
43
+ * Gets all message headers.
44
+ *
45
+ * The keys represent the header name as it will be sent over the wire, and
46
+ * each value is an array of strings associated with the header.
47
+ *
48
+ * // Represent the headers as a string
49
+ * foreach ($message->getHeaders() as $name => $values) {
50
+ * echo $name . ": " . implode(", ", $values);
51
+ * }
52
+ *
53
+ * @return array Returns an associative array of the message's headers.
54
+ */
55
+ public function getHeaders();
56
+
57
+ /**
58
+ * Retrieve a header by the given case-insensitive name.
59
+ *
60
+ * @param string $header Case-insensitive header name.
61
+ *
62
+ * @return string
63
+ */
64
+ public function getHeader($header);
65
+
66
+ /**
67
+ * Retrieves a header by the given case-insensitive name as an array of strings.
68
+ *
69
+ * @param string $header Case-insensitive header name.
70
+ *
71
+ * @return string[]
72
+ */
73
+ public function getHeaderAsArray($header);
74
+
75
+ /**
76
+ * Checks if a header exists by the given case-insensitive name.
77
+ *
78
+ * @param string $header Case-insensitive header name.
79
+ *
80
+ * @return bool Returns true if any header names match the given header
81
+ * name using a case-insensitive string comparison. Returns false if
82
+ * no matching header name is found in the message.
83
+ */
84
+ public function hasHeader($header);
85
+
86
+ /**
87
+ * Remove a specific header by case-insensitive name.
88
+ *
89
+ * @param string $header Case-insensitive header name.
90
+ */
91
+ public function removeHeader($header);
92
+
93
+ /**
94
+ * Appends a header value to any existing values associated with the
95
+ * given header name.
96
+ *
97
+ * @param string $header Header name to add
98
+ * @param string $value Value of the header
99
+ */
100
+ public function addHeader($header, $value);
101
+
102
+ /**
103
+ * Merges in an associative array of headers.
104
+ *
105
+ * Each array key MUST be a string representing the case-insensitive name
106
+ * of a header. Each value MUST be either a string or an array of strings.
107
+ * For each value, the value is appended to any existing header of the same
108
+ * name, or, if a header does not already exist by the given name, then the
109
+ * header is added.
110
+ *
111
+ * @param array $headers Associative array of headers to add to the message
112
+ */
113
+ public function addHeaders(array $headers);
114
+
115
+ /**
116
+ * Sets a header, replacing any existing values of any headers with the
117
+ * same case-insensitive name.
118
+ *
119
+ * The header values MUST be a string or an array of strings.
120
+ *
121
+ * @param string $header Header name
122
+ * @param string|array $value Header value(s)
123
+ */
124
+ public function setHeader($header, $value);
125
+
126
+ /**
127
+ * Sets headers, replacing any headers that have already been set on the
128
+ * message.
129
+ *
130
+ * The array keys MUST be a string. The array values must be either a
131
+ * string or an array of strings.
132
+ *
133
+ * @param array $headers Headers to set.
134
+ */
135
+ public function setHeaders(array $headers);
136
+ }
vendor/guzzlehttp/guzzle/src/Message/MessageParser.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ /**
5
+ * Request and response parser used by Guzzle
6
+ */
7
+ class MessageParser
8
+ {
9
+ /**
10
+ * Parse an HTTP request message into an associative array of parts.
11
+ *
12
+ * @param string $message HTTP request to parse
13
+ *
14
+ * @return array|bool Returns false if the message is invalid
15
+ */
16
+ public function parseRequest($message)
17
+ {
18
+ if (!($parts = $this->parseMessage($message))) {
19
+ return false;
20
+ }
21
+
22
+ // Parse the protocol and protocol version
23
+ if (isset($parts['start_line'][2])) {
24
+ $startParts = explode('/', $parts['start_line'][2]);
25
+ $protocol = strtoupper($startParts[0]);
26
+ $version = isset($startParts[1]) ? $startParts[1] : '1.1';
27
+ } else {
28
+ $protocol = 'HTTP';
29
+ $version = '1.1';
30
+ }
31
+
32
+ $parsed = [
33
+ 'method' => strtoupper($parts['start_line'][0]),
34
+ 'protocol' => $protocol,
35
+ 'protocol_version' => $version,
36
+ 'headers' => $parts['headers'],
37
+ 'body' => $parts['body']
38
+ ];
39
+
40
+ $parsed['request_url'] = $this->getUrlPartsFromMessage(
41
+ (isset($parts['start_line'][1]) ? $parts['start_line'][1] : ''), $parsed);
42
+
43
+ return $parsed;
44
+ }
45
+
46
+ /**
47
+ * Parse an HTTP response message into an associative array of parts.
48
+ *
49
+ * @param string $message HTTP response to parse
50
+ *
51
+ * @return array|bool Returns false if the message is invalid
52
+ */
53
+ public function parseResponse($message)
54
+ {
55
+ if (!($parts = $this->parseMessage($message))) {
56
+ return false;
57
+ }
58
+
59
+ list($protocol, $version) = explode('/', trim($parts['start_line'][0]));
60
+
61
+ return [
62
+ 'protocol' => $protocol,
63
+ 'protocol_version' => $version,
64
+ 'code' => $parts['start_line'][1],
65
+ 'reason_phrase' => isset($parts['start_line'][2]) ? $parts['start_line'][2] : '',
66
+ 'headers' => $parts['headers'],
67
+ 'body' => $parts['body']
68
+ ];
69
+ }
70
+
71
+ /**
72
+ * Parse a message into parts
73
+ *
74
+ * @param string $message Message to parse
75
+ *
76
+ * @return array|bool
77
+ */
78
+ private function parseMessage($message)
79
+ {
80
+ if (!$message) {
81
+ return false;
82
+ }
83
+
84
+ $startLine = null;
85
+ $headers = [];
86
+ $body = '';
87
+
88
+ // Iterate over each line in the message, accounting for line endings
89
+ $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
90
+ for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
91
+
92
+ $line = $lines[$i];
93
+
94
+ // If two line breaks were encountered, then this is the end of body
95
+ if (empty($line)) {
96
+ if ($i < $totalLines - 1) {
97
+ $body = implode('', array_slice($lines, $i + 2));
98
+ }
99
+ break;
100
+ }
101
+
102
+ // Parse message headers
103
+ if (!$startLine) {
104
+ $startLine = explode(' ', $line, 3);
105
+ } elseif (strpos($line, ':')) {
106
+ $parts = explode(':', $line, 2);
107
+ $key = trim($parts[0]);
108
+ $value = isset($parts[1]) ? trim($parts[1]) : '';
109
+ if (!isset($headers[$key])) {
110
+ $headers[$key] = $value;
111
+ } elseif (!is_array($headers[$key])) {
112
+ $headers[$key] = [$headers[$key], $value];
113
+ } else {
114
+ $headers[$key][] = $value;
115
+ }
116
+ }
117
+ }
118
+
119
+ return [
120
+ 'start_line' => $startLine,
121
+ 'headers' => $headers,
122
+ 'body' => $body
123
+ ];
124
+ }
125
+
126
+ /**
127
+ * Create URL parts from HTTP message parts
128
+ *
129
+ * @param string $requestUrl Associated URL
130
+ * @param array $parts HTTP message parts
131
+ *
132
+ * @return array
133
+ */
134
+ private function getUrlPartsFromMessage($requestUrl, array $parts)
135
+ {
136
+ // Parse the URL information from the message
137
+ $urlParts = ['path' => $requestUrl, 'scheme' => 'http'];
138
+
139
+ // Check for the Host header
140
+ if (isset($parts['headers']['Host'])) {
141
+ $urlParts['host'] = $parts['headers']['Host'];
142
+ } elseif (isset($parts['headers']['host'])) {
143
+ $urlParts['host'] = $parts['headers']['host'];
144
+ } else {
145
+ $urlParts['host'] = null;
146
+ }
147
+
148
+ if (false === strpos($urlParts['host'], ':')) {
149
+ $urlParts['port'] = '';
150
+ } else {
151
+ $hostParts = explode(':', $urlParts['host']);
152
+ $urlParts['host'] = trim($hostParts[0]);
153
+ $urlParts['port'] = (int) trim($hostParts[1]);
154
+ if ($urlParts['port'] == 443) {
155
+ $urlParts['scheme'] = 'https';
156
+ }
157
+ }
158
+
159
+ // Check if a query is present
160
+ $path = $urlParts['path'];
161
+ $qpos = strpos($path, '?');
162
+ if ($qpos) {
163
+ $urlParts['query'] = substr($path, $qpos + 1);
164
+ $urlParts['path'] = substr($path, 0, $qpos);
165
+ } else {
166
+ $urlParts['query'] = '';
167
+ }
168
+
169
+ return $urlParts;
170
+ }
171
+ }
vendor/guzzlehttp/guzzle/src/Message/Request.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Collection;
5
+ use GuzzleHttp\Event\HasEmitterTrait;
6
+ use GuzzleHttp\Subscriber\Prepare;
7
+ use GuzzleHttp\Url;
8
+
9
+ /**
10
+ * HTTP request class to send requests
11
+ */
12
+ class Request extends AbstractMessage implements RequestInterface
13
+ {
14
+ use HasEmitterTrait;
15
+
16
+ /** @var Url HTTP Url */
17
+ private $url;
18
+
19
+ /** @var string HTTP method */
20
+ private $method;
21
+
22
+ /** @var Collection Transfer options */
23
+ private $transferOptions;
24
+
25
+ /**
26
+ * @param string $method HTTP method
27
+ * @param string|Url $url HTTP URL to connect to. The URI scheme,
28
+ * host header, and URI are parsed from the full URL. If query string
29
+ * parameters are present they will be parsed as well.
30
+ * @param array|Collection $headers HTTP headers
31
+ * @param mixed $body Body to send with the request
32
+ * @param array $options Array of options to use with the request
33
+ * - emitter: Event emitter to use with the request
34
+ */
35
+ public function __construct(
36
+ $method,
37
+ $url,
38
+ $headers = [],
39
+ $body = null,
40
+ array $options = []
41
+ ) {
42
+ $this->setUrl($url);
43
+ $this->method = strtoupper($method);
44
+ $this->handleOptions($options);
45
+ $this->transferOptions = new Collection($options);
46
+ $this->addPrepareEvent();
47
+
48
+ if ($body !== null) {
49
+ $this->setBody($body);
50
+ }
51
+
52
+ if ($headers) {
53
+ foreach ($headers as $key => $value) {
54
+ $this->addHeader($key, $value);
55
+ }
56
+ }
57
+ }
58
+
59
+ public function __clone()
60
+ {
61
+ if ($this->emitter) {
62
+ $this->emitter = clone $this->emitter;
63
+ }
64
+ $this->transferOptions = clone $this->transferOptions;
65
+ $this->url = clone $this->url;
66
+ }
67
+
68
+ public function setUrl($url)
69
+ {
70
+ $this->url = $url instanceof Url ? $url : Url::fromString($url);
71
+ $this->updateHostHeaderFromUrl();
72
+ }
73
+
74
+ public function getUrl()
75
+ {
76
+ return (string) $this->url;
77
+ }
78
+
79
+ public function setQuery($query)
80
+ {
81
+ $this->url->setQuery($query);
82
+ }
83
+
84
+ public function getQuery()
85
+ {
86
+ return $this->url->getQuery();
87
+ }
88
+
89
+ public function setMethod($method)
90
+ {
91
+ $this->method = strtoupper($method);
92
+ }
93
+
94
+ public function getMethod()
95
+ {
96
+ return $this->method;
97
+ }
98
+
99
+ public function getScheme()
100
+ {
101
+ return $this->url->getScheme();
102
+ }
103
+
104
+ public function setScheme($scheme)
105
+ {
106
+ $this->url->setScheme($scheme);
107
+ }
108
+
109
+ public function getPort()
110
+ {
111
+ return $this->url->getPort();
112
+ }
113
+
114
+ public function setPort($port)
115
+ {
116
+ $this->url->setPort($port);
117
+ $this->updateHostHeaderFromUrl();
118
+ }
119
+
120
+ public function getHost()
121
+ {
122
+ return $this->url->getHost();
123
+ }
124
+
125
+ public function setHost($host)
126
+ {
127
+ $this->url->setHost($host);
128
+ $this->updateHostHeaderFromUrl();
129
+ }
130
+
131
+ public function getPath()
132
+ {
133
+ return '/' . ltrim($this->url->getPath(), '/');
134
+ }
135
+
136
+ public function setPath($path)
137
+ {
138
+ $this->url->setPath($path);
139
+ }
140
+
141
+ public function getResource()
142
+ {
143
+ $resource = $this->getPath();
144
+ if ($query = (string) $this->url->getQuery()) {
145
+ $resource .= '?' . $query;
146
+ }
147
+
148
+ return $resource;
149
+ }
150
+
151
+ public function getConfig()
152
+ {
153
+ return $this->transferOptions;
154
+ }
155
+
156
+ protected function handleOptions(array &$options)
157
+ {
158
+ parent::handleOptions($options);
159
+ // Use a custom emitter if one is specified, and remove it from
160
+ // options that are exposed through getConfig()
161
+ if (isset($options['emitter'])) {
162
+ $this->emitter = $options['emitter'];
163
+ unset($options['emitter']);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Adds a subscriber that ensures a request's body is prepared before
169
+ * sending.
170
+ */
171
+ private function addPrepareEvent()
172
+ {
173
+ static $subscriber;
174
+ if (!$subscriber) {
175
+ $subscriber = new Prepare();
176
+ }
177
+
178
+ $this->getEmitter()->attach($subscriber);
179
+ }
180
+
181
+ private function updateHostHeaderFromUrl()
182
+ {
183
+ $port = $this->url->getPort();
184
+ $scheme = $this->url->getScheme();
185
+ if ($host = $this->url->getHost()) {
186
+ if (($port == 80 && $scheme == 'http') ||
187
+ ($port == 443 && $scheme == 'https')
188
+ ) {
189
+ $this->setHeader('Host', $host);
190
+ } else {
191
+ $this->setHeader('Host', "{$host}:{$port}");
192
+ }
193
+ }
194
+ }
195
+ }
vendor/guzzlehttp/guzzle/src/Message/RequestInterface.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Event\HasEmitterInterface;
5
+ use GuzzleHttp\Query;
6
+
7
+ /**
8
+ * Generic HTTP request interface
9
+ */
10
+ interface RequestInterface extends MessageInterface, HasEmitterInterface
11
+ {
12
+ /**
13
+ * Sets the request URL.
14
+ *
15
+ * The URL MUST be a string, or an object that implements the
16
+ * `__toString()` method.
17
+ *
18
+ * @param string $url Request URL.
19
+ *
20
+ * @throws \InvalidArgumentException If the URL is invalid.
21
+ */
22
+ public function setUrl($url);
23
+
24
+ /**
25
+ * Gets the request URL as a string.
26
+ *
27
+ * @return string Returns the URL as a string.
28
+ */
29
+ public function getUrl();
30
+
31
+ /**
32
+ * Get the resource part of the the request, including the path, query
33
+ * string, and fragment.
34
+ *
35
+ * @return string
36
+ */
37
+ public function getResource();
38
+
39
+ /**
40
+ * Get the collection of key value pairs that will be used as the query
41
+ * string in the request.
42
+ *
43
+ * @return Query
44
+ */
45
+ public function getQuery();
46
+
47
+ /**
48
+ * Set the query string used by the request
49
+ *
50
+ * @param array|Query $query Query to set
51
+ */
52
+ public function setQuery($query);
53
+
54
+ /**
55
+ * Get the HTTP method of the request.
56
+ *
57
+ * @return string
58
+ */
59
+ public function getMethod();
60
+
61
+ /**
62
+ * Set the HTTP method of the request.
63
+ *
64
+ * @param string $method HTTP method
65
+ */
66
+ public function setMethod($method);
67
+
68
+ /**
69
+ * Get the URI scheme of the request (http, https, etc.).
70
+ *
71
+ * @return string
72
+ */
73
+ public function getScheme();
74
+
75
+ /**
76
+ * Set the URI scheme of the request (http, https, etc.).
77
+ *
78
+ * @param string $scheme Scheme to set
79
+ */
80
+ public function setScheme($scheme);
81
+
82
+ /**
83
+ * Get the port scheme of the request (e.g., 80, 443, etc.).
84
+ *
85
+ * @return int
86
+ */
87
+ public function getPort();
88
+
89
+ /**
90
+ * Set the port of the request.
91
+ *
92
+ * Setting a port modifies the Host header of a request as necessary.
93
+ *
94
+ * @param int $port Port to set
95
+ */
96
+ public function setPort($port);
97
+
98
+ /**
99
+ * Get the host of the request.
100
+ *
101
+ * @return string
102
+ */
103
+ public function getHost();
104
+
105
+ /**
106
+ * Set the host of the request including an optional port.
107
+ *
108
+ * Including a port in the host argument will explicitly change the port of
109
+ * the request. If no port is found, the default port of the current
110
+ * request scheme will be utilized.
111
+ *
112
+ * @param string $host Host to set (e.g. www.yahoo.com, www.yahoo.com:80)
113
+ */
114
+ public function setHost($host);
115
+
116
+ /**
117
+ * Get the path of the request (e.g. '/', '/index.html').
118
+ *
119
+ * @return string
120
+ */
121
+ public function getPath();
122
+
123
+ /**
124
+ * Set the path of the request (e.g. '/', '/index.html').
125
+ *
126
+ * @param string|array $path Path to set or array of segments to implode
127
+ */
128
+ public function setPath($path);
129
+
130
+ /**
131
+ * Get the request's configuration options.
132
+ *
133
+ * @return \GuzzleHttp\Collection
134
+ */
135
+ public function getConfig();
136
+ }
vendor/guzzlehttp/guzzle/src/Message/Response.php ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ use GuzzleHttp\Exception\ParseException;
5
+ use GuzzleHttp\Exception\XmlParseException;
6
+ use GuzzleHttp\Stream\StreamInterface;
7
+ use GuzzleHttp\Utils;
8
+
9
+ /**
10
+ * Guzzle HTTP response object
11
+ */
12
+ class Response extends AbstractMessage implements ResponseInterface
13
+ {
14
+ /** @var array Mapping of status codes to reason phrases */
15
+ private static $statusTexts = [
16
+ 100 => 'Continue',
17
+ 101 => 'Switching Protocols',
18
+ 102 => 'Processing',
19
+ 200 => 'OK',
20
+ 201 => 'Created',
21
+ 202 => 'Accepted',
22
+ 203 => 'Non-Authoritative Information',
23
+ 204 => 'No Content',
24
+ 205 => 'Reset Content',
25
+ 206 => 'Partial Content',
26
+ 207 => 'Multi-Status',
27
+ 208 => 'Already Reported',
28
+ 226 => 'IM Used',
29
+ 300 => 'Multiple Choices',
30
+ 301 => 'Moved Permanently',
31
+ 302 => 'Found',
32
+ 303 => 'See Other',
33
+ 304 => 'Not Modified',
34
+ 305 => 'Use Proxy',
35
+ 307 => 'Temporary Redirect',
36
+ 308 => 'Permanent Redirect',
37
+ 400 => 'Bad Request',
38
+ 401 => 'Unauthorized',
39
+ 402 => 'Payment Required',
40
+ 403 => 'Forbidden',
41
+ 404 => 'Not Found',
42
+ 405 => 'Method Not Allowed',
43
+ 406 => 'Not Acceptable',
44
+ 407 => 'Proxy Authentication Required',
45
+ 408 => 'Request Timeout',
46
+ 409 => 'Conflict',
47
+ 410 => 'Gone',
48
+ 411 => 'Length Required',
49
+ 412 => 'Precondition Failed',
50
+ 413 => 'Request Entity Too Large',
51
+ 414 => 'Request-URI Too Long',
52
+ 415 => 'Unsupported Media Type',
53
+ 416 => 'Requested Range Not Satisfiable',
54
+ 417 => 'Expectation Failed',
55
+ 422 => 'Unprocessable Entity',
56
+ 423 => 'Locked',
57
+ 424 => 'Failed Dependency',
58
+ 425 => 'Reserved for WebDAV advanced collections expired proposal',
59
+ 426 => 'Upgrade required',
60
+ 428 => 'Precondition Required',
61
+ 429 => 'Too Many Requests',
62
+ 431 => 'Request Header Fields Too Large',
63
+ 500 => 'Internal Server Error',
64
+ 501 => 'Not Implemented',
65
+ 502 => 'Bad Gateway',
66
+ 503 => 'Service Unavailable',
67
+ 504 => 'Gateway Timeout',
68
+ 505 => 'HTTP Version Not Supported',
69
+ 506 => 'Variant Also Negotiates (Experimental)',
70
+ 507 => 'Insufficient Storage',
71
+ 508 => 'Loop Detected',
72
+ 510 => 'Not Extended',
73
+ 511 => 'Network Authentication Required',
74
+ ];
75
+
76
+ /** @var string The reason phrase of the response (human readable code) */
77
+ private $reasonPhrase;
78
+
79
+ /** @var string The status code of the response */
80
+ private $statusCode;
81
+
82
+ /** @var string The effective URL that returned this response */
83
+ private $effectiveUrl;
84
+
85
+ /**
86
+ * @param int|string $statusCode The response status code (e.g. 200)
87
+ * @param array $headers The response headers
88
+ * @param StreamInterface $body The body of the response
89
+ * @param array $options Response message options
90
+ * - reason_phrase: Set a custom reason phrase
91
+ * - protocol_version: Set a custom protocol version
92
+ */
93
+ public function __construct(
94
+ $statusCode,
95
+ array $headers = [],
96
+ StreamInterface $body = null,
97
+ array $options = []
98
+ ) {
99
+ $this->statusCode = (int) $statusCode;
100
+ $this->handleOptions($options);
101
+
102
+ // Assume a reason phrase if one was not applied as an option
103
+ if (!$this->reasonPhrase &&
104
+ isset(self::$statusTexts[$this->statusCode])
105
+ ) {
106
+ $this->reasonPhrase = self::$statusTexts[$this->statusCode];
107
+ }
108
+
109
+ if ($headers) {
110
+ $this->setHeaders($headers);
111
+ }
112
+
113
+ if ($body) {
114
+ $this->setBody($body);
115
+ }
116
+ }
117
+
118
+ public function getStatusCode()
119
+ {
120
+ return $this->statusCode;
121
+ }
122
+
123
+ public function setStatusCode($code)
124
+ {
125
+ return $this->statusCode = (int) $code;
126
+ }
127
+
128
+ public function getReasonPhrase()
129
+ {
130
+ return $this->reasonPhrase;
131
+ }
132
+
133
+ public function setReasonPhrase($phrase)
134
+ {
135
+ return $this->reasonPhrase = $phrase;
136
+ }
137
+
138
+ public function json(array $config = [])
139
+ {
140
+ try {
141
+ return Utils::jsonDecode(
142
+ (string) $this->getBody(),
143
+ isset($config['object']) ? !$config['object'] : true,
144
+ 512,
145
+ isset($config['big_int_strings']) ? JSON_BIGINT_AS_STRING : 0
146
+ );
147
+ } catch (\InvalidArgumentException $e) {
148
+ throw new ParseException(
149
+ $e->getMessage(),
150
+ $this
151
+ );
152
+ }
153
+ }
154
+
155
+ public function xml(array $config = [])
156
+ {
157
+ $disableEntities = libxml_disable_entity_loader(true);
158
+ $internalErrors = libxml_use_internal_errors(true);
159
+
160
+ try {
161
+ // Allow XML to be retrieved even if there is no response body
162
+ $xml = new \SimpleXMLElement(
163
+ (string) $this->getBody() ?: '<root />',
164
+ isset($config['libxml_options']) ? $config['libxml_options'] : LIBXML_NONET,
165
+ false,
166
+ isset($config['ns']) ? $config['ns'] : '',
167
+ isset($config['ns_is_prefix']) ? $config['ns_is_prefix'] : false
168
+ );
169
+ libxml_disable_entity_loader($disableEntities);
170
+ libxml_use_internal_errors($internalErrors);
171
+ } catch (\Exception $e) {
172
+ libxml_disable_entity_loader($disableEntities);
173
+ libxml_use_internal_errors($internalErrors);
174
+ throw new XmlParseException(
175
+ 'Unable to parse response body into XML: ' . $e->getMessage(),
176
+ $this,
177
+ $e,
178
+ (libxml_get_last_error()) ?: null
179
+ );
180
+ }
181
+
182
+ return $xml;
183
+ }
184
+
185
+ public function getEffectiveUrl()
186
+ {
187
+ return $this->effectiveUrl;
188
+ }
189
+
190
+ public function setEffectiveUrl($url)
191
+ {
192
+ $this->effectiveUrl = $url;
193
+ }
194
+
195
+ /**
196
+ * Accepts and modifies the options provided to the response in the
197
+ * constructor.
198
+ *
199
+ * @param array $options Options array passed by reference.
200
+ */
201
+ protected function handleOptions(array &$options = [])
202
+ {
203
+ parent::handleOptions($options);
204
+ if (isset($options['reason_phrase'])) {
205
+ $this->reasonPhrase = $options['reason_phrase'];
206
+ }
207
+ }
208
+ }
vendor/guzzlehttp/guzzle/src/Message/ResponseInterface.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Message;
3
+
4
+ /**
5
+ * Represents an HTTP response message.
6
+ */
7
+ interface ResponseInterface extends MessageInterface
8
+ {
9
+ /**
10
+ * Gets the response Status-Code.
11
+ *
12
+ * The Status-Code is a 3-digit integer result code of the server's attempt
13
+ * to understand and satisfy the request.
14
+ *
15
+ * @return int Status code.
16
+ */
17
+ public function getStatusCode();
18
+
19
+ /**
20
+ * Sets the status code of this response.
21
+ *
22
+ * @param int $code The 3-digit integer result code to set.
23
+ */
24
+ public function setStatusCode($code);
25
+
26
+ /**
27
+ * Gets the response Reason-Phrase, a short textual description of the
28
+ * Status-Code.
29
+ *
30
+ * Because a Reason-Phrase is not a required element in response
31
+ * Status-Line, the Reason-Phrase value MAY be null. Implementations MAY
32
+ * choose to return the default RFC 2616 recommended reason phrase for the
33
+ * response's Status-Code.
34
+ *
35
+ * @return string|null Reason phrase, or null if unknown.
36
+ */
37
+ public function getReasonPhrase();
38
+
39
+ /**
40
+ * Sets the Reason-Phrase of the response.
41
+ *
42
+ * If no Reason-Phrase is specified, implementations MAY choose to default
43
+ * to the RFC 2616 recommended reason phrase for the response's Status-Code.
44
+ *
45
+ * @param string $phrase The Reason-Phrase to set.
46
+ */
47
+ public function setReasonPhrase($phrase);
48
+
49
+ /**
50
+ * Get the effective URL that resulted in this response (e.g. the last
51
+ * redirect URL).
52
+ *
53
+ * @return string
54
+ */
55
+ public function getEffectiveUrl();
56
+
57
+ /**
58
+ * Set the effective URL that resulted in this response (e.g. the last
59
+ * redirect URL).
60
+ *
61
+ * @param string $url Effective URL
62
+ */
63
+ public function setEffectiveUrl($url);
64
+
65
+ /**
66
+ * Parse the JSON response body and return the JSON decoded data.
67
+ *
68
+ * @param array $config Associative array of configuration settings used
69
+ * to control how the JSON data is parsed. Concrete implementations MAY
70
+ * add further configuration settings as needed, but they MUST implement
71
+ * functionality for the following options:
72
+ *
73
+ * - object: Set to true to parse JSON objects as PHP objects rather
74
+ * than associative arrays. Defaults to false.
75
+ * - big_int_strings: When set to true, large integers are converted to
76
+ * strings rather than floats. Defaults to false.
77
+ *
78
+ * Implementations are free to add further configuration settings as
79
+ * needed.
80
+ *
81
+ * @return mixed Returns the JSON decoded data based on the provided
82
+ * parse settings.
83
+ * @throws \RuntimeException if the response body is not in JSON format
84
+ */
85
+ public function json(array $config = []);
86
+
87
+ /**
88
+ * Parse the XML response body and return a \SimpleXMLElement.
89
+ *
90
+ * In order to prevent XXE attacks, this method disables loading external
91
+ * entities. If you rely on external entities, then you must parse the
92
+ * XML response manually by accessing the response body directly.
93
+ *
94
+ * @param array $config Associative array of configuration settings used
95
+ * to control how the XML is parsed. Concrete implementations MAY add
96
+ * further configuration settings as needed, but they MUST implement
97
+ * functionality for the following options:
98
+ *
99
+ * - ns: Set to a string to represent the namespace prefix or URI
100
+ * - ns_is_prefix: Set to true to specify that the NS is a prefix rather
101
+ * than a URI (defaults to false).
102
+ * - libxml_options: Bitwise OR of the libxml option constants
103
+ * listed at http://php.net/manual/en/libxml.constants.php
104
+ * (defaults to LIBXML_NONET)
105
+ *
106
+ * @return \SimpleXMLElement
107
+ * @throws \RuntimeException if the response body is not in XML format
108
+ * @link http://websec.io/2012/08/27/Preventing-XXE-in-PHP.html
109
+ */
110
+ public function xml(array $config = []);
111
+ }
vendor/guzzlehttp/guzzle/src/Mimetypes.php ADDED
@@ -0,0 +1,963 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Provides mappings of file extensions to mimetypes
6
+ * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
7
+ */
8
+ class Mimetypes
9
+ {
10
+ /** @var self */
11
+ protected static $instance;
12
+
13
+ /** @var array Mapping of extension to mimetype */
14
+ protected $mimetypes = array(
15
+ '3dml' => 'text/vnd.in3d.3dml',
16
+ '3g2' => 'video/3gpp2',
17
+ '3gp' => 'video/3gpp',
18
+ '7z' => 'application/x-7z-compressed',
19
+ 'aab' => 'application/x-authorware-bin',
20
+ 'aac' => 'audio/x-aac',
21
+ 'aam' => 'application/x-authorware-map',
22
+ 'aas' => 'application/x-authorware-seg',
23
+ 'abw' => 'application/x-abiword',
24
+ 'ac' => 'application/pkix-attr-cert',
25
+ 'acc' => 'application/vnd.americandynamics.acc',
26
+ 'ace' => 'application/x-ace-compressed',
27
+ 'acu' => 'application/vnd.acucobol',
28
+ 'acutc' => 'application/vnd.acucorp',
29
+ 'adp' => 'audio/adpcm',
30
+ 'aep' => 'application/vnd.audiograph',
31
+ 'afm' => 'application/x-font-type1',
32
+ 'afp' => 'application/vnd.ibm.modcap',
33
+ 'ahead' => 'application/vnd.ahead.space',
34
+ 'ai' => 'application/postscript',
35
+ 'aif' => 'audio/x-aiff',
36
+ 'aifc' => 'audio/x-aiff',
37
+ 'aiff' => 'audio/x-aiff',
38
+ 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
39
+ 'ait' => 'application/vnd.dvb.ait',
40
+ 'ami' => 'application/vnd.amiga.ami',
41
+ 'apk' => 'application/vnd.android.package-archive',
42
+ 'application' => 'application/x-ms-application',
43
+ 'apr' => 'application/vnd.lotus-approach',
44
+ 'asa' => 'text/plain',
45
+ 'asax' => 'application/octet-stream',
46
+ 'asc' => 'application/pgp-signature',
47
+ 'ascx' => 'text/plain',
48
+ 'asf' => 'video/x-ms-asf',
49
+ 'ashx' => 'text/plain',
50
+ 'asm' => 'text/x-asm',
51
+ 'asmx' => 'text/plain',
52
+ 'aso' => 'application/vnd.accpac.simply.aso',
53
+ 'asp' => 'text/plain',
54
+ 'aspx' => 'text/plain',
55
+ 'asx' => 'video/x-ms-asf',
56
+ 'atc' => 'application/vnd.acucorp',
57
+ 'atom' => 'application/atom+xml',
58
+ 'atomcat' => 'application/atomcat+xml',
59
+ 'atomsvc' => 'application/atomsvc+xml',
60
+ 'atx' => 'application/vnd.antix.game-component',
61
+ 'au' => 'audio/basic',
62
+ 'avi' => 'video/x-msvideo',
63
+ 'aw' => 'application/applixware',
64
+ 'axd' => 'text/plain',
65
+ 'azf' => 'application/vnd.airzip.filesecure.azf',
66
+ 'azs' => 'application/vnd.airzip.filesecure.azs',
67
+ 'azw' => 'application/vnd.amazon.ebook',
68
+ 'bat' => 'application/x-msdownload',
69
+ 'bcpio' => 'application/x-bcpio',
70
+ 'bdf' => 'application/x-font-bdf',
71
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
72
+ 'bed' => 'application/vnd.realvnc.bed',
73
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
74
+ 'bin' => 'application/octet-stream',
75
+ 'bmi' => 'application/vnd.bmi',
76
+ 'bmp' => 'image/bmp',
77
+ 'book' => 'application/vnd.framemaker',
78
+ 'box' => 'application/vnd.previewsystems.box',
79
+ 'boz' => 'application/x-bzip2',
80
+ 'bpk' => 'application/octet-stream',
81
+ 'btif' => 'image/prs.btif',
82
+ 'bz' => 'application/x-bzip',
83
+ 'bz2' => 'application/x-bzip2',
84
+ 'c' => 'text/x-c',
85
+ 'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
86
+ 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
87
+ 'c4d' => 'application/vnd.clonk.c4group',
88
+ 'c4f' => 'application/vnd.clonk.c4group',
89
+ 'c4g' => 'application/vnd.clonk.c4group',
90
+ 'c4p' => 'application/vnd.clonk.c4group',
91
+ 'c4u' => 'application/vnd.clonk.c4group',
92
+ 'cab' => 'application/vnd.ms-cab-compressed',
93
+ 'car' => 'application/vnd.curl.car',
94
+ 'cat' => 'application/vnd.ms-pki.seccat',
95
+ 'cc' => 'text/x-c',
96
+ 'cct' => 'application/x-director',
97
+ 'ccxml' => 'application/ccxml+xml',
98
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
99
+ 'cdf' => 'application/x-netcdf',
100
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
101
+ 'cdmia' => 'application/cdmi-capability',
102
+ 'cdmic' => 'application/cdmi-container',
103
+ 'cdmid' => 'application/cdmi-domain',
104
+ 'cdmio' => 'application/cdmi-object',
105
+ 'cdmiq' => 'application/cdmi-queue',
106
+ 'cdx' => 'chemical/x-cdx',
107
+ 'cdxml' => 'application/vnd.chemdraw+xml',
108
+ 'cdy' => 'application/vnd.cinderella',
109
+ 'cer' => 'application/pkix-cert',
110
+ 'cfc' => 'application/x-coldfusion',
111
+ 'cfm' => 'application/x-coldfusion',
112
+ 'cgm' => 'image/cgm',
113
+ 'chat' => 'application/x-chat',
114
+ 'chm' => 'application/vnd.ms-htmlhelp',
115
+ 'chrt' => 'application/vnd.kde.kchart',
116
+ 'cif' => 'chemical/x-cif',
117
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
118
+ 'cil' => 'application/vnd.ms-artgalry',
119
+ 'cla' => 'application/vnd.claymore',
120
+ 'class' => 'application/java-vm',
121
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
122
+ 'clkp' => 'application/vnd.crick.clicker.palette',
123
+ 'clkt' => 'application/vnd.crick.clicker.template',
124
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
125
+ 'clkx' => 'application/vnd.crick.clicker',
126
+ 'clp' => 'application/x-msclip',
127
+ 'cmc' => 'application/vnd.cosmocaller',
128
+ 'cmdf' => 'chemical/x-cmdf',
129
+ 'cml' => 'chemical/x-cml',
130
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
131
+ 'cmx' => 'image/x-cmx',
132
+ 'cod' => 'application/vnd.rim.cod',
133
+ 'com' => 'application/x-msdownload',
134
+ 'conf' => 'text/plain',
135
+ 'cpio' => 'application/x-cpio',
136
+ 'cpp' => 'text/x-c',
137
+ 'cpt' => 'application/mac-compactpro',
138
+ 'crd' => 'application/x-mscardfile',
139
+ 'crl' => 'application/pkix-crl',
140
+ 'crt' => 'application/x-x509-ca-cert',
141
+ 'cryptonote' => 'application/vnd.rig.cryptonote',
142
+ 'cs' => 'text/plain',
143
+ 'csh' => 'application/x-csh',
144
+ 'csml' => 'chemical/x-csml',
145
+ 'csp' => 'application/vnd.commonspace',
146
+ 'css' => 'text/css',
147
+ 'cst' => 'application/x-director',
148
+ 'csv' => 'text/csv',
149
+ 'cu' => 'application/cu-seeme',
150
+ 'curl' => 'text/vnd.curl',
151
+ 'cww' => 'application/prs.cww',
152
+ 'cxt' => 'application/x-director',
153
+ 'cxx' => 'text/x-c',
154
+ 'dae' => 'model/vnd.collada+xml',
155
+ 'daf' => 'application/vnd.mobius.daf',
156
+ 'dataless' => 'application/vnd.fdsn.seed',
157
+ 'davmount' => 'application/davmount+xml',
158
+ 'dcr' => 'application/x-director',
159
+ 'dcurl' => 'text/vnd.curl.dcurl',
160
+ 'dd2' => 'application/vnd.oma.dd2+xml',
161
+ 'ddd' => 'application/vnd.fujixerox.ddd',
162
+ 'deb' => 'application/x-debian-package',
163
+ 'def' => 'text/plain',
164
+ 'deploy' => 'application/octet-stream',
165
+ 'der' => 'application/x-x509-ca-cert',
166
+ 'dfac' => 'application/vnd.dreamfactory',
167
+ 'dic' => 'text/x-c',
168
+ 'dir' => 'application/x-director',
169
+ 'dis' => 'application/vnd.mobius.dis',
170
+ 'dist' => 'application/octet-stream',
171
+ 'distz' => 'application/octet-stream',
172
+ 'djv' => 'image/vnd.djvu',
173
+ 'djvu' => 'image/vnd.djvu',
174
+ 'dll' => 'application/x-msdownload',
175
+ 'dmg' => 'application/octet-stream',
176
+ 'dms' => 'application/octet-stream',
177
+ 'dna' => 'application/vnd.dna',
178
+ 'doc' => 'application/msword',
179
+ 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
180
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
181
+ 'dot' => 'application/msword',
182
+ 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
183
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
184
+ 'dp' => 'application/vnd.osgi.dp',
185
+ 'dpg' => 'application/vnd.dpgraph',
186
+ 'dra' => 'audio/vnd.dra',
187
+ 'dsc' => 'text/prs.lines.tag',
188
+ 'dssc' => 'application/dssc+der',
189
+ 'dtb' => 'application/x-dtbook+xml',
190
+ 'dtd' => 'application/xml-dtd',
191
+ 'dts' => 'audio/vnd.dts',
192
+ 'dtshd' => 'audio/vnd.dts.hd',
193
+ 'dump' => 'application/octet-stream',
194
+ 'dvi' => 'application/x-dvi',
195
+ 'dwf' => 'model/vnd.dwf',
196
+ 'dwg' => 'image/vnd.dwg',
197
+ 'dxf' => 'image/vnd.dxf',
198
+ 'dxp' => 'application/vnd.spotfire.dxp',
199
+ 'dxr' => 'application/x-director',
200
+ 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
201
+ 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
202
+ 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
203
+ 'ecma' => 'application/ecmascript',
204
+ 'edm' => 'application/vnd.novadigm.edm',
205
+ 'edx' => 'application/vnd.novadigm.edx',
206
+ 'efif' => 'application/vnd.picsel',
207
+ 'ei6' => 'application/vnd.pg.osasli',
208
+ 'elc' => 'application/octet-stream',
209
+ 'eml' => 'message/rfc822',
210
+ 'emma' => 'application/emma+xml',
211
+ 'eol' => 'audio/vnd.digital-winds',
212
+ 'eot' => 'application/vnd.ms-fontobject',
213
+ 'eps' => 'application/postscript',
214
+ 'epub' => 'application/epub+zip',
215
+ 'es3' => 'application/vnd.eszigno3+xml',
216
+ 'esf' => 'application/vnd.epson.esf',
217
+ 'et3' => 'application/vnd.eszigno3+xml',
218
+ 'etx' => 'text/x-setext',
219
+ 'exe' => 'application/x-msdownload',
220
+ 'exi' => 'application/exi',
221
+ 'ext' => 'application/vnd.novadigm.ext',
222
+ 'ez' => 'application/andrew-inset',
223
+ 'ez2' => 'application/vnd.ezpix-album',
224
+ 'ez3' => 'application/vnd.ezpix-package',
225
+ 'f' => 'text/x-fortran',
226
+ 'f4v' => 'video/x-f4v',
227
+ 'f77' => 'text/x-fortran',
228
+ 'f90' => 'text/x-fortran',
229
+ 'fbs' => 'image/vnd.fastbidsheet',
230
+ 'fcs' => 'application/vnd.isac.fcs',
231
+ 'fdf' => 'application/vnd.fdf',
232
+ 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
233
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
234
+ 'fgd' => 'application/x-director',
235
+ 'fh' => 'image/x-freehand',
236
+ 'fh4' => 'image/x-freehand',
237
+ 'fh5' => 'image/x-freehand',
238
+ 'fh7' => 'image/x-freehand',
239
+ 'fhc' => 'image/x-freehand',
240
+ 'fig' => 'application/x-xfig',
241
+ 'fli' => 'video/x-fli',
242
+ 'flo' => 'application/vnd.micrografx.flo',
243
+ 'flv' => 'video/x-flv',
244
+ 'flw' => 'application/vnd.kde.kivio',
245
+ 'flx' => 'text/vnd.fmi.flexstor',
246
+ 'fly' => 'text/vnd.fly',
247
+ 'fm' => 'application/vnd.framemaker',
248
+ 'fnc' => 'application/vnd.frogans.fnc',
249
+ 'for' => 'text/x-fortran',
250
+ 'fpx' => 'image/vnd.fpx',
251
+ 'frame' => 'application/vnd.framemaker',
252
+ 'fsc' => 'application/vnd.fsc.weblaunch',
253
+ 'fst' => 'image/vnd.fst',
254
+ 'ftc' => 'application/vnd.fluxtime.clip',
255
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
256
+ 'fvt' => 'video/vnd.fvt',
257
+ 'fxp' => 'application/vnd.adobe.fxp',
258
+ 'fxpl' => 'application/vnd.adobe.fxp',
259
+ 'fzs' => 'application/vnd.fuzzysheet',
260
+ 'g2w' => 'application/vnd.geoplan',
261
+ 'g3' => 'image/g3fax',
262
+ 'g3w' => 'application/vnd.geospace',
263
+ 'gac' => 'application/vnd.groove-account',
264
+ 'gdl' => 'model/vnd.gdl',
265
+ 'geo' => 'application/vnd.dynageo',
266
+ 'gex' => 'application/vnd.geometry-explorer',
267
+ 'ggb' => 'application/vnd.geogebra.file',
268
+ 'ggt' => 'application/vnd.geogebra.tool',
269
+ 'ghf' => 'application/vnd.groove-help',
270
+ 'gif' => 'image/gif',
271
+ 'gim' => 'application/vnd.groove-identity-message',
272
+ 'gmx' => 'application/vnd.gmx',
273
+ 'gnumeric' => 'application/x-gnumeric',
274
+ 'gph' => 'application/vnd.flographit',
275
+ 'gqf' => 'application/vnd.grafeq',
276
+ 'gqs' => 'application/vnd.grafeq',
277
+ 'gram' => 'application/srgs',
278
+ 'gre' => 'application/vnd.geometry-explorer',
279
+ 'grv' => 'application/vnd.groove-injector',
280
+ 'grxml' => 'application/srgs+xml',
281
+ 'gsf' => 'application/x-font-ghostscript',
282
+ 'gtar' => 'application/x-gtar',
283
+ 'gtm' => 'application/vnd.groove-tool-message',
284
+ 'gtw' => 'model/vnd.gtw',
285
+ 'gv' => 'text/vnd.graphviz',
286
+ 'gxt' => 'application/vnd.geonext',
287
+ 'h' => 'text/x-c',
288
+ 'h261' => 'video/h261',
289
+ 'h263' => 'video/h263',
290
+ 'h264' => 'video/h264',
291
+ 'hal' => 'application/vnd.hal+xml',
292
+ 'hbci' => 'application/vnd.hbci',
293
+ 'hdf' => 'application/x-hdf',
294
+ 'hh' => 'text/x-c',
295
+ 'hlp' => 'application/winhlp',
296
+ 'hpgl' => 'application/vnd.hp-hpgl',
297
+ 'hpid' => 'application/vnd.hp-hpid',
298
+ 'hps' => 'application/vnd.hp-hps',
299
+ 'hqx' => 'application/mac-binhex40',
300
+ 'hta' => 'application/octet-stream',
301
+ 'htc' => 'text/html',
302
+ 'htke' => 'application/vnd.kenameaapp',
303
+ 'htm' => 'text/html',
304
+ 'html' => 'text/html',
305
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
306
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
307
+ 'hvs' => 'application/vnd.yamaha.hv-script',
308
+ 'i2g' => 'application/vnd.intergeo',
309
+ 'icc' => 'application/vnd.iccprofile',
310
+ 'ice' => 'x-conference/x-cooltalk',
311
+ 'icm' => 'application/vnd.iccprofile',
312
+ 'ico' => 'image/x-icon',
313
+ 'ics' => 'text/calendar',
314
+ 'ief' => 'image/ief',
315
+ 'ifb' => 'text/calendar',
316
+ 'ifm' => 'application/vnd.shana.informed.formdata',
317
+ 'iges' => 'model/iges',
318
+ 'igl' => 'application/vnd.igloader',
319
+ 'igm' => 'application/vnd.insors.igm',
320
+ 'igs' => 'model/iges',
321
+ 'igx' => 'application/vnd.micrografx.igx',
322
+ 'iif' => 'application/vnd.shana.informed.interchange',
323
+ 'imp' => 'application/vnd.accpac.simply.imp',
324
+ 'ims' => 'application/vnd.ms-ims',
325
+ 'in' => 'text/plain',
326
+ 'ini' => 'text/plain',
327
+ 'ipfix' => 'application/ipfix',
328
+ 'ipk' => 'application/vnd.shana.informed.package',
329
+ 'irm' => 'application/vnd.ibm.rights-management',
330
+ 'irp' => 'application/vnd.irepository.package+xml',
331
+ 'iso' => 'application/octet-stream',
332
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
333
+ 'ivp' => 'application/vnd.immervision-ivp',
334
+ 'ivu' => 'application/vnd.immervision-ivu',
335
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
336
+ 'jam' => 'application/vnd.jam',
337
+ 'jar' => 'application/java-archive',
338
+ 'java' => 'text/x-java-source',
339
+ 'jisp' => 'application/vnd.jisp',
340
+ 'jlt' => 'application/vnd.hp-jlyt',
341
+ 'jnlp' => 'application/x-java-jnlp-file',
342
+ 'joda' => 'application/vnd.joost.joda-archive',
343
+ 'jpe' => 'image/jpeg',
344
+ 'jpeg' => 'image/jpeg',
345
+ 'jpg' => 'image/jpeg',
346
+ 'jpgm' => 'video/jpm',
347
+ 'jpgv' => 'video/jpeg',
348
+ 'jpm' => 'video/jpm',
349
+ 'js' => 'text/javascript',
350
+ 'json' => 'application/json',
351
+ 'kar' => 'audio/midi',
352
+ 'karbon' => 'application/vnd.kde.karbon',
353
+ 'kfo' => 'application/vnd.kde.kformula',
354
+ 'kia' => 'application/vnd.kidspiration',
355
+ 'kml' => 'application/vnd.google-earth.kml+xml',
356
+ 'kmz' => 'application/vnd.google-earth.kmz',
357
+ 'kne' => 'application/vnd.kinar',
358
+ 'knp' => 'application/vnd.kinar',
359
+ 'kon' => 'application/vnd.kde.kontour',
360
+ 'kpr' => 'application/vnd.kde.kpresenter',
361
+ 'kpt' => 'application/vnd.kde.kpresenter',
362
+ 'ksp' => 'application/vnd.kde.kspread',
363
+ 'ktr' => 'application/vnd.kahootz',
364
+ 'ktx' => 'image/ktx',
365
+ 'ktz' => 'application/vnd.kahootz',
366
+ 'kwd' => 'application/vnd.kde.kword',
367
+ 'kwt' => 'application/vnd.kde.kword',
368
+ 'lasxml' => 'application/vnd.las.las+xml',
369
+ 'latex' => 'application/x-latex',
370
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
371
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
372
+ 'les' => 'application/vnd.hhe.lesson-player',
373
+ 'lha' => 'application/octet-stream',
374
+ 'link66' => 'application/vnd.route66.link66+xml',
375
+ 'list' => 'text/plain',
376
+ 'list3820' => 'application/vnd.ibm.modcap',
377
+ 'listafp' => 'application/vnd.ibm.modcap',
378
+ 'log' => 'text/plain',
379
+ 'lostxml' => 'application/lost+xml',
380
+ 'lrf' => 'application/octet-stream',
381
+ 'lrm' => 'application/vnd.ms-lrm',
382
+ 'ltf' => 'application/vnd.frogans.ltf',
383
+ 'lvp' => 'audio/vnd.lucent.voice',
384
+ 'lwp' => 'application/vnd.lotus-wordpro',
385
+ 'lzh' => 'application/octet-stream',
386
+ 'm13' => 'application/x-msmediaview',
387
+ 'm14' => 'application/x-msmediaview',
388
+ 'm1v' => 'video/mpeg',
389
+ 'm21' => 'application/mp21',
390
+ 'm2a' => 'audio/mpeg',
391
+ 'm2v' => 'video/mpeg',
392
+ 'm3a' => 'audio/mpeg',
393
+ 'm3u' => 'audio/x-mpegurl',
394
+ 'm3u8' => 'application/vnd.apple.mpegurl',
395
+ 'm4a' => 'audio/mp4',
396
+ 'm4u' => 'video/vnd.mpegurl',
397
+ 'm4v' => 'video/mp4',
398
+ 'ma' => 'application/mathematica',
399
+ 'mads' => 'application/mads+xml',
400
+ 'mag' => 'application/vnd.ecowin.chart',
401
+ 'maker' => 'application/vnd.framemaker',
402
+ 'man' => 'text/troff',
403
+ 'mathml' => 'application/mathml+xml',
404
+ 'mb' => 'application/mathematica',
405
+ 'mbk' => 'application/vnd.mobius.mbk',
406
+ 'mbox' => 'application/mbox',
407
+ 'mc1' => 'application/vnd.medcalcdata',
408
+ 'mcd' => 'application/vnd.mcd',
409
+ 'mcurl' => 'text/vnd.curl.mcurl',
410
+ 'mdb' => 'application/x-msaccess',
411
+ 'mdi' => 'image/vnd.ms-modi',
412
+ 'me' => 'text/troff',
413
+ 'mesh' => 'model/mesh',
414
+ 'meta4' => 'application/metalink4+xml',
415
+ 'mets' => 'application/mets+xml',
416
+ 'mfm' => 'application/vnd.mfmp',
417
+ 'mgp' => 'application/vnd.osgeo.mapguide.package',
418
+ 'mgz' => 'application/vnd.proteus.magazine',
419
+ 'mid' => 'audio/midi',
420
+ 'midi' => 'audio/midi',
421
+ 'mif' => 'application/vnd.mif',
422
+ 'mime' => 'message/rfc822',
423
+ 'mj2' => 'video/mj2',
424
+ 'mjp2' => 'video/mj2',
425
+ 'mlp' => 'application/vnd.dolby.mlp',
426
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
427
+ 'mmf' => 'application/vnd.smaf',
428
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
429
+ 'mny' => 'application/x-msmoney',
430
+ 'mobi' => 'application/x-mobipocket-ebook',
431
+ 'mods' => 'application/mods+xml',
432
+ 'mov' => 'video/quicktime',
433
+ 'movie' => 'video/x-sgi-movie',
434
+ 'mp2' => 'audio/mpeg',
435
+ 'mp21' => 'application/mp21',
436
+ 'mp2a' => 'audio/mpeg',
437
+ 'mp3' => 'audio/mpeg',
438
+ 'mp4' => 'video/mp4',
439
+ 'mp4a' => 'audio/mp4',
440
+ 'mp4s' => 'application/mp4',
441
+ 'mp4v' => 'video/mp4',
442
+ 'mpc' => 'application/vnd.mophun.certificate',
443
+ 'mpe' => 'video/mpeg',
444
+ 'mpeg' => 'video/mpeg',
445
+ 'mpg' => 'video/mpeg',
446
+ 'mpg4' => 'video/mp4',
447
+ 'mpga' => 'audio/mpeg',
448
+ 'mpkg' => 'application/vnd.apple.installer+xml',
449
+ 'mpm' => 'application/vnd.blueice.multipass',
450
+ 'mpn' => 'application/vnd.mophun.application',
451
+ 'mpp' => 'application/vnd.ms-project',
452
+ 'mpt' => 'application/vnd.ms-project',
453
+ 'mpy' => 'application/vnd.ibm.minipay',
454
+ 'mqy' => 'application/vnd.mobius.mqy',
455
+ 'mrc' => 'application/marc',
456
+ 'mrcx' => 'application/marcxml+xml',
457
+ 'ms' => 'text/troff',
458
+ 'mscml' => 'application/mediaservercontrol+xml',
459
+ 'mseed' => 'application/vnd.fdsn.mseed',
460
+ 'mseq' => 'application/vnd.mseq',
461
+ 'msf' => 'application/vnd.epson.msf',
462
+ 'msh' => 'model/mesh',
463
+ 'msi' => 'application/x-msdownload',
464
+ 'msl' => 'application/vnd.mobius.msl',
465
+ 'msty' => 'application/vnd.muvee.style',
466
+ 'mts' => 'model/vnd.mts',
467
+ 'mus' => 'application/vnd.musician',
468
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
469
+ 'mvb' => 'application/x-msmediaview',
470
+ 'mwf' => 'application/vnd.mfer',
471
+ 'mxf' => 'application/mxf',
472
+ 'mxl' => 'application/vnd.recordare.musicxml',
473
+ 'mxml' => 'application/xv+xml',
474
+ 'mxs' => 'application/vnd.triscape.mxs',
475
+ 'mxu' => 'video/vnd.mpegurl',
476
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
477
+ 'n3' => 'text/n3',
478
+ 'nb' => 'application/mathematica',
479
+ 'nbp' => 'application/vnd.wolfram.player',
480
+ 'nc' => 'application/x-netcdf',
481
+ 'ncx' => 'application/x-dtbncx+xml',
482
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
483
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
484
+ 'nml' => 'application/vnd.enliven',
485
+ 'nnd' => 'application/vnd.noblenet-directory',
486
+ 'nns' => 'application/vnd.noblenet-sealer',
487
+ 'nnw' => 'application/vnd.noblenet-web',
488
+ 'npx' => 'image/vnd.net-fpx',
489
+ 'nsf' => 'application/vnd.lotus-notes',
490
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
491
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
492
+ 'oas' => 'application/vnd.fujitsu.oasys',
493
+ 'obd' => 'application/x-msbinder',
494
+ 'oda' => 'application/oda',
495
+ 'odb' => 'application/vnd.oasis.opendocument.database',
496
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
497
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
498
+ 'odft' => 'application/vnd.oasis.opendocument.formula-template',
499
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
500
+ 'odi' => 'application/vnd.oasis.opendocument.image',
501
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
502
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
503
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
504
+ 'odt' => 'application/vnd.oasis.opendocument.text',
505
+ 'oga' => 'audio/ogg',
506
+ 'ogg' => 'audio/ogg',
507
+ 'ogv' => 'video/ogg',
508
+ 'ogx' => 'application/ogg',
509
+ 'onepkg' => 'application/onenote',
510
+ 'onetmp' => 'application/onenote',
511
+ 'onetoc' => 'application/onenote',
512
+ 'onetoc2' => 'application/onenote',
513
+ 'opf' => 'application/oebps-package+xml',
514
+ 'oprc' => 'application/vnd.palm',
515
+ 'org' => 'application/vnd.lotus-organizer',
516
+ 'osf' => 'application/vnd.yamaha.openscoreformat',
517
+ 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
518
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
519
+ 'otf' => 'application/x-font-otf',
520
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
521
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
522
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
523
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
524
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
525
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
526
+ 'oxt' => 'application/vnd.openofficeorg.extension',
527
+ 'p' => 'text/x-pascal',
528
+ 'p10' => 'application/pkcs10',
529
+ 'p12' => 'application/x-pkcs12',
530
+ 'p7b' => 'application/x-pkcs7-certificates',
531
+ 'p7c' => 'application/pkcs7-mime',
532
+ 'p7m' => 'application/pkcs7-mime',
533
+ 'p7r' => 'application/x-pkcs7-certreqresp',
534
+ 'p7s' => 'application/pkcs7-signature',
535
+ 'p8' => 'application/pkcs8',
536
+ 'pas' => 'text/x-pascal',
537
+ 'paw' => 'application/vnd.pawaafile',
538
+ 'pbd' => 'application/vnd.powerbuilder6',
539
+ 'pbm' => 'image/x-portable-bitmap',
540
+ 'pcf' => 'application/x-font-pcf',
541
+ 'pcl' => 'application/vnd.hp-pcl',
542
+ 'pclxl' => 'application/vnd.hp-pclxl',
543
+ 'pct' => 'image/x-pict',
544
+ 'pcurl' => 'application/vnd.curl.pcurl',
545
+ 'pcx' => 'image/x-pcx',
546
+ 'pdb' => 'application/vnd.palm',
547
+ 'pdf' => 'application/pdf',
548
+ 'pfa' => 'application/x-font-type1',
549
+ 'pfb' => 'application/x-font-type1',
550
+ 'pfm' => 'application/x-font-type1',
551
+ 'pfr' => 'application/font-tdpfr',
552
+ 'pfx' => 'application/x-pkcs12',
553
+ 'pgm' => 'image/x-portable-graymap',
554
+ 'pgn' => 'application/x-chess-pgn',
555
+ 'pgp' => 'application/pgp-encrypted',
556
+ 'php' => 'text/x-php',
557
+ 'phps' => 'application/x-httpd-phps',
558
+ 'pic' => 'image/x-pict',
559
+ 'pkg' => 'application/octet-stream',
560
+ 'pki' => 'application/pkixcmp',
561
+ 'pkipath' => 'application/pkix-pkipath',
562
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
563
+ 'plc' => 'application/vnd.mobius.plc',
564
+ 'plf' => 'application/vnd.pocketlearn',
565
+ 'pls' => 'application/pls+xml',
566
+ 'pml' => 'application/vnd.ctc-posml',
567
+ 'png' => 'image/png',
568
+ 'pnm' => 'image/x-portable-anymap',
569
+ 'portpkg' => 'application/vnd.macports.portpkg',
570
+ 'pot' => 'application/vnd.ms-powerpoint',
571
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
572
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
573
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
574
+ 'ppd' => 'application/vnd.cups-ppd',
575
+ 'ppm' => 'image/x-portable-pixmap',
576
+ 'pps' => 'application/vnd.ms-powerpoint',
577
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
578
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
579
+ 'ppt' => 'application/vnd.ms-powerpoint',
580
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
581
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
582
+ 'pqa' => 'application/vnd.palm',
583
+ 'prc' => 'application/x-mobipocket-ebook',
584
+ 'pre' => 'application/vnd.lotus-freelance',
585
+ 'prf' => 'application/pics-rules',
586
+ 'ps' => 'application/postscript',
587
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
588
+ 'psd' => 'image/vnd.adobe.photoshop',
589
+ 'psf' => 'application/x-font-linux-psf',
590
+ 'pskcxml' => 'application/pskc+xml',
591
+ 'ptid' => 'application/vnd.pvi.ptid1',
592
+ 'pub' => 'application/x-mspublisher',
593
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
594
+ 'pwn' => 'application/vnd.3m.post-it-notes',
595
+ 'pya' => 'audio/vnd.ms-playready.media.pya',
596
+ 'pyv' => 'video/vnd.ms-playready.media.pyv',
597
+ 'qam' => 'application/vnd.epson.quickanime',
598
+ 'qbo' => 'application/vnd.intu.qbo',
599
+ 'qfx' => 'application/vnd.intu.qfx',
600
+ 'qps' => 'application/vnd.publishare-delta-tree',
601
+ 'qt' => 'video/quicktime',
602
+ 'qwd' => 'application/vnd.quark.quarkxpress',
603
+ 'qwt' => 'application/vnd.quark.quarkxpress',
604
+ 'qxb' => 'application/vnd.quark.quarkxpress',
605
+ 'qxd' => 'application/vnd.quark.quarkxpress',
606
+ 'qxl' => 'application/vnd.quark.quarkxpress',
607
+ 'qxt' => 'application/vnd.quark.quarkxpress',
608
+ 'ra' => 'audio/x-pn-realaudio',
609
+ 'ram' => 'audio/x-pn-realaudio',
610
+ 'rar' => 'application/x-rar-compressed',
611
+ 'ras' => 'image/x-cmu-raster',
612
+ 'rb' => 'text/plain',
613
+ 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
614
+ 'rdf' => 'application/rdf+xml',
615
+ 'rdz' => 'application/vnd.data-vision.rdz',
616
+ 'rep' => 'application/vnd.businessobjects',
617
+ 'res' => 'application/x-dtbresource+xml',
618
+ 'resx' => 'text/xml',
619
+ 'rgb' => 'image/x-rgb',
620
+ 'rif' => 'application/reginfo+xml',
621
+ 'rip' => 'audio/vnd.rip',
622
+ 'rl' => 'application/resource-lists+xml',
623
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
624
+ 'rld' => 'application/resource-lists-diff+xml',
625
+ 'rm' => 'application/vnd.rn-realmedia',
626
+ 'rmi' => 'audio/midi',
627
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
628
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
629
+ 'rnc' => 'application/relax-ng-compact-syntax',
630
+ 'roff' => 'text/troff',
631
+ 'rp9' => 'application/vnd.cloanto.rp9',
632
+ 'rpss' => 'application/vnd.nokia.radio-presets',
633
+ 'rpst' => 'application/vnd.nokia.radio-preset',
634
+ 'rq' => 'application/sparql-query',
635
+ 'rs' => 'application/rls-services+xml',
636
+ 'rsd' => 'application/rsd+xml',
637
+ 'rss' => 'application/rss+xml',
638
+ 'rtf' => 'application/rtf',
639
+ 'rtx' => 'text/richtext',
640
+ 's' => 'text/x-asm',
641
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
642
+ 'sbml' => 'application/sbml+xml',
643
+ 'sc' => 'application/vnd.ibm.secure-container',
644
+ 'scd' => 'application/x-msschedule',
645
+ 'scm' => 'application/vnd.lotus-screencam',
646
+ 'scq' => 'application/scvp-cv-request',
647
+ 'scs' => 'application/scvp-cv-response',
648
+ 'scurl' => 'text/vnd.curl.scurl',
649
+ 'sda' => 'application/vnd.stardivision.draw',
650
+ 'sdc' => 'application/vnd.stardivision.calc',
651
+ 'sdd' => 'application/vnd.stardivision.impress',
652
+ 'sdkd' => 'application/vnd.solent.sdkm+xml',
653
+ 'sdkm' => 'application/vnd.solent.sdkm+xml',
654
+ 'sdp' => 'application/sdp',
655
+ 'sdw' => 'application/vnd.stardivision.writer',
656
+ 'see' => 'application/vnd.seemail',
657
+ 'seed' => 'application/vnd.fdsn.seed',
658
+ 'sema' => 'application/vnd.sema',
659
+ 'semd' => 'application/vnd.semd',
660
+ 'semf' => 'application/vnd.semf',
661
+ 'ser' => 'application/java-serialized-object',
662
+ 'setpay' => 'application/set-payment-initiation',
663
+ 'setreg' => 'application/set-registration-initiation',
664
+ 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
665
+ 'sfs' => 'application/vnd.spotfire.sfs',
666
+ 'sgl' => 'application/vnd.stardivision.writer-global',
667
+ 'sgm' => 'text/sgml',
668
+ 'sgml' => 'text/sgml',
669
+ 'sh' => 'application/x-sh',
670
+ 'shar' => 'application/x-shar',
671
+ 'shf' => 'application/shf+xml',
672
+ 'sig' => 'application/pgp-signature',
673
+ 'silo' => 'model/mesh',
674
+ 'sis' => 'application/vnd.symbian.install',
675
+ 'sisx' => 'application/vnd.symbian.install',
676
+ 'sit' => 'application/x-stuffit',
677
+ 'sitx' => 'application/x-stuffitx',
678
+ 'skd' => 'application/vnd.koan',
679
+ 'skm' => 'application/vnd.koan',
680
+ 'skp' => 'application/vnd.koan',
681
+ 'skt' => 'application/vnd.koan',
682
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
683
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
684
+ 'slt' => 'application/vnd.epson.salt',
685
+ 'sm' => 'application/vnd.stepmania.stepchart',
686
+ 'smf' => 'application/vnd.stardivision.math',
687
+ 'smi' => 'application/smil+xml',
688
+ 'smil' => 'application/smil+xml',
689
+ 'snd' => 'audio/basic',
690
+ 'snf' => 'application/x-font-snf',
691
+ 'so' => 'application/octet-stream',
692
+ 'spc' => 'application/x-pkcs7-certificates',
693
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
694
+ 'spl' => 'application/x-futuresplash',
695
+ 'spot' => 'text/vnd.in3d.spot',
696
+ 'spp' => 'application/scvp-vp-response',
697
+ 'spq' => 'application/scvp-vp-request',
698
+ 'spx' => 'audio/ogg',
699
+ 'src' => 'application/x-wais-source',
700
+ 'sru' => 'application/sru+xml',
701
+ 'srx' => 'application/sparql-results+xml',
702
+ 'sse' => 'application/vnd.kodak-descriptor',
703
+ 'ssf' => 'application/vnd.epson.ssf',
704
+ 'ssml' => 'application/ssml+xml',
705
+ 'st' => 'application/vnd.sailingtracker.track',
706
+ 'stc' => 'application/vnd.sun.xml.calc.template',
707
+ 'std' => 'application/vnd.sun.xml.draw.template',
708
+ 'stf' => 'application/vnd.wt.stf',
709
+ 'sti' => 'application/vnd.sun.xml.impress.template',
710
+ 'stk' => 'application/hyperstudio',
711
+ 'stl' => 'application/vnd.ms-pki.stl',
712
+ 'str' => 'application/vnd.pg.format',
713
+ 'stw' => 'application/vnd.sun.xml.writer.template',
714
+ 'sub' => 'image/vnd.dvb.subtitle',
715
+ 'sus' => 'application/vnd.sus-calendar',
716
+ 'susp' => 'application/vnd.sus-calendar',
717
+ 'sv4cpio' => 'application/x-sv4cpio',
718
+ 'sv4crc' => 'application/x-sv4crc',
719
+ 'svc' => 'application/vnd.dvb.service',
720
+ 'svd' => 'application/vnd.svd',
721
+ 'svg' => 'image/svg+xml',
722
+ 'svgz' => 'image/svg+xml',
723
+ 'swa' => 'application/x-director',
724
+ 'swf' => 'application/x-shockwave-flash',
725
+ 'swi' => 'application/vnd.aristanetworks.swi',
726
+ 'sxc' => 'application/vnd.sun.xml.calc',
727
+ 'sxd' => 'application/vnd.sun.xml.draw',
728
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
729
+ 'sxi' => 'application/vnd.sun.xml.impress',
730
+ 'sxm' => 'application/vnd.sun.xml.math',
731
+ 'sxw' => 'application/vnd.sun.xml.writer',
732
+ 't' => 'text/troff',
733
+ 'tao' => 'application/vnd.tao.intent-module-archive',
734
+ 'tar' => 'application/x-tar',
735
+ 'tcap' => 'application/vnd.3gpp2.tcap',
736
+ 'tcl' => 'application/x-tcl',
737
+ 'teacher' => 'application/vnd.smart.teacher',
738
+ 'tei' => 'application/tei+xml',
739
+ 'teicorpus' => 'application/tei+xml',
740
+ 'tex' => 'application/x-tex',
741
+ 'texi' => 'application/x-texinfo',
742
+ 'texinfo' => 'application/x-texinfo',
743
+ 'text' => 'text/plain',
744
+ 'tfi' => 'application/thraud+xml',
745
+ 'tfm' => 'application/x-tex-tfm',
746
+ 'thmx' => 'application/vnd.ms-officetheme',
747
+ 'tif' => 'image/tiff',
748
+ 'tiff' => 'image/tiff',
749
+ 'tmo' => 'application/vnd.tmobile-livetv',
750
+ 'torrent' => 'application/x-bittorrent',
751
+ 'tpl' => 'application/vnd.groove-tool-template',
752
+ 'tpt' => 'application/vnd.trid.tpt',
753
+ 'tr' => 'text/troff',
754
+ 'tra' => 'application/vnd.trueapp',
755
+ 'trm' => 'application/x-msterminal',
756
+ 'tsd' => 'application/timestamped-data',
757
+ 'tsv' => 'text/tab-separated-values',
758
+ 'ttc' => 'application/x-font-ttf',
759
+ 'ttf' => 'application/x-font-ttf',
760
+ 'ttl' => 'text/turtle',
761
+ 'twd' => 'application/vnd.simtech-mindmapper',
762
+ 'twds' => 'application/vnd.simtech-mindmapper',
763
+ 'txd' => 'application/vnd.genomatix.tuxedo',
764
+ 'txf' => 'application/vnd.mobius.txf',
765
+ 'txt' => 'text/plain',
766
+ 'u32' => 'application/x-authorware-bin',
767
+ 'udeb' => 'application/x-debian-package',
768
+ 'ufd' => 'application/vnd.ufdl',
769
+ 'ufdl' => 'application/vnd.ufdl',
770
+ 'umj' => 'application/vnd.umajin',
771
+ 'unityweb' => 'application/vnd.unity',
772
+ 'uoml' => 'application/vnd.uoml+xml',
773
+ 'uri' => 'text/uri-list',
774
+ 'uris' => 'text/uri-list',
775
+ 'urls' => 'text/uri-list',
776
+ 'ustar' => 'application/x-ustar',
777
+ 'utz' => 'application/vnd.uiq.theme',
778
+ 'uu' => 'text/x-uuencode',
779
+ 'uva' => 'audio/vnd.dece.audio',
780
+ 'uvd' => 'application/vnd.dece.data',
781
+ 'uvf' => 'application/vnd.dece.data',
782
+ 'uvg' => 'image/vnd.dece.graphic',
783
+ 'uvh' => 'video/vnd.dece.hd',
784
+ 'uvi' => 'image/vnd.dece.graphic',
785
+ 'uvm' => 'video/vnd.dece.mobile',
786
+ 'uvp' => 'video/vnd.dece.pd',
787
+ 'uvs' => 'video/vnd.dece.sd',
788
+ 'uvt' => 'application/vnd.dece.ttml+xml',
789
+ 'uvu' => 'video/vnd.uvvu.mp4',
790
+ 'uvv' => 'video/vnd.dece.video',
791
+ 'uvva' => 'audio/vnd.dece.audio',
792
+ 'uvvd' => 'application/vnd.dece.data',
793
+ 'uvvf' => 'application/vnd.dece.data',
794
+ 'uvvg' => 'image/vnd.dece.graphic',
795
+ 'uvvh' => 'video/vnd.dece.hd',
796
+ 'uvvi' => 'image/vnd.dece.graphic',
797
+ 'uvvm' => 'video/vnd.dece.mobile',
798
+ 'uvvp' => 'video/vnd.dece.pd',
799
+ 'uvvs' => 'video/vnd.dece.sd',
800
+ 'uvvt' => 'application/vnd.dece.ttml+xml',
801
+ 'uvvu' => 'video/vnd.uvvu.mp4',
802
+ 'uvvv' => 'video/vnd.dece.video',
803
+ 'uvvx' => 'application/vnd.dece.unspecified',
804
+ 'uvx' => 'application/vnd.dece.unspecified',
805
+ 'vcd' => 'application/x-cdlink',
806
+ 'vcf' => 'text/x-vcard',
807
+ 'vcg' => 'application/vnd.groove-vcard',
808
+ 'vcs' => 'text/x-vcalendar',
809
+ 'vcx' => 'application/vnd.vcx',
810
+ 'vis' => 'application/vnd.visionary',
811
+ 'viv' => 'video/vnd.vivo',
812
+ 'vor' => 'application/vnd.stardivision.writer',
813
+ 'vox' => 'application/x-authorware-bin',
814
+ 'vrml' => 'model/vrml',
815
+ 'vsd' => 'application/vnd.visio',
816
+ 'vsf' => 'application/vnd.vsf',
817
+ 'vss' => 'application/vnd.visio',
818
+ 'vst' => 'application/vnd.visio',
819
+ 'vsw' => 'application/vnd.visio',
820
+ 'vtu' => 'model/vnd.vtu',
821
+ 'vxml' => 'application/voicexml+xml',
822
+ 'w3d' => 'application/x-director',
823
+ 'wad' => 'application/x-doom',
824
+ 'wav' => 'audio/x-wav',
825
+ 'wax' => 'audio/x-ms-wax',
826
+ 'wbmp' => 'image/vnd.wap.wbmp',
827
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
828
+ 'wbxml' => 'application/vnd.wap.wbxml',
829
+ 'wcm' => 'application/vnd.ms-works',
830
+ 'wdb' => 'application/vnd.ms-works',
831
+ 'weba' => 'audio/webm',
832
+ 'webm' => 'video/webm',
833
+ 'webp' => 'image/webp',
834
+ 'wg' => 'application/vnd.pmi.widget',
835
+ 'wgt' => 'application/widget',
836
+ 'wks' => 'application/vnd.ms-works',
837
+ 'wm' => 'video/x-ms-wm',
838
+ 'wma' => 'audio/x-ms-wma',
839
+ 'wmd' => 'application/x-ms-wmd',
840
+ 'wmf' => 'application/x-msmetafile',
841
+ 'wml' => 'text/vnd.wap.wml',
842
+ 'wmlc' => 'application/vnd.wap.wmlc',
843
+ 'wmls' => 'text/vnd.wap.wmlscript',
844
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
845
+ 'wmv' => 'video/x-ms-wmv',
846
+ 'wmx' => 'video/x-ms-wmx',
847
+ 'wmz' => 'application/x-ms-wmz',
848
+ 'woff' => 'application/x-font-woff',
849
+ 'wpd' => 'application/vnd.wordperfect',
850
+ 'wpl' => 'application/vnd.ms-wpl',
851
+ 'wps' => 'application/vnd.ms-works',
852
+ 'wqd' => 'application/vnd.wqd',
853
+ 'wri' => 'application/x-mswrite',
854
+ 'wrl' => 'model/vrml',
855
+ 'wsdl' => 'application/wsdl+xml',
856
+ 'wspolicy' => 'application/wspolicy+xml',
857
+ 'wtb' => 'application/vnd.webturbo',
858
+ 'wvx' => 'video/x-ms-wvx',
859
+ 'x32' => 'application/x-authorware-bin',
860
+ 'x3d' => 'application/vnd.hzn-3d-crossword',
861
+ 'xap' => 'application/x-silverlight-app',
862
+ 'xar' => 'application/vnd.xara',
863
+ 'xbap' => 'application/x-ms-xbap',
864
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
865
+ 'xbm' => 'image/x-xbitmap',
866
+ 'xdf' => 'application/xcap-diff+xml',
867
+ 'xdm' => 'application/vnd.syncml.dm+xml',
868
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
869
+ 'xdssc' => 'application/dssc+xml',
870
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
871
+ 'xenc' => 'application/xenc+xml',
872
+ 'xer' => 'application/patch-ops-error+xml',
873
+ 'xfdf' => 'application/vnd.adobe.xfdf',
874
+ 'xfdl' => 'application/vnd.xfdl',
875
+ 'xht' => 'application/xhtml+xml',
876
+ 'xhtml' => 'application/xhtml+xml',
877
+ 'xhvml' => 'application/xv+xml',
878
+ 'xif' => 'image/vnd.xiff',
879
+ 'xla' => 'application/vnd.ms-excel',
880
+ 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
881
+ 'xlc' => 'application/vnd.ms-excel',
882
+ 'xlm' => 'application/vnd.ms-excel',
883
+ 'xls' => 'application/vnd.ms-excel',
884
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
885
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
886
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
887
+ 'xlt' => 'application/vnd.ms-excel',
888
+ 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
889
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
890
+ 'xlw' => 'application/vnd.ms-excel',
891
+ 'xml' => 'application/xml',
892
+ 'xo' => 'application/vnd.olpc-sugar',
893
+ 'xop' => 'application/xop+xml',
894
+ 'xpi' => 'application/x-xpinstall',
895
+ 'xpm' => 'image/x-xpixmap',
896
+ 'xpr' => 'application/vnd.is-xpr',
897
+ 'xps' => 'application/vnd.ms-xpsdocument',
898
+ 'xpw' => 'application/vnd.intercon.formnet',
899
+ 'xpx' => 'application/vnd.intercon.formnet',
900
+ 'xsl' => 'application/xml',
901
+ 'xslt' => 'application/xslt+xml',
902
+ 'xsm' => 'application/vnd.syncml+xml',
903
+ 'xspf' => 'application/xspf+xml',
904
+ 'xul' => 'application/vnd.mozilla.xul+xml',
905
+ 'xvm' => 'application/xv+xml',
906
+ 'xvml' => 'application/xv+xml',
907
+ 'xwd' => 'image/x-xwindowdump',
908
+ 'xyz' => 'chemical/x-xyz',
909
+ 'yaml' => 'text/yaml',
910
+ 'yang' => 'application/yang',
911
+ 'yin' => 'application/yin+xml',
912
+ 'yml' => 'text/yaml',
913
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
914
+ 'zip' => 'application/zip',
915
+ 'zir' => 'application/vnd.zul',
916
+ 'zirz' => 'application/vnd.zul',
917
+ 'zmm' => 'application/vnd.handheld-entertainment+xml'
918
+ );
919
+
920
+ /**
921
+ * Get a singleton instance of the class
922
+ *
923
+ * @return self
924
+ * @codeCoverageIgnore
925
+ */
926
+ public static function getInstance()
927
+ {
928
+ if (!self::$instance) {
929
+ self::$instance = new self();
930
+ }
931
+
932
+ return self::$instance;
933
+ }
934
+
935
+ /**
936
+ * Get a mimetype value from a file extension
937
+ *
938
+ * @param string $extension File extension
939
+ *
940
+ * @return string|null
941
+ *
942
+ */
943
+ public function fromExtension($extension)
944
+ {
945
+ $extension = strtolower($extension);
946
+
947
+ return isset($this->mimetypes[$extension])
948
+ ? $this->mimetypes[$extension]
949
+ : null;
950
+ }
951
+
952
+ /**
953
+ * Get a mimetype from a filename
954
+ *
955
+ * @param string $filename Filename to generate a mimetype from
956
+ *
957
+ * @return string|null
958
+ */
959
+ public function fromFilename($filename)
960
+ {
961
+ return $this->fromExtension(pathinfo($filename, PATHINFO_EXTENSION));
962
+ }
963
+ }
vendor/guzzlehttp/guzzle/src/Pool.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Event\BeforeEvent;
5
+ use GuzzleHttp\Event\RequestEvents;
6
+ use GuzzleHttp\Message\RequestInterface;
7
+ use GuzzleHttp\Message\ResponseInterface;
8
+ use GuzzleHttp\Ring\Core;
9
+ use GuzzleHttp\Ring\Future\FutureInterface;
10
+ use GuzzleHttp\Event\ListenerAttacherTrait;
11
+ use GuzzleHttp\Event\EndEvent;
12
+ use React\Promise\Deferred;
13
+ use React\Promise\FulfilledPromise;
14
+ use React\Promise\PromiseInterface;
15
+ use React\Promise\RejectedPromise;
16
+
17
+ /**
18
+ * Sends and iterator of requests concurrently using a capped pool size.
19
+ *
20
+ * The Pool object implements FutureInterface, meaning it can be used later
21
+ * when necessary, the requests provided to the pool can be cancelled, and
22
+ * you can check the state of the pool to know if it has been dereferenced
23
+ * (sent) or has been cancelled.
24
+ *
25
+ * When sending the pool, keep in mind that no results are returned: callers
26
+ * are expected to handle results asynchronously using Guzzle's event system.
27
+ * When requests complete, more are added to the pool to ensure that the
28
+ * requested pool size is always filled as much as possible.
29
+ *
30
+ * IMPORTANT: Do not provide a pool size greater that what the utilized
31
+ * underlying RingPHP handler can support. This will result is extremely poor
32
+ * performance.
33
+ */
34
+ class Pool implements FutureInterface
35
+ {
36
+ use ListenerAttacherTrait;
37
+
38
+ /** @var \GuzzleHttp\ClientInterface */
39
+ private $client;
40
+
41
+ /** @var \Iterator Yields requests */
42
+ private $iter;
43
+
44
+ /** @var Deferred */
45
+ private $deferred;
46
+
47
+ /** @var PromiseInterface */
48
+ private $promise;
49
+
50
+ private $waitQueue = [];
51
+ private $eventListeners = [];
52
+ private $poolSize;
53
+ private $isRealized = false;
54
+
55
+ /**
56
+ * The option values for 'before', 'complete', 'error' and 'end' can be a
57
+ * callable, an associative array containing event data, or an array of
58
+ * event data arrays. Event data arrays contain the following keys:
59
+ *
60
+ * - fn: callable to invoke that receives the event
61
+ * - priority: Optional event priority (defaults to 0)
62
+ * - once: Set to true so that the event is removed after it is triggered
63
+ *
64
+ * @param ClientInterface $client Client used to send the requests.
65
+ * @param array|\Iterator $requests Requests to send in parallel
66
+ * @param array $options Associative array of options
67
+ * - pool_size: (callable|int) Maximum number of requests to send
68
+ * concurrently, or a callback that receives
69
+ * the current queue size and returns the
70
+ * number of new requests to send
71
+ * - before: (callable|array) Receives a BeforeEvent
72
+ * - complete: (callable|array) Receives a CompleteEvent
73
+ * - error: (callable|array) Receives a ErrorEvent
74
+ * - end: (callable|array) Receives an EndEvent
75
+ */
76
+ public function __construct(
77
+ ClientInterface $client,
78
+ $requests,
79
+ array $options = []
80
+ ) {
81
+ $this->client = $client;
82
+ $this->iter = $this->coerceIterable($requests);
83
+ $this->deferred = new Deferred();
84
+ $this->promise = $this->deferred->promise();
85
+ $this->poolSize = isset($options['pool_size'])
86
+ ? $options['pool_size'] : 25;
87
+ $this->eventListeners = $this->prepareListeners(
88
+ $options,
89
+ ['before', 'complete', 'error', 'end']
90
+ );
91
+ }
92
+
93
+ /**
94
+ * Sends multiple requests in parallel and returns an array of responses
95
+ * and exceptions that uses the same ordering as the provided requests.
96
+ *
97
+ * IMPORTANT: This method keeps every request and response in memory, and
98
+ * as such, is NOT recommended when sending a large number or an
99
+ * indeterminate number of requests concurrently.
100
+ *
101
+ * @param ClientInterface $client Client used to send the requests
102
+ * @param array|\Iterator $requests Requests to send in parallel
103
+ * @param array $options Passes through the options available in
104
+ * {@see GuzzleHttp\Pool::__construct}
105
+ *
106
+ * @return BatchResults Returns a container for the results.
107
+ * @throws \InvalidArgumentException if the event format is incorrect.
108
+ */
109
+ public static function batch(
110
+ ClientInterface $client,
111
+ $requests,
112
+ array $options = []
113
+ ) {
114
+ $hash = new \SplObjectStorage();
115
+ foreach ($requests as $request) {
116
+ $hash->attach($request);
117
+ }
118
+
119
+ // In addition to the normally run events when requests complete, add
120
+ // and event to continuously track the results of transfers in the hash.
121
+ (new self($client, $requests, RequestEvents::convertEventArray(
122
+ $options,
123
+ ['end'],
124
+ [
125
+ 'priority' => RequestEvents::LATE,
126
+ 'fn' => function (EndEvent $e) use ($hash) {
127
+ $hash[$e->getRequest()] = $e->getException()
128
+ ? $e->getException()
129
+ : $e->getResponse();
130
+ }
131
+ ]
132
+ )))->wait();
133
+
134
+ return new BatchResults($hash);
135
+ }
136
+
137
+ /**
138
+ * Creates a Pool and immediately sends the requests.
139
+ *
140
+ * @param ClientInterface $client Client used to send the requests
141
+ * @param array|\Iterator $requests Requests to send in parallel
142
+ * @param array $options Passes through the options available in
143
+ * {@see GuzzleHttp\Pool::__construct}
144
+ */
145
+ public static function send(
146
+ ClientInterface $client,
147
+ $requests,
148
+ array $options = []
149
+ ) {
150
+ $pool = new self($client, $requests, $options);
151
+ $pool->wait();
152
+ }
153
+
154
+ private function getPoolSize()
155
+ {
156
+ return is_callable($this->poolSize)
157
+ ? call_user_func($this->poolSize, count($this->waitQueue))
158
+ : $this->poolSize;
159
+ }
160
+
161
+ /**
162
+ * Add as many requests as possible up to the current pool limit.
163
+ */
164
+ private function addNextRequests()
165
+ {
166
+ $limit = max($this->getPoolSize() - count($this->waitQueue), 0);
167
+ while ($limit--) {
168
+ if (!$this->addNextRequest()) {
169
+ break;
170
+ }
171
+ }
172
+ }
173
+
174
+ public function wait()
175
+ {
176
+ if ($this->isRealized) {
177
+ return false;
178
+ }
179
+
180
+ // Seed the pool with N number of requests.
181
+ $this->addNextRequests();
182
+
183
+ // Stop if the pool was cancelled while transferring requests.
184
+ if ($this->isRealized) {
185
+ return false;
186
+ }
187
+
188
+ // Wait on any outstanding FutureResponse objects.
189
+ while ($response = array_pop($this->waitQueue)) {
190
+ try {
191
+ $response->wait();
192
+ } catch (\Exception $e) {
193
+ // Eat exceptions because they should be handled asynchronously
194
+ }
195
+ $this->addNextRequests();
196
+ }
197
+
198
+ // Clean up no longer needed state.
199
+ $this->isRealized = true;
200
+ $this->waitQueue = $this->eventListeners = [];
201
+ $this->client = $this->iter = null;
202
+ $this->deferred->resolve(true);
203
+
204
+ return true;
205
+ }
206
+
207
+ /**
208
+ * {@inheritdoc}
209
+ *
210
+ * Attempt to cancel all outstanding requests (requests that are queued for
211
+ * dereferencing). Returns true if all outstanding requests can be
212
+ * cancelled.
213
+ *
214
+ * @return bool
215
+ */
216
+ public function cancel()
217
+ {
218
+ if ($this->isRealized) {
219
+ return false;
220
+ }
221
+
222
+ $success = $this->isRealized = true;
223
+ foreach ($this->waitQueue as $response) {
224
+ if (!$response->cancel()) {
225
+ $success = false;
226
+ }
227
+ }
228
+
229
+ return $success;
230
+ }
231
+
232
+ /**
233
+ * Returns a promise that is invoked when the pool completed. There will be
234
+ * no passed value.
235
+ *
236
+ * {@inheritdoc}
237
+ */
238
+ public function then(
239
+ callable $onFulfilled = null,
240
+ callable $onRejected = null,
241
+ callable $onProgress = null
242
+ ) {
243
+ return $this->promise->then($onFulfilled, $onRejected, $onProgress);
244
+ }
245
+
246
+ public function promise()
247
+ {
248
+ return $this->promise;
249
+ }
250
+
251
+ private function coerceIterable($requests)
252
+ {
253
+ if ($requests instanceof \Iterator) {
254
+ return $requests;
255
+ } elseif (is_array($requests)) {
256
+ return new \ArrayIterator($requests);
257
+ }
258
+
259
+ throw new \InvalidArgumentException('Expected Iterator or array. '
260
+ . 'Found ' . Core::describeType($requests));
261
+ }
262
+
263
+ /**
264
+ * Adds the next request to pool and tracks what requests need to be
265
+ * dereferenced when completing the pool.
266
+ */
267
+ private function addNextRequest()
268
+ {
269
+ add_next:
270
+
271
+ if ($this->isRealized || !$this->iter || !$this->iter->valid()) {
272
+ return false;
273
+ }
274
+
275
+ $request = $this->iter->current();
276
+ $this->iter->next();
277
+
278
+ if (!($request instanceof RequestInterface)) {
279
+ throw new \InvalidArgumentException(sprintf(
280
+ 'All requests in the provided iterator must implement '
281
+ . 'RequestInterface. Found %s',
282
+ Core::describeType($request)
283
+ ));
284
+ }
285
+
286
+ // Be sure to use "lazy" futures, meaning they do not send right away.
287
+ $request->getConfig()->set('future', 'lazy');
288
+ $hash = spl_object_hash($request);
289
+ $this->attachListeners($request, $this->eventListeners);
290
+ $request->getEmitter()->on('before', [$this, '_trackRetries'], RequestEvents::EARLY);
291
+ $response = $this->client->send($request);
292
+ $this->waitQueue[$hash] = $response;
293
+ $promise = $response->promise();
294
+
295
+ // Don't recursively call itself for completed or rejected responses.
296
+ if ($promise instanceof FulfilledPromise
297
+ || $promise instanceof RejectedPromise
298
+ ) {
299
+ try {
300
+ $this->finishResponse($request, $response->wait(), $hash);
301
+ } catch (\Exception $e) {
302
+ $this->finishResponse($request, $e, $hash);
303
+ }
304
+ goto add_next;
305
+ }
306
+
307
+ // Use this function for both resolution and rejection.
308
+ $thenFn = function ($value) use ($request, $hash) {
309
+ $this->finishResponse($request, $value, $hash);
310
+ if (!$request->getConfig()->get('_pool_retries')) {
311
+ $this->addNextRequests();
312
+ }
313
+ };
314
+
315
+ $promise->then($thenFn, $thenFn);
316
+
317
+ return true;
318
+ }
319
+
320
+ public function _trackRetries(BeforeEvent $e)
321
+ {
322
+ $e->getRequest()->getConfig()->set('_pool_retries', $e->getRetryCount());
323
+ }
324
+
325
+ private function finishResponse($request, $value, $hash)
326
+ {
327
+ unset($this->waitQueue[$hash]);
328
+ $result = $value instanceof ResponseInterface
329
+ ? ['request' => $request, 'response' => $value, 'error' => null]
330
+ : ['request' => $request, 'response' => null, 'error' => $value];
331
+ $this->deferred->notify($result);
332
+ }
333
+ }
vendor/guzzlehttp/guzzle/src/Post/MultipartBody.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Post;
3
+
4
+ use GuzzleHttp\Stream\AppendStream;
5
+ use GuzzleHttp\Stream\Stream;
6
+ use GuzzleHttp\Stream\StreamDecoratorTrait;
7
+ use GuzzleHttp\Stream\StreamInterface;
8
+
9
+ /**
10
+ * Stream that when read returns bytes for a streaming multipart/form-data body
11
+ */
12
+ class MultipartBody implements StreamInterface
13
+ {
14
+ use StreamDecoratorTrait;
15
+
16
+ private $boundary;
17
+
18
+ /**
19
+ * @param array $fields Associative array of field names to values where
20
+ * each value is a string or array of strings.
21
+ * @param array $files Associative array of PostFileInterface objects
22
+ * @param string $boundary You can optionally provide a specific boundary
23
+ * @throws \InvalidArgumentException
24
+ */
25
+ public function __construct(
26
+ array $fields = [],
27
+ array $files = [],
28
+ $boundary = null
29
+ ) {
30
+ $this->boundary = $boundary ?: uniqid();
31
+ $this->stream = $this->createStream($fields, $files);
32
+ }
33
+
34
+ /**
35
+ * Get the boundary
36
+ *
37
+ * @return string
38
+ */
39
+ public function getBoundary()
40
+ {
41
+ return $this->boundary;
42
+ }
43
+
44
+ public function isWritable()
45
+ {
46
+ return false;
47
+ }
48
+
49
+ /**
50
+ * Get the string needed to transfer a POST field
51
+ */
52
+ private function getFieldString($name, $value)
53
+ {
54
+ return sprintf(
55
+ "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n",
56
+ $this->boundary,
57
+ $name,
58
+ $value
59
+ );
60
+ }
61
+
62
+ /**
63
+ * Get the headers needed before transferring the content of a POST file
64
+ */
65
+ private function getFileHeaders(PostFileInterface $file)
66
+ {
67
+ $headers = '';
68
+ foreach ($file->getHeaders() as $key => $value) {
69
+ $headers .= "{$key}: {$value}\r\n";
70
+ }
71
+
72
+ return "--{$this->boundary}\r\n" . trim($headers) . "\r\n\r\n";
73
+ }
74
+
75
+ /**
76
+ * Create the aggregate stream that will be used to upload the POST data
77
+ */
78
+ protected function createStream(array $fields, array $files)
79
+ {
80
+ $stream = new AppendStream();
81
+
82
+ foreach ($fields as $name => $fieldValues) {
83
+ foreach ((array) $fieldValues as $value) {
84
+ $stream->addStream(
85
+ Stream::factory($this->getFieldString($name, $value))
86
+ );
87
+ }
88
+ }
89
+
90
+ foreach ($files as $file) {
91
+
92
+ if (!$file instanceof PostFileInterface) {
93
+ throw new \InvalidArgumentException('All POST fields must '
94
+ . 'implement PostFieldInterface');
95
+ }
96
+
97
+ $stream->addStream(
98
+ Stream::factory($this->getFileHeaders($file))
99
+ );
100
+ $stream->addStream($file->getContent());
101
+ $stream->addStream(Stream::factory("\r\n"));
102
+ }
103
+
104
+ // Add the trailing boundary with CRLF
105
+ $stream->addStream(Stream::factory("--{$this->boundary}--\r\n"));
106
+
107
+ return $stream;
108
+ }
109
+ }
vendor/guzzlehttp/guzzle/src/Post/PostBody.php ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Post;
3
+
4
+ use GuzzleHttp\Message\RequestInterface;
5
+ use GuzzleHttp\Stream\Exception\CannotAttachException;
6
+ use GuzzleHttp\Stream\StreamInterface;
7
+ use GuzzleHttp\Stream\Stream;
8
+ use GuzzleHttp\Query;
9
+
10
+ /**
11
+ * Holds POST fields and files and creates a streaming body when read methods
12
+ * are called on the object.
13
+ */
14
+ class PostBody implements PostBodyInterface
15
+ {
16
+ /** @var StreamInterface */
17
+ private $body;
18
+
19
+ /** @var callable */
20
+ private $aggregator;
21
+
22
+ private $fields = [];
23
+
24
+ /** @var PostFileInterface[] */
25
+ private $files = [];
26
+ private $forceMultipart = false;
27
+ private $detached = false;
28
+
29
+ /**
30
+ * Applies request headers to a request based on the POST state
31
+ *
32
+ * @param RequestInterface $request Request to update
33
+ */
34
+ public function applyRequestHeaders(RequestInterface $request)
35
+ {
36
+ if ($this->files || $this->forceMultipart) {
37
+ $request->setHeader(
38
+ 'Content-Type',
39
+ 'multipart/form-data; boundary=' . $this->getBody()->getBoundary()
40
+ );
41
+ } elseif ($this->fields && !$request->hasHeader('Content-Type')) {
42
+ $request->setHeader(
43
+ 'Content-Type',
44
+ 'application/x-www-form-urlencoded'
45
+ );
46
+ }
47
+
48
+ if ($size = $this->getSize()) {
49
+ $request->setHeader('Content-Length', $size);
50
+ }
51
+ }
52
+
53
+ public function forceMultipartUpload($force)
54
+ {
55
+ $this->forceMultipart = $force;
56
+ }
57
+
58
+ public function setAggregator(callable $aggregator)
59
+ {
60
+ $this->aggregator = $aggregator;
61
+ }
62
+
63
+ public function setField($name, $value)
64
+ {
65
+ $this->fields[$name] = $value;
66
+ $this->mutate();
67
+ }
68
+
69
+ public function replaceFields(array $fields)
70
+ {
71
+ $this->fields = $fields;
72
+ $this->mutate();
73
+ }
74
+
75
+ public function getField($name)
76
+ {
77
+ return isset($this->fields[$name]) ? $this->fields[$name] : null;
78
+ }
79
+
80
+ public function removeField($name)
81
+ {
82
+ unset($this->fields[$name]);
83
+ $this->mutate();
84
+ }
85
+
86
+ public function getFields($asString = false)
87
+ {
88
+ if (!$asString) {
89
+ return $this->fields;
90
+ }
91
+
92
+ $query = new Query($this->fields);
93
+ $query->setEncodingType(Query::RFC1738);
94
+ $query->setAggregator($this->getAggregator());
95
+
96
+ return (string) $query;
97
+ }
98
+
99
+ public function hasField($name)
100
+ {
101
+ return isset($this->fields[$name]);
102
+ }
103
+
104
+ public function getFile($name)
105
+ {
106
+ foreach ($this->files as $file) {
107
+ if ($file->getName() == $name) {
108
+ return $file;
109
+ }
110
+ }
111
+
112
+ return null;
113
+ }
114
+
115
+ public function getFiles()
116
+ {
117
+ return $this->files;
118
+ }
119
+
120
+ public function addFile(PostFileInterface $file)
121
+ {
122
+ $this->files[] = $file;
123
+ $this->mutate();
124
+ }
125
+
126
+ public function clearFiles()
127
+ {
128
+ $this->files = [];
129
+ $this->mutate();
130
+ }
131
+
132
+ /**
133
+ * Returns the numbers of fields + files
134
+ *
135
+ * @return int
136
+ */
137
+ public function count()
138
+ {
139
+ return count($this->files) + count($this->fields);
140
+ }
141
+
142
+ public function __toString()
143
+ {
144
+ return (string) $this->getBody();
145
+ }
146
+
147
+ public function getContents($maxLength = -1)
148
+ {
149
+ return $this->getBody()->getContents();
150
+ }
151
+
152
+ public function close()
153
+ {
154
+ $this->detach();
155
+ }
156
+
157
+ public function detach()
158
+ {
159
+ $this->detached = true;
160
+ $this->fields = $this->files = [];
161
+
162
+ if ($this->body) {
163
+ $this->body->close();
164
+ $this->body = null;
165
+ }
166
+ }
167
+
168
+ public function attach($stream)
169
+ {
170
+ throw new CannotAttachException();
171
+ }
172
+
173
+ public function eof()
174
+ {
175
+ return $this->getBody()->eof();
176
+ }
177
+
178
+ public function tell()
179
+ {
180
+ return $this->body ? $this->body->tell() : 0;
181
+ }
182
+
183
+ public function isSeekable()
184
+ {
185
+ return true;
186
+ }
187
+
188
+ public function isReadable()
189
+ {
190
+ return true;
191
+ }
192
+
193
+ public function isWritable()
194
+ {
195
+ return false;
196
+ }
197
+
198
+ public function getSize()
199
+ {
200
+ return $this->getBody()->getSize();
201
+ }
202
+
203
+ public function seek($offset, $whence = SEEK_SET)
204
+ {
205
+ return $this->getBody()->seek($offset, $whence);
206
+ }
207
+
208
+ public function read($length)
209
+ {
210
+ return $this->getBody()->read($length);
211
+ }
212
+
213
+ public function write($string)
214
+ {
215
+ return false;
216
+ }
217
+
218
+ public function getMetadata($key = null)
219
+ {
220
+ return $key ? null : [];
221
+ }
222
+
223
+ /**
224
+ * Return a stream object that is built from the POST fields and files.
225
+ *
226
+ * If one has already been created, the previously created stream will be
227
+ * returned.
228
+ */
229
+ private function getBody()
230
+ {
231
+ if ($this->body) {
232
+ return $this->body;
233
+ } elseif ($this->files || $this->forceMultipart) {
234
+ return $this->body = $this->createMultipart();
235
+ } elseif ($this->fields) {
236
+ return $this->body = $this->createUrlEncoded();
237
+ } else {
238
+ return $this->body = Stream::factory();
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Get the aggregator used to join multi-valued field parameters
244
+ *
245
+ * @return callable
246
+ */
247
+ final protected function getAggregator()
248
+ {
249
+ if (!$this->aggregator) {
250
+ $this->aggregator = Query::phpAggregator();
251
+ }
252
+
253
+ return $this->aggregator;
254
+ }
255
+
256
+ /**
257
+ * Creates a multipart/form-data body stream
258
+ *
259
+ * @return MultipartBody
260
+ */
261
+ private function createMultipart()
262
+ {
263
+ // Flatten the nested query string values using the correct aggregator
264
+ return new MultipartBody(
265
+ call_user_func($this->getAggregator(), $this->fields),
266
+ $this->files
267
+ );
268
+ }
269
+
270
+ /**
271
+ * Creates an application/x-www-form-urlencoded stream body
272
+ *
273
+ * @return StreamInterface
274
+ */
275
+ private function createUrlEncoded()
276
+ {
277
+ return Stream::factory($this->getFields(true));
278
+ }
279
+
280
+ /**
281
+ * Get rid of any cached data
282
+ */
283
+ private function mutate()
284
+ {
285
+ $this->body = null;
286
+ }
287
+ }
vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Post;
3
+
4
+ use GuzzleHttp\Message\AppliesHeadersInterface;
5
+ use GuzzleHttp\Stream\StreamInterface;
6
+
7
+ /**
8
+ * Represents a POST body that is sent as either a multipart/form-data stream
9
+ * or application/x-www-urlencoded stream.
10
+ */
11
+ interface PostBodyInterface extends StreamInterface, \Countable, AppliesHeadersInterface
12
+ {
13
+ /**
14
+ * Set a specific field
15
+ *
16
+ * @param string $name Name of the field to set
17
+ * @param string|array $value Value to set
18
+ */
19
+ public function setField($name, $value);
20
+
21
+ /**
22
+ * Set the aggregation strategy that will be used to turn multi-valued
23
+ * fields into a string.
24
+ *
25
+ * The aggregation function accepts a deeply nested array of query string
26
+ * values and returns a flattened associative array of key value pairs.
27
+ *
28
+ * @param callable $aggregator
29
+ */
30
+ public function setAggregator(callable $aggregator);
31
+
32
+ /**
33
+ * Set to true to force a multipart upload even if there are no files.
34
+ *
35
+ * @param bool $force Set to true to force multipart uploads or false to
36
+ * remove this flag.
37
+ */
38
+ public function forceMultipartUpload($force);
39
+
40
+ /**
41
+ * Replace all existing form fields with an array of fields
42
+ *
43
+ * @param array $fields Associative array of fields to set
44
+ */
45
+ public function replaceFields(array $fields);
46
+
47
+ /**
48
+ * Get a specific field by name
49
+ *
50
+ * @param string $name Name of the POST field to retrieve
51
+ *
52
+ * @return string|null
53
+ */
54
+ public function getField($name);
55
+
56
+ /**
57
+ * Remove a field by name
58
+ *
59
+ * @param string $name Name of the field to remove
60
+ */
61
+ public function removeField($name);
62
+
63
+ /**
64
+ * Returns an associative array of names to values or a query string.
65
+ *
66
+ * @param bool $asString Set to true to retrieve the fields as a query
67
+ * string.
68
+ *
69
+ * @return array|string
70
+ */
71
+ public function getFields($asString = false);
72
+
73
+ /**
74
+ * Returns true if a field is set
75
+ *
76
+ * @param string $name Name of the field to set
77
+ *
78
+ * @return bool
79
+ */
80
+ public function hasField($name);
81
+
82
+ /**
83
+ * Get all of the files
84
+ *
85
+ * @return array Returns an array of PostFileInterface objects
86
+ */
87
+ public function getFiles();
88
+
89
+ /**
90
+ * Get a POST file by name.
91
+ *
92
+ * @param string $name Name of the POST file to retrieve
93
+ *
94
+ * @return PostFileInterface|null
95
+ */
96
+ public function getFile($name);
97
+
98
+ /**
99
+ * Add a file to the POST
100
+ *
101
+ * @param PostFileInterface $file File to add
102
+ */
103
+ public function addFile(PostFileInterface $file);
104
+
105
+ /**
106
+ * Remove all files from the collection
107
+ */
108
+ public function clearFiles();
109
+ }
vendor/guzzlehttp/guzzle/src/Post/PostFile.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Post;
3
+
4
+ use GuzzleHttp\Mimetypes;
5
+ use GuzzleHttp\Stream\StreamInterface;
6
+ use GuzzleHttp\Stream\Stream;
7
+
8
+ /**
9
+ * Post file upload
10
+ */
11
+ class PostFile implements PostFileInterface
12
+ {
13
+ private $name;
14
+ private $filename;
15
+ private $content;
16
+ private $headers = [];
17
+
18
+ /**
19
+ * @param string $name Name of the form field
20
+ * @param mixed $content Data to send
21
+ * @param string|null $filename Filename content-disposition attribute
22
+ * @param array $headers Array of headers to set on the file
23
+ * (can override any default headers)
24
+ * @throws \RuntimeException when filename is not passed or can't be determined
25
+ */
26
+ public function __construct(
27
+ $name,
28
+ $content,
29
+ $filename = null,
30
+ array $headers = []
31
+ ) {
32
+ $this->headers = $headers;
33
+ $this->name = $name;
34
+ $this->prepareContent($content);
35
+ $this->prepareFilename($filename);
36
+ $this->prepareDefaultHeaders();
37
+ }
38
+
39
+ public function getName()
40
+ {
41
+ return $this->name;
42
+ }
43
+
44
+ public function getFilename()
45
+ {
46
+ return $this->filename;
47
+ }
48
+
49
+ public function getContent()
50
+ {
51
+ return $this->content;
52
+ }
53
+
54
+ public function getHeaders()
55
+ {
56
+ return $this->headers;
57
+ }
58
+
59
+ /**
60
+ * Prepares the contents of a POST file.
61
+ *
62
+ * @param mixed $content Content of the POST file
63
+ */
64
+ private function prepareContent($content)
65
+ {
66
+ $this->content = $content;
67
+
68
+ if (!($this->content instanceof StreamInterface)) {
69
+ $this->content = Stream::factory($this->content);
70
+ } elseif ($this->content instanceof MultipartBody) {
71
+ if (!$this->hasHeader('Content-Disposition')) {
72
+ $disposition = 'form-data; name="' . $this->name .'"';
73
+ $this->headers['Content-Disposition'] = $disposition;
74
+ }
75
+
76
+ if (!$this->hasHeader('Content-Type')) {
77
+ $this->headers['Content-Type'] = sprintf(
78
+ "multipart/form-data; boundary=%s",
79
+ $this->content->getBoundary()
80
+ );
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Applies a file name to the POST file based on various checks.
87
+ *
88
+ * @param string|null $filename Filename to apply (or null to guess)
89
+ */
90
+ private function prepareFilename($filename)
91
+ {
92
+ $this->filename = $filename;
93
+
94
+ if (!$this->filename) {
95
+ $this->filename = $this->content->getMetadata('uri');
96
+ }
97
+
98
+ if (!$this->filename || substr($this->filename, 0, 6) === 'php://') {
99
+ $this->filename = $this->name;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Applies default Content-Disposition and Content-Type headers if needed.
105
+ */
106
+ private function prepareDefaultHeaders()
107
+ {
108
+ // Set a default content-disposition header if one was no provided
109
+ if (!$this->hasHeader('Content-Disposition')) {
110
+ $this->headers['Content-Disposition'] = sprintf(
111
+ 'form-data; name="%s"; filename="%s"',
112
+ $this->name,
113
+ basename($this->filename)
114
+ );
115
+ }
116
+
117
+ // Set a default Content-Type if one was not supplied
118
+ if (!$this->hasHeader('Content-Type')) {
119
+ $this->headers['Content-Type'] = Mimetypes::getInstance()
120
+ ->fromFilename($this->filename) ?: 'text/plain';
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Check if a specific header exists on the POST file by name.
126
+ *
127
+ * @param string $name Case-insensitive header to check
128
+ *
129
+ * @return bool
130
+ */
131
+ private function hasHeader($name)
132
+ {
133
+ return isset(array_change_key_case($this->headers)[strtolower($name)]);
134
+ }
135
+ }
vendor/guzzlehttp/guzzle/src/Post/PostFileInterface.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Post;
3
+
4
+ use GuzzleHttp\Stream\StreamInterface;
5
+
6
+ /**
7
+ * Post file upload interface
8
+ */
9
+ interface PostFileInterface
10
+ {
11
+ /**
12
+ * Get the name of the form field
13
+ *
14
+ * @return string
15
+ */
16
+ public function getName();
17
+
18
+ /**
19
+ * Get the full path to the file
20
+ *
21
+ * @return string
22
+ */
23
+ public function getFilename();
24
+
25
+ /**
26
+ * Get the content
27
+ *
28
+ * @return StreamInterface
29
+ */
30
+ public function getContent();
31
+
32
+ /**
33
+ * Gets all POST file headers.
34
+ *
35
+ * The keys represent the header name as it will be sent over the wire, and
36
+ * each value is a string.
37
+ *
38
+ * @return array Returns an associative array of the file's headers.
39
+ */
40
+ public function getHeaders();
41
+ }
vendor/guzzlehttp/guzzle/src/Query.php ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Manages query string variables and can aggregate them into a string
6
+ */
7
+ class Query extends Collection
8
+ {
9
+ const RFC3986 = 'RFC3986';
10
+ const RFC1738 = 'RFC1738';
11
+
12
+ /** @var callable Encoding function */
13
+ private $encoding = 'rawurlencode';
14
+ /** @var callable */
15
+ private $aggregator;
16
+
17
+ /**
18
+ * Parse a query string into a Query object
19
+ *
20
+ * $urlEncoding is used to control how the query string is parsed and how
21
+ * it is ultimately serialized. The value can be set to one of the
22
+ * following:
23
+ *
24
+ * - true: (default) Parse query strings using RFC 3986 while still
25
+ * converting "+" to " ".
26
+ * - false: Disables URL decoding of the input string and URL encoding when
27
+ * the query string is serialized.
28
+ * - 'RFC3986': Use RFC 3986 URL encoding/decoding
29
+ * - 'RFC1738': Use RFC 1738 URL encoding/decoding
30
+ *
31
+ * @param string $query Query string to parse
32
+ * @param bool|string $urlEncoding Controls how the input string is decoded
33
+ * and encoded.
34
+ * @return self
35
+ */
36
+ public static function fromString($query, $urlEncoding = true)
37
+ {
38
+ static $qp;
39
+ if (!$qp) {
40
+ $qp = new QueryParser();
41
+ }
42
+
43
+ $q = new static();
44
+
45
+ if ($urlEncoding !== true) {
46
+ $q->setEncodingType($urlEncoding);
47
+ }
48
+
49
+ $qp->parseInto($q, $query, $urlEncoding);
50
+
51
+ return $q;
52
+ }
53
+
54
+ /**
55
+ * Convert the query string parameters to a query string string
56
+ *
57
+ * @return string
58
+ */
59
+ public function __toString()
60
+ {
61
+ if (!$this->data) {
62
+ return '';
63
+ }
64
+
65
+ // The default aggregator is statically cached
66
+ static $defaultAggregator;
67
+
68
+ if (!$this->aggregator) {
69
+ if (!$defaultAggregator) {
70
+ $defaultAggregator = self::phpAggregator();
71
+ }
72
+ $this->aggregator = $defaultAggregator;
73
+ }
74
+
75
+ $result = '';
76
+ $aggregator = $this->aggregator;
77
+ $encoder = $this->encoding;
78
+
79
+ foreach ($aggregator($this->data) as $key => $values) {
80
+ foreach ($values as $value) {
81
+ if ($result) {
82
+ $result .= '&';
83
+ }
84
+ $result .= $encoder($key);
85
+ if ($value !== null) {
86
+ $result .= '=' . $encoder($value);
87
+ }
88
+ }
89
+ }
90
+
91
+ return $result;
92
+ }
93
+
94
+ /**
95
+ * Controls how multi-valued query string parameters are aggregated into a
96
+ * string.
97
+ *
98
+ * $query->setAggregator($query::duplicateAggregator());
99
+ *
100
+ * @param callable $aggregator Callable used to convert a deeply nested
101
+ * array of query string variables into a flattened array of key value
102
+ * pairs. The callable accepts an array of query data and returns a
103
+ * flattened array of key value pairs where each value is an array of
104
+ * strings.
105
+ */
106
+ public function setAggregator(callable $aggregator)
107
+ {
108
+ $this->aggregator = $aggregator;
109
+ }
110
+
111
+ /**
112
+ * Specify how values are URL encoded
113
+ *
114
+ * @param string|bool $type One of 'RFC1738', 'RFC3986', or false to disable encoding
115
+ *
116
+ * @throws \InvalidArgumentException
117
+ */
118
+ public function setEncodingType($type)
119
+ {
120
+ switch ($type) {
121
+ case self::RFC3986:
122
+ $this->encoding = 'rawurlencode';
123
+ break;
124
+ case self::RFC1738:
125
+ $this->encoding = 'urlencode';
126
+ break;
127
+ case false:
128
+ $this->encoding = function ($v) { return $v; };
129
+ break;
130
+ default:
131
+ throw new \InvalidArgumentException('Invalid URL encoding type');
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Query string aggregator that does not aggregate nested query string
137
+ * values and allows duplicates in the resulting array.
138
+ *
139
+ * Example: http://test.com?q=1&q=2
140
+ *
141
+ * @return callable
142
+ */
143
+ public static function duplicateAggregator()
144
+ {
145
+ return function (array $data) {
146
+ return self::walkQuery($data, '', function ($key, $prefix) {
147
+ return is_int($key) ? $prefix : "{$prefix}[{$key}]";
148
+ });
149
+ };
150
+ }
151
+
152
+ /**
153
+ * Aggregates nested query string variables using the same technique as
154
+ * ``http_build_query()``.
155
+ *
156
+ * @param bool $numericIndices Pass false to not include numeric indices
157
+ * when multi-values query string parameters are present.
158
+ *
159
+ * @return callable
160
+ */
161
+ public static function phpAggregator($numericIndices = true)
162
+ {
163
+ return function (array $data) use ($numericIndices) {
164
+ return self::walkQuery(
165
+ $data,
166
+ '',
167
+ function ($key, $prefix) use ($numericIndices) {
168
+ return !$numericIndices && is_int($key)
169
+ ? "{$prefix}[]"
170
+ : "{$prefix}[{$key}]";
171
+ }
172
+ );
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Easily create query aggregation functions by providing a key prefix
178
+ * function to this query string array walker.
179
+ *
180
+ * @param array $query Query string to walk
181
+ * @param string $keyPrefix Key prefix (start with '')
182
+ * @param callable $prefixer Function used to create a key prefix
183
+ *
184
+ * @return array
185
+ */
186
+ public static function walkQuery(array $query, $keyPrefix, callable $prefixer)
187
+ {
188
+ $result = [];
189
+ foreach ($query as $key => $value) {
190
+ if ($keyPrefix) {
191
+ $key = $prefixer($key, $keyPrefix);
192
+ }
193
+ if (is_array($value)) {
194
+ $result += self::walkQuery($value, $key, $prefixer);
195
+ } elseif (isset($result[$key])) {
196
+ $result[$key][] = $value;
197
+ } else {
198
+ $result[$key] = array($value);
199
+ }
200
+ }
201
+
202
+ return $result;
203
+ }
204
+ }
vendor/guzzlehttp/guzzle/src/QueryParser.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Parses query strings into a Query object.
6
+ *
7
+ * While parsing, the parser will attempt to determine the most appropriate
8
+ * query string aggregator to use when serializing the parsed query string
9
+ * object back into a string. The hope is that parsing then serializing a
10
+ * query string should be a lossless operation.
11
+ *
12
+ * @internal Use Query::fromString()
13
+ */
14
+ class QueryParser
15
+ {
16
+ private $duplicates;
17
+ private $numericIndices;
18
+
19
+ /**
20
+ * Parse a query string into a Query object.
21
+ *
22
+ * @param Query $query Query object to populate
23
+ * @param string $str Query string to parse
24
+ * @param bool|string $urlEncoding How the query string is encoded
25
+ */
26
+ public function parseInto(Query $query, $str, $urlEncoding = true)
27
+ {
28
+ if ($str === '') {
29
+ return;
30
+ }
31
+
32
+ $result = [];
33
+ $this->duplicates = false;
34
+ $this->numericIndices = true;
35
+ $decoder = self::getDecoder($urlEncoding);
36
+
37
+ foreach (explode('&', $str) as $kvp) {
38
+
39
+ $parts = explode('=', $kvp, 2);
40
+ $key = $decoder($parts[0]);
41
+ $value = isset($parts[1]) ? $decoder($parts[1]) : null;
42
+
43
+ // Special handling needs to be taken for PHP nested array syntax
44
+ if (strpos($key, '[') !== false) {
45
+ $this->parsePhpValue($key, $value, $result);
46
+ continue;
47
+ }
48
+
49
+ if (!isset($result[$key])) {
50
+ $result[$key] = $value;
51
+ } else {
52
+ $this->duplicates = true;
53
+ if (!is_array($result[$key])) {
54
+ $result[$key] = [$result[$key]];
55
+ }
56
+ $result[$key][] = $value;
57
+ }
58
+ }
59
+
60
+ $query->replace($result);
61
+
62
+ if (!$this->numericIndices) {
63
+ $query->setAggregator(Query::phpAggregator(false));
64
+ } elseif ($this->duplicates) {
65
+ $query->setAggregator(Query::duplicateAggregator());
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Returns a callable that is used to URL decode query keys and values.
71
+ *
72
+ * @param string|bool $type One of true, false, RFC3986, and RFC1738
73
+ *
74
+ * @return callable|string
75
+ */
76
+ private static function getDecoder($type)
77
+ {
78
+ if ($type === true) {
79
+ return function ($value) {
80
+ return rawurldecode(str_replace('+', ' ', $value));
81
+ };
82
+ } elseif ($type == Query::RFC3986) {
83
+ return 'rawurldecode';
84
+ } elseif ($type == Query::RFC1738) {
85
+ return 'urldecode';
86
+ } else {
87
+ return function ($str) { return $str; };
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Parses a PHP style key value pair.
93
+ *
94
+ * @param string $key Key to parse (e.g., "foo[a][b]")
95
+ * @param string|null $value Value to set
96
+ * @param array $result Result to modify by reference
97
+ */
98
+ private function parsePhpValue($key, $value, array &$result)
99
+ {
100
+ $node =& $result;
101
+ $keyBuffer = '';
102
+
103
+ for ($i = 0, $t = strlen($key); $i < $t; $i++) {
104
+ switch ($key[$i]) {
105
+ case '[':
106
+ if ($keyBuffer) {
107
+ $this->prepareNode($node, $keyBuffer);
108
+ $node =& $node[$keyBuffer];
109
+ $keyBuffer = '';
110
+ }
111
+ break;
112
+ case ']':
113
+ $k = $this->cleanKey($node, $keyBuffer);
114
+ $this->prepareNode($node, $k);
115
+ $node =& $node[$k];
116
+ $keyBuffer = '';
117
+ break;
118
+ default:
119
+ $keyBuffer .= $key[$i];
120
+ break;
121
+ }
122
+ }
123
+
124
+ if (isset($node)) {
125
+ $this->duplicates = true;
126
+ $node[] = $value;
127
+ } else {
128
+ $node = $value;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Prepares a value in the array at the given key.
134
+ *
135
+ * If the key already exists, the key value is converted into an array.
136
+ *
137
+ * @param array $node Result node to modify
138
+ * @param string $key Key to add or modify in the node
139
+ */
140
+ private function prepareNode(&$node, $key)
141
+ {
142
+ if (!isset($node[$key])) {
143
+ $node[$key] = null;
144
+ } elseif (!is_array($node[$key])) {
145
+ $node[$key] = [$node[$key]];
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Returns the appropriate key based on the node and key.
151
+ */
152
+ private function cleanKey($node, $key)
153
+ {
154
+ if ($key === '') {
155
+ $key = $node ? (string) count($node) : 0;
156
+ // Found a [] key, so track this to ensure that we disable numeric
157
+ // indexing of keys in the resolved query aggregator.
158
+ $this->numericIndices = false;
159
+ }
160
+
161
+ return $key;
162
+ }
163
+ }
vendor/guzzlehttp/guzzle/src/RequestFsm.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Event\BeforeEvent;
5
+ use GuzzleHttp\Event\ErrorEvent;
6
+ use GuzzleHttp\Event\CompleteEvent;
7
+ use GuzzleHttp\Event\EndEvent;
8
+ use GuzzleHttp\Exception\StateException;
9
+ use GuzzleHttp\Exception\RequestException;
10
+ use GuzzleHttp\Message\FutureResponse;
11
+ use GuzzleHttp\Message\MessageFactoryInterface;
12
+ use GuzzleHttp\Ring\Future\FutureInterface;
13
+
14
+ /**
15
+ * Responsible for transitioning requests through lifecycle events.
16
+ */
17
+ class RequestFsm
18
+ {
19
+ private $handler;
20
+ private $mf;
21
+ private $maxTransitions;
22
+
23
+ public function __construct(
24
+ callable $handler,
25
+ MessageFactoryInterface $messageFactory,
26
+ $maxTransitions = 200
27
+ ) {
28
+ $this->mf = $messageFactory;
29
+ $this->maxTransitions = $maxTransitions;
30
+ $this->handler = $handler;
31
+ }
32
+
33
+ /**
34
+ * Runs the state machine until a terminal state is entered or the
35
+ * optionally supplied $finalState is entered.
36
+ *
37
+ * @param Transaction $trans Transaction being transitioned.
38
+ *
39
+ * @throws \Exception if a terminal state throws an exception.
40
+ */
41
+ public function __invoke(Transaction $trans)
42
+ {
43
+ $trans->_transitionCount = 0;
44
+
45
+ if (!$trans->state) {
46
+ $trans->state = 'before';
47
+ }
48
+
49
+ transition:
50
+
51
+ if (++$trans->_transitionCount > $this->maxTransitions) {
52
+ throw new StateException("Too many state transitions were "
53
+ . "encountered ({$trans->_transitionCount}). This likely "
54
+ . "means that a combination of event listeners are in an "
55
+ . "infinite loop.");
56
+ }
57
+
58
+ switch ($trans->state) {
59
+ case 'before': goto before;
60
+ case 'complete': goto complete;
61
+ case 'error': goto error;
62
+ case 'retry': goto retry;
63
+ case 'send': goto send;
64
+ case 'end': goto end;
65
+ default: throw new StateException("Invalid state: {$trans->state}");
66
+ }
67
+
68
+ before: {
69
+ try {
70
+ $trans->request->getEmitter()->emit('before', new BeforeEvent($trans));
71
+ $trans->state = 'send';
72
+ if ((bool) $trans->response) {
73
+ $trans->state = 'complete';
74
+ }
75
+ } catch (\Exception $e) {
76
+ $trans->state = 'error';
77
+ $trans->exception = $e;
78
+ }
79
+ goto transition;
80
+ }
81
+
82
+ complete: {
83
+ try {
84
+ if ($trans->response instanceof FutureInterface) {
85
+ // Futures will have their own end events emitted when
86
+ // dereferenced.
87
+ return;
88
+ }
89
+ $trans->state = 'end';
90
+ $trans->response->setEffectiveUrl($trans->request->getUrl());
91
+ $trans->request->getEmitter()->emit('complete', new CompleteEvent($trans));
92
+ } catch (\Exception $e) {
93
+ $trans->state = 'error';
94
+ $trans->exception = $e;
95
+ }
96
+ goto transition;
97
+ }
98
+
99
+ error: {
100
+ try {
101
+ // Convert non-request exception to a wrapped exception
102
+ $trans->exception = RequestException::wrapException(
103
+ $trans->request, $trans->exception
104
+ );
105
+ $trans->state = 'end';
106
+ $trans->request->getEmitter()->emit('error', new ErrorEvent($trans));
107
+ // An intercepted request (not retried) transitions to complete
108
+ if (!$trans->exception && $trans->state !== 'retry') {
109
+ $trans->state = 'complete';
110
+ }
111
+ } catch (\Exception $e) {
112
+ $trans->state = 'end';
113
+ $trans->exception = $e;
114
+ }
115
+ goto transition;
116
+ }
117
+
118
+ retry: {
119
+ $trans->retries++;
120
+ $trans->response = null;
121
+ $trans->exception = null;
122
+ $trans->state = 'before';
123
+ goto transition;
124
+ }
125
+
126
+ send: {
127
+ $fn = $this->handler;
128
+ $trans->response = FutureResponse::proxy(
129
+ $fn(RingBridge::prepareRingRequest($trans)),
130
+ function ($value) use ($trans) {
131
+ RingBridge::completeRingResponse($trans, $value, $this->mf, $this);
132
+ $this($trans);
133
+ return $trans->response;
134
+ }
135
+ );
136
+ return;
137
+ }
138
+
139
+ end: {
140
+ $trans->request->getEmitter()->emit('end', new EndEvent($trans));
141
+ // Throw exceptions in the terminal event if the exception
142
+ // was not handled by an "end" event listener.
143
+ if ($trans->exception) {
144
+ if (!($trans->exception instanceof RequestException)) {
145
+ $trans->exception = RequestException::wrapException(
146
+ $trans->request, $trans->exception
147
+ );
148
+ }
149
+ throw $trans->exception;
150
+ }
151
+ }
152
+ }
153
+ }
vendor/guzzlehttp/guzzle/src/RingBridge.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Message\MessageFactoryInterface;
5
+ use GuzzleHttp\Message\RequestInterface;
6
+ use GuzzleHttp\Event\ProgressEvent;
7
+ use GuzzleHttp\Message\Request;
8
+ use GuzzleHttp\Ring\Core;
9
+ use GuzzleHttp\Stream\Stream;
10
+ use GuzzleHttp\Exception\RequestException;
11
+
12
+ /**
13
+ * Provides the bridge between Guzzle requests and responses and Guzzle Ring.
14
+ */
15
+ class RingBridge
16
+ {
17
+ /**
18
+ * Creates a Ring request from a request object.
19
+ *
20
+ * This function does not hook up the "then" and "progress" events that
21
+ * would be required for actually sending a Guzzle request through a
22
+ * RingPHP handler.
23
+ *
24
+ * @param RequestInterface $request Request to convert.
25
+ *
26
+ * @return array Converted Guzzle Ring request.
27
+ */
28
+ public static function createRingRequest(RequestInterface $request)
29
+ {
30
+ $options = $request->getConfig()->toArray();
31
+ $url = $request->getUrl();
32
+ // No need to calculate the query string twice (in URL and query).
33
+ $qs = ($pos = strpos($url, '?')) ? substr($url, $pos + 1) : null;
34
+
35
+ return [
36
+ 'scheme' => $request->getScheme(),
37
+ 'http_method' => $request->getMethod(),
38
+ 'url' => $url,
39
+ 'uri' => $request->getPath(),
40
+ 'headers' => $request->getHeaders(),
41
+ 'body' => $request->getBody(),
42
+ 'version' => $request->getProtocolVersion(),
43
+ 'client' => $options,
44
+ 'query_string' => $qs,
45
+ 'future' => isset($options['future']) ? $options['future'] : false
46
+ ];
47
+ }
48
+
49
+ /**
50
+ * Creates a Ring request from a request object AND prepares the callbacks.
51
+ *
52
+ * @param Transaction $trans Transaction to update.
53
+ *
54
+ * @return array Converted Guzzle Ring request.
55
+ */
56
+ public static function prepareRingRequest(Transaction $trans)
57
+ {
58
+ // Clear out the transaction state when initiating.
59
+ $trans->exception = null;
60
+ $request = self::createRingRequest($trans->request);
61
+
62
+ // Emit progress events if any progress listeners are registered.
63
+ if ($trans->request->getEmitter()->hasListeners('progress')) {
64
+ $emitter = $trans->request->getEmitter();
65
+ $request['client']['progress'] = function ($a, $b, $c, $d) use ($trans, $emitter) {
66
+ $emitter->emit('progress', new ProgressEvent($trans, $a, $b, $c, $d));
67
+ };
68
+ }
69
+
70
+ return $request;
71
+ }
72
+
73
+ /**
74
+ * Handles the process of processing a response received from a ring
75
+ * handler. The created response is added to the transaction, and the
76
+ * transaction stat is set appropriately.
77
+ *
78
+ * @param Transaction $trans Owns request and response.
79
+ * @param array $response Ring response array
80
+ * @param MessageFactoryInterface $messageFactory Creates response objects.
81
+ */
82
+ public static function completeRingResponse(
83
+ Transaction $trans,
84
+ array $response,
85
+ MessageFactoryInterface $messageFactory
86
+ ) {
87
+ $trans->state = 'complete';
88
+ $trans->transferInfo = isset($response['transfer_stats'])
89
+ ? $response['transfer_stats'] : [];
90
+
91
+ if (!empty($response['status'])) {
92
+ $options = [];
93
+ if (isset($response['version'])) {
94
+ $options['protocol_version'] = $response['version'];
95
+ }
96
+ if (isset($response['reason'])) {
97
+ $options['reason_phrase'] = $response['reason'];
98
+ }
99
+ $trans->response = $messageFactory->createResponse(
100
+ $response['status'],
101
+ isset($response['headers']) ? $response['headers'] : [],
102
+ isset($response['body']) ? $response['body'] : null,
103
+ $options
104
+ );
105
+ if (isset($response['effective_url'])) {
106
+ $trans->response->setEffectiveUrl($response['effective_url']);
107
+ }
108
+ } elseif (empty($response['error'])) {
109
+ // When nothing was returned, then we need to add an error.
110
+ $response['error'] = self::getNoRingResponseException($trans->request);
111
+ }
112
+
113
+ if (isset($response['error'])) {
114
+ $trans->state = 'error';
115
+ $trans->exception = $response['error'];
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Creates a Guzzle request object using a ring request array.
121
+ *
122
+ * @param array $request Ring request
123
+ *
124
+ * @return Request
125
+ * @throws \InvalidArgumentException for incomplete requests.
126
+ */
127
+ public static function fromRingRequest(array $request)
128
+ {
129
+ $options = [];
130
+ if (isset($request['version'])) {
131
+ $options['protocol_version'] = $request['version'];
132
+ }
133
+
134
+ if (!isset($request['http_method'])) {
135
+ throw new \InvalidArgumentException('No http_method');
136
+ }
137
+
138
+ return new Request(
139
+ $request['http_method'],
140
+ Core::url($request),
141
+ isset($request['headers']) ? $request['headers'] : [],
142
+ isset($request['body']) ? Stream::factory($request['body']) : null,
143
+ $options
144
+ );
145
+ }
146
+
147
+ /**
148
+ * Get an exception that can be used when a RingPHP handler does not
149
+ * populate a response.
150
+ *
151
+ * @param RequestInterface $request
152
+ *
153
+ * @return RequestException
154
+ */
155
+ public static function getNoRingResponseException(RequestInterface $request)
156
+ {
157
+ $message = <<<EOT
158
+ Sending the request did not return a response, exception, or populate the
159
+ transaction with a response. This is most likely due to an incorrectly
160
+ implemented RingPHP handler. If you are simply trying to mock responses,
161
+ then it is recommended to use the GuzzleHttp\Ring\Client\MockHandler.
162
+ EOT;
163
+ return new RequestException($message, $request);
164
+ }
165
+ }
vendor/guzzlehttp/guzzle/src/Subscriber/Cookie.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Subscriber;
3
+
4
+ use GuzzleHttp\Cookie\CookieJar;
5
+ use GuzzleHttp\Cookie\CookieJarInterface;
6
+ use GuzzleHttp\Event\BeforeEvent;
7
+ use GuzzleHttp\Event\CompleteEvent;
8
+ use GuzzleHttp\Event\RequestEvents;
9
+ use GuzzleHttp\Event\SubscriberInterface;
10
+
11
+ /**
12
+ * Adds, extracts, and persists cookies between HTTP requests
13
+ */
14
+ class Cookie implements SubscriberInterface
15
+ {
16
+ /** @var CookieJarInterface */
17
+ private $cookieJar;
18
+
19
+ /**
20
+ * @param CookieJarInterface $cookieJar Cookie jar used to hold cookies
21
+ */
22
+ public function __construct(CookieJarInterface $cookieJar = null)
23
+ {
24
+ $this->cookieJar = $cookieJar ?: new CookieJar();
25
+ }
26
+
27
+ public function getEvents()
28
+ {
29
+ // Fire the cookie plugin complete event before redirecting
30
+ return [
31
+ 'before' => ['onBefore'],
32
+ 'complete' => ['onComplete', RequestEvents::REDIRECT_RESPONSE + 10]
33
+ ];
34
+ }
35
+
36
+ /**
37
+ * Get the cookie cookieJar
38
+ *
39
+ * @return CookieJarInterface
40
+ */
41
+ public function getCookieJar()
42
+ {
43
+ return $this->cookieJar;
44
+ }
45
+
46
+ public function onBefore(BeforeEvent $event)
47
+ {
48
+ $this->cookieJar->addCookieHeader($event->getRequest());
49
+ }
50
+
51
+ public function onComplete(CompleteEvent $event)
52
+ {
53
+ $this->cookieJar->extractCookies(
54
+ $event->getRequest(),
55
+ $event->getResponse()
56
+ );
57
+ }
58
+ }
vendor/guzzlehttp/guzzle/src/Subscriber/History.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Subscriber;
3
+
4
+ use GuzzleHttp\Event\CompleteEvent;
5
+ use GuzzleHttp\Event\ErrorEvent;
6
+ use GuzzleHttp\Event\RequestEvents;
7
+ use GuzzleHttp\Event\SubscriberInterface;
8
+ use GuzzleHttp\Message\RequestInterface;
9
+ use GuzzleHttp\Message\ResponseInterface;
10
+
11
+ /**
12
+ * Maintains a list of requests and responses sent using a request or client
13
+ */
14
+ class History implements SubscriberInterface, \IteratorAggregate, \Countable
15
+ {
16
+ /** @var int The maximum number of requests to maintain in the history */
17
+ private $limit;
18
+
19
+ /** @var array Requests and responses that have passed through the plugin */
20
+ private $transactions = [];
21
+
22
+ public function __construct($limit = 10)
23
+ {
24
+ $this->limit = $limit;
25
+ }
26
+
27
+ public function getEvents()
28
+ {
29
+ return [
30
+ 'complete' => ['onComplete', RequestEvents::EARLY],
31
+ 'error' => ['onError', RequestEvents::EARLY],
32
+ ];
33
+ }
34
+
35
+ /**
36
+ * Convert to a string that contains all request and response headers
37
+ *
38
+ * @return string
39
+ */
40
+ public function __toString()
41
+ {
42
+ $lines = array();
43
+ foreach ($this->transactions as $entry) {
44
+ $response = isset($entry['response']) ? $entry['response'] : '';
45
+ $lines[] = '> ' . trim($entry['sent_request'])
46
+ . "\n\n< " . trim($response) . "\n";
47
+ }
48
+
49
+ return implode("\n", $lines);
50
+ }
51
+
52
+ public function onComplete(CompleteEvent $event)
53
+ {
54
+ $this->add($event->getRequest(), $event->getResponse());
55
+ }
56
+
57
+ public function onError(ErrorEvent $event)
58
+ {
59
+ // Only track when no response is present, meaning this didn't ever
60
+ // emit a complete event
61
+ if (!$event->getResponse()) {
62
+ $this->add($event->getRequest());
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Returns an Iterator that yields associative array values where each
68
+ * associative array contains the following key value pairs:
69
+ *
70
+ * - request: Representing the actual request that was received.
71
+ * - sent_request: A clone of the request that will not be mutated.
72
+ * - response: The response that was received (if available).
73
+ *
74
+ * @return \Iterator
75
+ */
76
+ public function getIterator()
77
+ {
78
+ return new \ArrayIterator($this->transactions);
79
+ }
80
+
81
+ /**
82
+ * Get all of the requests sent through the plugin.
83
+ *
84
+ * Requests can be modified after they are logged by the history
85
+ * subscriber. By default this method will return the actual request
86
+ * instances that were received. Pass true to this method if you wish to
87
+ * get copies of the requests that represent the request state when it was
88
+ * initially logged by the history subscriber.
89
+ *
90
+ * @param bool $asSent Set to true to get clones of the requests that have
91
+ * not been mutated since the request was received by
92
+ * the history subscriber.
93
+ *
94
+ * @return RequestInterface[]
95
+ */
96
+ public function getRequests($asSent = false)
97
+ {
98
+ return array_map(function ($t) use ($asSent) {
99
+ return $asSent ? $t['sent_request'] : $t['request'];
100
+ }, $this->transactions);
101
+ }
102
+
103
+ /**
104
+ * Get the number of requests in the history
105
+ *
106
+ * @return int
107
+ */
108
+ public function count()
109
+ {
110
+ return count($this->transactions);
111
+ }
112
+
113
+ /**
114
+ * Get the last request sent.
115
+ *
116
+ * Requests can be modified after they are logged by the history
117
+ * subscriber. By default this method will return the actual request
118
+ * instance that was received. Pass true to this method if you wish to get
119
+ * a copy of the request that represents the request state when it was
120
+ * initially logged by the history subscriber.
121
+ *
122
+ * @param bool $asSent Set to true to get a clone of the last request that
123
+ * has not been mutated since the request was received
124
+ * by the history subscriber.
125
+ *
126
+ * @return RequestInterface
127
+ */
128
+ public function getLastRequest($asSent = false)
129
+ {
130
+ return $asSent
131
+ ? end($this->transactions)['sent_request']
132
+ : end($this->transactions)['request'];
133
+ }
134
+
135
+ /**
136
+ * Get the last response in the history
137
+ *
138
+ * @return ResponseInterface|null
139
+ */
140
+ public function getLastResponse()
141
+ {
142
+ return end($this->transactions)['response'];
143
+ }
144
+
145
+ /**
146
+ * Clears the history
147
+ */
148
+ public function clear()
149
+ {
150
+ $this->transactions = array();
151
+ }
152
+
153
+ /**
154
+ * Add a request to the history
155
+ *
156
+ * @param RequestInterface $request Request to add
157
+ * @param ResponseInterface $response Response of the request
158
+ */
159
+ private function add(
160
+ RequestInterface $request,
161
+ ResponseInterface $response = null
162
+ ) {
163
+ $this->transactions[] = [
164
+ 'request' => $request,
165
+ 'sent_request' => clone $request,
166
+ 'response' => $response
167
+ ];
168
+ if (count($this->transactions) > $this->limit) {
169
+ array_shift($this->transactions);
170
+ }
171
+ }
172
+ }
vendor/guzzlehttp/guzzle/src/Subscriber/HttpError.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Subscriber;
3
+
4
+ use GuzzleHttp\Event\CompleteEvent;
5
+ use GuzzleHttp\Event\RequestEvents;
6
+ use GuzzleHttp\Event\SubscriberInterface;
7
+ use GuzzleHttp\Exception\RequestException;
8
+
9
+ /**
10
+ * Throws exceptions when a 4xx or 5xx response is received
11
+ */
12
+ class HttpError implements SubscriberInterface
13
+ {
14
+ public function getEvents()
15
+ {
16
+ return ['complete' => ['onComplete', RequestEvents::VERIFY_RESPONSE]];
17
+ }
18
+
19
+ /**
20
+ * Throw a RequestException on an HTTP protocol error
21
+ *
22
+ * @param CompleteEvent $event Emitted event
23
+ * @throws RequestException
24
+ */
25
+ public function onComplete(CompleteEvent $event)
26
+ {
27
+ $code = (string) $event->getResponse()->getStatusCode();
28
+ // Throw an exception for an unsuccessful response
29
+ if ($code[0] >= 4) {
30
+ throw RequestException::create(
31
+ $event->getRequest(),
32
+ $event->getResponse()
33
+ );
34
+ }
35
+ }
36
+ }
vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Subscriber;
3
+
4
+ use GuzzleHttp\Event\RequestEvents;
5
+ use GuzzleHttp\Event\SubscriberInterface;
6
+ use GuzzleHttp\Event\BeforeEvent;
7
+ use GuzzleHttp\Exception\RequestException;
8
+ use GuzzleHttp\Message\MessageFactory;
9
+ use GuzzleHttp\Message\ResponseInterface;
10
+ use GuzzleHttp\Stream\StreamInterface;
11
+
12
+ /**
13
+ * Queues mock responses or exceptions and delivers mock responses or
14
+ * exceptions in a fifo order.
15
+ */
16
+ class Mock implements SubscriberInterface, \Countable
17
+ {
18
+ /** @var array Array of mock responses / exceptions */
19
+ private $queue = [];
20
+
21
+ /** @var bool Whether or not to consume an entity body when mocking */
22
+ private $readBodies;
23
+
24
+ /** @var MessageFactory */
25
+ private $factory;
26
+
27
+ /**
28
+ * @param array $items Array of responses or exceptions to queue
29
+ * @param bool $readBodies Set to false to not consume the entity body of
30
+ * a request when a mock is served.
31
+ */
32
+ public function __construct(array $items = [], $readBodies = true)
33
+ {
34
+ $this->factory = new MessageFactory();
35
+ $this->readBodies = $readBodies;
36
+ $this->addMultiple($items);
37
+ }
38
+
39
+ public function getEvents()
40
+ {
41
+ // Fire the event last, after signing
42
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST - 10]];
43
+ }
44
+
45
+ /**
46
+ * @throws \OutOfBoundsException|\Exception
47
+ */
48
+ public function onBefore(BeforeEvent $event)
49
+ {
50
+ if (!$item = array_shift($this->queue)) {
51
+ throw new \OutOfBoundsException('Mock queue is empty');
52
+ } elseif ($item instanceof RequestException) {
53
+ throw $item;
54
+ }
55
+
56
+ // Emulate reading a response body
57
+ $request = $event->getRequest();
58
+ if ($this->readBodies && $request->getBody()) {
59
+ while (!$request->getBody()->eof()) {
60
+ $request->getBody()->read(8096);
61
+ }
62
+ }
63
+
64
+ $saveTo = $event->getRequest()->getConfig()->get('save_to');
65
+
66
+ if (null !== $saveTo) {
67
+ $body = $item->getBody();
68
+
69
+ if (is_resource($saveTo)) {
70
+ fwrite($saveTo, $body);
71
+ } elseif (is_string($saveTo)) {
72
+ file_put_contents($saveTo, $body);
73
+ } elseif ($saveTo instanceof StreamInterface) {
74
+ $saveTo->write($body);
75
+ }
76
+ }
77
+
78
+ $event->intercept($item);
79
+ }
80
+
81
+ public function count()
82
+ {
83
+ return count($this->queue);
84
+ }
85
+
86
+ /**
87
+ * Add a response to the end of the queue
88
+ *
89
+ * @param string|ResponseInterface $response Response or path to response file
90
+ *
91
+ * @return self
92
+ * @throws \InvalidArgumentException if a string or Response is not passed
93
+ */
94
+ public function addResponse($response)
95
+ {
96
+ if (is_string($response)) {
97
+ $response = file_exists($response)
98
+ ? $this->factory->fromMessage(file_get_contents($response))
99
+ : $this->factory->fromMessage($response);
100
+ } elseif (!($response instanceof ResponseInterface)) {
101
+ throw new \InvalidArgumentException('Response must a message '
102
+ . 'string, response object, or path to a file');
103
+ }
104
+
105
+ $this->queue[] = $response;
106
+
107
+ return $this;
108
+ }
109
+
110
+ /**
111
+ * Add an exception to the end of the queue
112
+ *
113
+ * @param RequestException $e Exception to throw when the request is executed
114
+ *
115
+ * @return self
116
+ */
117
+ public function addException(RequestException $e)
118
+ {
119
+ $this->queue[] = $e;
120
+
121
+ return $this;
122
+ }
123
+
124
+ /**
125
+ * Add multiple items to the queue
126
+ *
127
+ * @param array $items Items to add
128
+ */
129
+ public function addMultiple(array $items)
130
+ {
131
+ foreach ($items as $item) {
132
+ if ($item instanceof RequestException) {
133
+ $this->addException($item);
134
+ } else {
135
+ $this->addResponse($item);
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Clear the queue
142
+ */
143
+ public function clearQueue()
144
+ {
145
+ $this->queue = [];
146
+ }
147
+ }
vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Subscriber;
3
+
4
+ use GuzzleHttp\Event\BeforeEvent;
5
+ use GuzzleHttp\Event\RequestEvents;
6
+ use GuzzleHttp\Event\SubscriberInterface;
7
+ use GuzzleHttp\Message\AppliesHeadersInterface;
8
+ use GuzzleHttp\Message\RequestInterface;
9
+ use GuzzleHttp\Mimetypes;
10
+ use GuzzleHttp\Stream\StreamInterface;
11
+
12
+ /**
13
+ * Prepares requests with a body before sending
14
+ *
15
+ * **Request Options**
16
+ *
17
+ * - expect: Set to true to enable the "Expect: 100-Continue" header for a
18
+ * request that send a body. Set to false to disable "Expect: 100-Continue".
19
+ * Set to a number so that the size of the payload must be greater than the
20
+ * number in order to send the Expect header. Setting to a number will send
21
+ * the Expect header for all requests in which the size of the payload cannot
22
+ * be determined or where the body is not rewindable.
23
+ */
24
+ class Prepare implements SubscriberInterface
25
+ {
26
+ public function getEvents()
27
+ {
28
+ return ['before' => ['onBefore', RequestEvents::PREPARE_REQUEST]];
29
+ }
30
+
31
+ public function onBefore(BeforeEvent $event)
32
+ {
33
+ $request = $event->getRequest();
34
+
35
+ // Set the appropriate Content-Type for a request if one is not set and
36
+ // there are form fields
37
+ if (!($body = $request->getBody())) {
38
+ return;
39
+ }
40
+
41
+ $this->addContentLength($request, $body);
42
+
43
+ if ($body instanceof AppliesHeadersInterface) {
44
+ // Synchronize the body with the request headers
45
+ $body->applyRequestHeaders($request);
46
+ } elseif (!$request->hasHeader('Content-Type')) {
47
+ $this->addContentType($request, $body);
48
+ }
49
+
50
+ $this->addExpectHeader($request, $body);
51
+ }
52
+
53
+ private function addContentType(
54
+ RequestInterface $request,
55
+ StreamInterface $body
56
+ ) {
57
+ if (!($uri = $body->getMetadata('uri'))) {
58
+ return;
59
+ }
60
+
61
+ // Guess the content-type based on the stream's "uri" metadata value.
62
+ // The file extension is used to determine the appropriate mime-type.
63
+ if ($contentType = Mimetypes::getInstance()->fromFilename($uri)) {
64
+ $request->setHeader('Content-Type', $contentType);
65
+ }
66
+ }
67
+
68
+ private function addContentLength(
69
+ RequestInterface $request,
70
+ StreamInterface $body
71
+ ) {
72
+ // Set the Content-Length header if it can be determined, and never
73
+ // send a Transfer-Encoding: chunked and Content-Length header in
74
+ // the same request.
75
+ if ($request->hasHeader('Content-Length')) {
76
+ // Remove transfer-encoding if content-length is set.
77
+ $request->removeHeader('Transfer-Encoding');
78
+ return;
79
+ }
80
+
81
+ if ($request->hasHeader('Transfer-Encoding')) {
82
+ return;
83
+ }
84
+
85
+ if (null !== ($size = $body->getSize())) {
86
+ $request->setHeader('Content-Length', $size);
87
+ $request->removeHeader('Transfer-Encoding');
88
+ } elseif ('1.1' == $request->getProtocolVersion()) {
89
+ // Use chunked Transfer-Encoding if there is no determinable
90
+ // content-length header and we're using HTTP/1.1.
91
+ $request->setHeader('Transfer-Encoding', 'chunked');
92
+ $request->removeHeader('Content-Length');
93
+ }
94
+ }
95
+
96
+ private function addExpectHeader(
97
+ RequestInterface $request,
98
+ StreamInterface $body
99
+ ) {
100
+ // Determine if the Expect header should be used
101
+ if ($request->hasHeader('Expect')) {
102
+ return;
103
+ }
104
+
105
+ $expect = $request->getConfig()['expect'];
106
+
107
+ // Return if disabled or if you're not using HTTP/1.1
108
+ if ($expect === false || $request->getProtocolVersion() !== '1.1') {
109
+ return;
110
+ }
111
+
112
+ // The expect header is unconditionally enabled
113
+ if ($expect === true) {
114
+ $request->setHeader('Expect', '100-Continue');
115
+ return;
116
+ }
117
+
118
+ // By default, send the expect header when the payload is > 1mb
119
+ if ($expect === null) {
120
+ $expect = 1048576;
121
+ }
122
+
123
+ // Always add if the body cannot be rewound, the size cannot be
124
+ // determined, or the size is greater than the cutoff threshold
125
+ $size = $body->getSize();
126
+ if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
127
+ $request->setHeader('Expect', '100-Continue');
128
+ }
129
+ }
130
+ }
vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Subscriber;
3
+
4
+ use GuzzleHttp\Event\CompleteEvent;
5
+ use GuzzleHttp\Event\RequestEvents;
6
+ use GuzzleHttp\Event\SubscriberInterface;
7
+ use GuzzleHttp\Exception\BadResponseException;
8
+ use GuzzleHttp\Exception\CouldNotRewindStreamException;
9
+ use GuzzleHttp\Exception\TooManyRedirectsException;
10
+ use GuzzleHttp\Message\RequestInterface;
11
+ use GuzzleHttp\Message\ResponseInterface;
12
+ use GuzzleHttp\Url;
13
+
14
+ /**
15
+ * Subscriber used to implement HTTP redirects.
16
+ *
17
+ * **Request options**
18
+ *
19
+ * - redirect: Associative array containing the 'max', 'strict', and 'referer'
20
+ * keys.
21
+ *
22
+ * - max: Maximum number of redirects allowed per-request
23
+ * - strict: You can use strict redirects by setting this value to ``true``.
24
+ * Strict redirects adhere to strict RFC compliant redirection (e.g.,
25
+ * redirect POST with POST) vs doing what most clients do (e.g., redirect
26
+ * POST request with a GET request).
27
+ * - referer: Set to true to automatically add the "Referer" header when a
28
+ * redirect request is sent.
29
+ * - protocols: Array of allowed protocols. Defaults to 'http' and 'https'.
30
+ * When a redirect attempts to utilize a protocol that is not white listed,
31
+ * an exception is thrown.
32
+ */
33
+ class Redirect implements SubscriberInterface
34
+ {
35
+ public function getEvents()
36
+ {
37
+ return ['complete' => ['onComplete', RequestEvents::REDIRECT_RESPONSE]];
38
+ }
39
+
40
+ /**
41
+ * Rewind the entity body of the request if needed
42
+ *
43
+ * @param RequestInterface $redirectRequest
44
+ * @throws CouldNotRewindStreamException
45
+ */
46
+ public static function rewindEntityBody(RequestInterface $redirectRequest)
47
+ {
48
+ // Rewind the entity body of the request if needed
49
+ if ($body = $redirectRequest->getBody()) {
50
+ // Only rewind the body if some of it has been read already, and
51
+ // throw an exception if the rewind fails
52
+ if ($body->tell() && !$body->seek(0)) {
53
+ throw new CouldNotRewindStreamException(
54
+ 'Unable to rewind the non-seekable request body after redirecting',
55
+ $redirectRequest
56
+ );
57
+ }
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Called when a request receives a redirect response
63
+ *
64
+ * @param CompleteEvent $event Event emitted
65
+ * @throws TooManyRedirectsException
66
+ */
67
+ public function onComplete(CompleteEvent $event)
68
+ {
69
+ $response = $event->getResponse();
70
+
71
+ if (substr($response->getStatusCode(), 0, 1) != '3'
72
+ || !$response->hasHeader('Location')
73
+ ) {
74
+ return;
75
+ }
76
+
77
+ $request = $event->getRequest();
78
+ $config = $request->getConfig();
79
+
80
+ // Increment the redirect and initialize the redirect state.
81
+ if ($redirectCount = $config['redirect_count']) {
82
+ $config['redirect_count'] = ++$redirectCount;
83
+ } else {
84
+ $config['redirect_scheme'] = $request->getScheme();
85
+ $config['redirect_count'] = $redirectCount = 1;
86
+ }
87
+
88
+ $max = $config->getPath('redirect/max') ?: 5;
89
+
90
+ if ($redirectCount > $max) {
91
+ throw new TooManyRedirectsException(
92
+ "Will not follow more than {$redirectCount} redirects",
93
+ $request
94
+ );
95
+ }
96
+
97
+ $this->modifyRedirectRequest($request, $response);
98
+ $event->retry();
99
+ }
100
+
101
+ private function modifyRedirectRequest(
102
+ RequestInterface $request,
103
+ ResponseInterface $response
104
+ ) {
105
+ $config = $request->getConfig();
106
+ $protocols = $config->getPath('redirect/protocols') ?: ['http', 'https'];
107
+
108
+ // Use a GET request if this is an entity enclosing request and we are
109
+ // not forcing RFC compliance, but rather emulating what all browsers
110
+ // would do.
111
+ $statusCode = $response->getStatusCode();
112
+ if ($statusCode == 303 ||
113
+ ($statusCode <= 302 && $request->getBody() && !$config->getPath('redirect/strict'))
114
+ ) {
115
+ $request->setMethod('GET');
116
+ $request->setBody(null);
117
+ }
118
+
119
+ $previousUrl = $request->getUrl();
120
+ $this->setRedirectUrl($request, $response, $protocols);
121
+ $this->rewindEntityBody($request);
122
+
123
+ // Add the Referer header if it is told to do so and only
124
+ // add the header if we are not redirecting from https to http.
125
+ if ($config->getPath('redirect/referer')
126
+ && ($request->getScheme() == 'https' || $request->getScheme() == $config['redirect_scheme'])
127
+ ) {
128
+ $url = Url::fromString($previousUrl);
129
+ $url->setUsername(null);
130
+ $url->setPassword(null);
131
+ $request->setHeader('Referer', (string) $url);
132
+ } else {
133
+ $request->removeHeader('Referer');
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Set the appropriate URL on the request based on the location header
139
+ *
140
+ * @param RequestInterface $request
141
+ * @param ResponseInterface $response
142
+ * @param array $protocols
143
+ */
144
+ private function setRedirectUrl(
145
+ RequestInterface $request,
146
+ ResponseInterface $response,
147
+ array $protocols
148
+ ) {
149
+ $location = $response->getHeader('Location');
150
+ $location = Url::fromString($location);
151
+
152
+ // Combine location with the original URL if it is not absolute.
153
+ if (!$location->isAbsolute()) {
154
+ $originalUrl = Url::fromString($request->getUrl());
155
+ // Remove query string parameters and just take what is present on
156
+ // the redirect Location header
157
+ $originalUrl->getQuery()->clear();
158
+ $location = $originalUrl->combine($location);
159
+ }
160
+
161
+ // Ensure that the redirect URL is allowed based on the protocols.
162
+ if (!in_array($location->getScheme(), $protocols)) {
163
+ throw new BadResponseException(
164
+ sprintf(
165
+ 'Redirect URL, %s, does not use one of the allowed redirect protocols: %s',
166
+ $location,
167
+ implode(', ', $protocols)
168
+ ),
169
+ $request,
170
+ $response
171
+ );
172
+ }
173
+
174
+ $request->setUrl($location);
175
+ }
176
+ }
vendor/guzzlehttp/guzzle/src/ToArrayInterface.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * An object that can be represented as an array
6
+ */
7
+ interface ToArrayInterface
8
+ {
9
+ /**
10
+ * Get the array representation of an object
11
+ *
12
+ * @return array
13
+ */
14
+ public function toArray();
15
+ }
vendor/guzzlehttp/guzzle/src/Transaction.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Message\RequestInterface;
5
+ use GuzzleHttp\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Represents the relationship between a client, request, and response.
9
+ *
10
+ * You can access the request, response, and client using their corresponding
11
+ * public properties.
12
+ */
13
+ class Transaction
14
+ {
15
+ /**
16
+ * HTTP client used to transfer the request.
17
+ *
18
+ * @var ClientInterface
19
+ */
20
+ public $client;
21
+
22
+ /**
23
+ * The request that is being sent.
24
+ *
25
+ * @var RequestInterface
26
+ */
27
+ public $request;
28
+
29
+ /**
30
+ * The response associated with the transaction. A response will not be
31
+ * present when a networking error occurs or an error occurs before sending
32
+ * the request.
33
+ *
34
+ * @var ResponseInterface|null
35
+ */
36
+ public $response;
37
+
38
+ /**
39
+ * Exception associated with the transaction. If this exception is present
40
+ * when processing synchronous or future commands, then it is thrown. When
41
+ * intercepting a failed transaction, you MUST set this value to null in
42
+ * order to prevent the exception from being thrown.
43
+ *
44
+ * @var \Exception
45
+ */
46
+ public $exception;
47
+
48
+ /**
49
+ * Associative array of handler specific transfer statistics and custom
50
+ * key value pair information. When providing similar information, handlers
51
+ * should follow the same key value pair naming conventions as PHP's
52
+ * curl_getinfo() (http://php.net/manual/en/function.curl-getinfo.php).
53
+ *
54
+ * @var array
55
+ */
56
+ public $transferInfo = [];
57
+
58
+ /**
59
+ * The number of transaction retries.
60
+ *
61
+ * @var int
62
+ */
63
+ public $retries = 0;
64
+
65
+ /**
66
+ * The transaction's current state.
67
+ *
68
+ * @var string
69
+ */
70
+ public $state;
71
+
72
+ /**
73
+ * Whether or not this is a future transaction. This value should not be
74
+ * changed after the future is constructed.
75
+ *
76
+ * @var bool
77
+ */
78
+ public $future;
79
+
80
+ /**
81
+ * The number of state transitions that this transaction has been through.
82
+ *
83
+ * @var int
84
+ * @internal This is for internal use only. If you modify this, then you
85
+ * are asking for trouble.
86
+ */
87
+ public $_transitionCount = 0;
88
+
89
+ /**
90
+ * @param ClientInterface $client Client that is used to send the requests
91
+ * @param RequestInterface $request Request to send
92
+ * @param bool $future Whether or not this is a future request.
93
+ */
94
+ public function __construct(
95
+ ClientInterface $client,
96
+ RequestInterface $request,
97
+ $future = false
98
+ ) {
99
+ $this->client = $client;
100
+ $this->request = $request;
101
+ $this->_future = $future;
102
+ }
103
+ }
vendor/guzzlehttp/guzzle/src/UriTemplate.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Expands URI templates. Userland implementation of PECL uri_template.
6
+ *
7
+ * @link http://tools.ietf.org/html/rfc6570
8
+ */
9
+ class UriTemplate
10
+ {
11
+ /** @var string URI template */
12
+ private $template;
13
+
14
+ /** @var array Variables to use in the template expansion */
15
+ private $variables;
16
+
17
+ /** @var array Hash for quick operator lookups */
18
+ private static $operatorHash = array(
19
+ '' => array('prefix' => '', 'joiner' => ',', 'query' => false),
20
+ '+' => array('prefix' => '', 'joiner' => ',', 'query' => false),
21
+ '#' => array('prefix' => '#', 'joiner' => ',', 'query' => false),
22
+ '.' => array('prefix' => '.', 'joiner' => '.', 'query' => false),
23
+ '/' => array('prefix' => '/', 'joiner' => '/', 'query' => false),
24
+ ';' => array('prefix' => ';', 'joiner' => ';', 'query' => true),
25
+ '?' => array('prefix' => '?', 'joiner' => '&', 'query' => true),
26
+ '&' => array('prefix' => '&', 'joiner' => '&', 'query' => true)
27
+ );
28
+
29
+ /** @var array Delimiters */
30
+ private static $delims = array(':', '/', '?', '#', '[', ']', '@', '!', '$',
31
+ '&', '\'', '(', ')', '*', '+', ',', ';', '=');
32
+
33
+ /** @var array Percent encoded delimiters */
34
+ private static $delimsPct = array('%3A', '%2F', '%3F', '%23', '%5B', '%5D',
35
+ '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
36
+ '%3B', '%3D');
37
+
38
+ public function expand($template, array $variables)
39
+ {
40
+ if (false === strpos($template, '{')) {
41
+ return $template;
42
+ }
43
+
44
+ $this->template = $template;
45
+ $this->variables = $variables;
46
+
47
+ return preg_replace_callback(
48
+ '/\{([^\}]+)\}/',
49
+ [$this, 'expandMatch'],
50
+ $this->template
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Parse an expression into parts
56
+ *
57
+ * @param string $expression Expression to parse
58
+ *
59
+ * @return array Returns an associative array of parts
60
+ */
61
+ private function parseExpression($expression)
62
+ {
63
+ $result = array();
64
+
65
+ if (isset(self::$operatorHash[$expression[0]])) {
66
+ $result['operator'] = $expression[0];
67
+ $expression = substr($expression, 1);
68
+ } else {
69
+ $result['operator'] = '';
70
+ }
71
+
72
+ foreach (explode(',', $expression) as $value) {
73
+ $value = trim($value);
74
+ $varspec = array();
75
+ if ($colonPos = strpos($value, ':')) {
76
+ $varspec['value'] = substr($value, 0, $colonPos);
77
+ $varspec['modifier'] = ':';
78
+ $varspec['position'] = (int) substr($value, $colonPos + 1);
79
+ } elseif (substr($value, -1) == '*') {
80
+ $varspec['modifier'] = '*';
81
+ $varspec['value'] = substr($value, 0, -1);
82
+ } else {
83
+ $varspec['value'] = (string) $value;
84
+ $varspec['modifier'] = '';
85
+ }
86
+ $result['values'][] = $varspec;
87
+ }
88
+
89
+ return $result;
90
+ }
91
+
92
+ /**
93
+ * Process an expansion
94
+ *
95
+ * @param array $matches Matches met in the preg_replace_callback
96
+ *
97
+ * @return string Returns the replacement string
98
+ */
99
+ private function expandMatch(array $matches)
100
+ {
101
+ static $rfc1738to3986 = array('+' => '%20', '%7e' => '~');
102
+
103
+ $replacements = array();
104
+ $parsed = self::parseExpression($matches[1]);
105
+ $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
106
+ $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
107
+ $useQuery = self::$operatorHash[$parsed['operator']]['query'];
108
+
109
+ foreach ($parsed['values'] as $value) {
110
+
111
+ if (!isset($this->variables[$value['value']])) {
112
+ continue;
113
+ }
114
+
115
+ $variable = $this->variables[$value['value']];
116
+ $actuallyUseQuery = $useQuery;
117
+ $expanded = '';
118
+
119
+ if (is_array($variable)) {
120
+
121
+ $isAssoc = $this->isAssoc($variable);
122
+ $kvp = array();
123
+ foreach ($variable as $key => $var) {
124
+
125
+ if ($isAssoc) {
126
+ $key = rawurlencode($key);
127
+ $isNestedArray = is_array($var);
128
+ } else {
129
+ $isNestedArray = false;
130
+ }
131
+
132
+ if (!$isNestedArray) {
133
+ $var = rawurlencode($var);
134
+ if ($parsed['operator'] == '+' ||
135
+ $parsed['operator'] == '#'
136
+ ) {
137
+ $var = $this->decodeReserved($var);
138
+ }
139
+ }
140
+
141
+ if ($value['modifier'] == '*') {
142
+ if ($isAssoc) {
143
+ if ($isNestedArray) {
144
+ // Nested arrays must allow for deeply nested
145
+ // structures.
146
+ $var = strtr(
147
+ http_build_query([$key => $var]),
148
+ $rfc1738to3986
149
+ );
150
+ } else {
151
+ $var = $key . '=' . $var;
152
+ }
153
+ } elseif ($key > 0 && $actuallyUseQuery) {
154
+ $var = $value['value'] . '=' . $var;
155
+ }
156
+ }
157
+
158
+ $kvp[$key] = $var;
159
+ }
160
+
161
+ if (empty($variable)) {
162
+ $actuallyUseQuery = false;
163
+ } elseif ($value['modifier'] == '*') {
164
+ $expanded = implode($joiner, $kvp);
165
+ if ($isAssoc) {
166
+ // Don't prepend the value name when using the explode
167
+ // modifier with an associative array.
168
+ $actuallyUseQuery = false;
169
+ }
170
+ } else {
171
+ if ($isAssoc) {
172
+ // When an associative array is encountered and the
173
+ // explode modifier is not set, then the result must be
174
+ // a comma separated list of keys followed by their
175
+ // respective values.
176
+ foreach ($kvp as $k => &$v) {
177
+ $v = $k . ',' . $v;
178
+ }
179
+ }
180
+ $expanded = implode(',', $kvp);
181
+ }
182
+
183
+ } else {
184
+ if ($value['modifier'] == ':') {
185
+ $variable = substr($variable, 0, $value['position']);
186
+ }
187
+ $expanded = rawurlencode($variable);
188
+ if ($parsed['operator'] == '+' || $parsed['operator'] == '#') {
189
+ $expanded = $this->decodeReserved($expanded);
190
+ }
191
+ }
192
+
193
+ if ($actuallyUseQuery) {
194
+ if (!$expanded && $joiner != '&') {
195
+ $expanded = $value['value'];
196
+ } else {
197
+ $expanded = $value['value'] . '=' . $expanded;
198
+ }
199
+ }
200
+
201
+ $replacements[] = $expanded;
202
+ }
203
+
204
+ $ret = implode($joiner, $replacements);
205
+ if ($ret && $prefix) {
206
+ return $prefix . $ret;
207
+ }
208
+
209
+ return $ret;
210
+ }
211
+
212
+ /**
213
+ * Determines if an array is associative.
214
+ *
215
+ * This makes the assumption that input arrays are sequences or hashes.
216
+ * This assumption is a tradeoff for accuracy in favor of speed, but it
217
+ * should work in almost every case where input is supplied for a URI
218
+ * template.
219
+ *
220
+ * @param array $array Array to check
221
+ *
222
+ * @return bool
223
+ */
224
+ private function isAssoc(array $array)
225
+ {
226
+ return $array && array_keys($array)[0] !== 0;
227
+ }
228
+
229
+ /**
230
+ * Removes percent encoding on reserved characters (used with + and #
231
+ * modifiers).
232
+ *
233
+ * @param string $string String to fix
234
+ *
235
+ * @return string
236
+ */
237
+ private function decodeReserved($string)
238
+ {
239
+ return str_replace(self::$delimsPct, self::$delims, $string);
240
+ }
241
+ }
vendor/guzzlehttp/guzzle/src/Url.php ADDED
@@ -0,0 +1,595 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Ring\Core;
5
+
6
+ /**
7
+ * Parses and generates URLs based on URL parts
8
+ */
9
+ class Url
10
+ {
11
+ private $scheme;
12
+ private $host;
13
+ private $port;
14
+ private $username;
15
+ private $password;
16
+ private $path = '';
17
+ private $fragment;
18
+ private static $defaultPorts = ['http' => 80, 'https' => 443, 'ftp' => 21];
19
+ private static $pathPattern = '/[^a-zA-Z0-9\-\._~!\$&\'\(\)\*\+,;=%:@\/]+|%(?![A-Fa-f0-9]{2})/';
20
+ private static $queryPattern = '/[^a-zA-Z0-9\-\._~!\$\'\(\)\*\+,;%:@\/\?=&]+|%(?![A-Fa-f0-9]{2})/';
21
+ /** @var Query|string Query part of the URL */
22
+ private $query;
23
+
24
+ /**
25
+ * Factory method to create a new URL from a URL string
26
+ *
27
+ * @param string $url Full URL used to create a Url object
28
+ *
29
+ * @return Url
30
+ * @throws \InvalidArgumentException
31
+ */
32
+ public static function fromString($url)
33
+ {
34
+ static $defaults = ['scheme' => null, 'host' => null,
35
+ 'path' => null, 'port' => null, 'query' => null,
36
+ 'user' => null, 'pass' => null, 'fragment' => null];
37
+
38
+ if (false === ($parts = parse_url($url))) {
39
+ throw new \InvalidArgumentException('Unable to parse malformed '
40
+ . 'url: ' . $url);
41
+ }
42
+
43
+ $parts += $defaults;
44
+
45
+ // Convert the query string into a Query object
46
+ if ($parts['query'] || 0 !== strlen($parts['query'])) {
47
+ $parts['query'] = Query::fromString($parts['query']);
48
+ }
49
+
50
+ return new static($parts['scheme'], $parts['host'], $parts['user'],
51
+ $parts['pass'], $parts['port'], $parts['path'], $parts['query'],
52
+ $parts['fragment']);
53
+ }
54
+
55
+ /**
56
+ * Build a URL from parse_url parts. The generated URL will be a relative
57
+ * URL if a scheme or host are not provided.
58
+ *
59
+ * @param array $parts Array of parse_url parts
60
+ *
61
+ * @return string
62
+ */
63
+ public static function buildUrl(array $parts)
64
+ {
65
+ $url = $scheme = '';
66
+
67
+ if (!empty($parts['scheme'])) {
68
+ $scheme = $parts['scheme'];
69
+ $url .= $scheme . ':';
70
+ }
71
+
72
+ if (!empty($parts['host'])) {
73
+ $url .= '//';
74
+ if (isset($parts['user'])) {
75
+ $url .= $parts['user'];
76
+ if (isset($parts['pass'])) {
77
+ $url .= ':' . $parts['pass'];
78
+ }
79
+ $url .= '@';
80
+ }
81
+
82
+ $url .= $parts['host'];
83
+
84
+ // Only include the port if it is not the default port of the scheme
85
+ if (isset($parts['port']) &&
86
+ (!isset(self::$defaultPorts[$scheme]) ||
87
+ $parts['port'] != self::$defaultPorts[$scheme])
88
+ ) {
89
+ $url .= ':' . $parts['port'];
90
+ }
91
+ }
92
+
93
+ // Add the path component if present
94
+ if (isset($parts['path']) && strlen($parts['path'])) {
95
+ // Always ensure that the path begins with '/' if set and something
96
+ // is before the path
97
+ if (!empty($parts['host']) && $parts['path'][0] != '/') {
98
+ $url .= '/';
99
+ }
100
+ $url .= $parts['path'];
101
+ }
102
+
103
+ // Add the query string if present
104
+ if (isset($parts['query'])) {
105
+ $queryStr = (string) $parts['query'];
106
+ if ($queryStr || $queryStr === '0') {
107
+ $url .= '?' . $queryStr;
108
+ }
109
+ }
110
+
111
+ // Ensure that # is only added to the url if fragment contains anything.
112
+ if (isset($parts['fragment'])) {
113
+ $url .= '#' . $parts['fragment'];
114
+ }
115
+
116
+ return $url;
117
+ }
118
+
119
+ /**
120
+ * Create a new URL from URL parts
121
+ *
122
+ * @param string $scheme Scheme of the URL
123
+ * @param string $host Host of the URL
124
+ * @param string $username Username of the URL
125
+ * @param string $password Password of the URL
126
+ * @param int $port Port of the URL
127
+ * @param string $path Path of the URL
128
+ * @param Query|array|string $query Query string of the URL
129
+ * @param string $fragment Fragment of the URL
130
+ */
131
+ public function __construct(
132
+ $scheme,
133
+ $host,
134
+ $username = null,
135
+ $password = null,
136
+ $port = null,
137
+ $path = null,
138
+ $query = null,
139
+ $fragment = null
140
+ ) {
141
+ $this->scheme = strtolower($scheme);
142
+ $this->host = $host;
143
+ $this->port = $port;
144
+ $this->username = $username;
145
+ $this->password = $password;
146
+ $this->fragment = $fragment;
147
+
148
+ if ($query) {
149
+ $this->setQuery($query);
150
+ }
151
+
152
+ $this->setPath($path);
153
+ }
154
+
155
+ /**
156
+ * Clone the URL
157
+ */
158
+ public function __clone()
159
+ {
160
+ if ($this->query instanceof Query) {
161
+ $this->query = clone $this->query;
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Returns the URL as a URL string
167
+ *
168
+ * @return string
169
+ */
170
+ public function __toString()
171
+ {
172
+ return static::buildUrl($this->getParts());
173
+ }
174
+
175
+ /**
176
+ * Get the parts of the URL as an array
177
+ *
178
+ * @return array
179
+ */
180
+ public function getParts()
181
+ {
182
+ return array(
183
+ 'scheme' => $this->scheme,
184
+ 'user' => $this->username,
185
+ 'pass' => $this->password,
186
+ 'host' => $this->host,
187
+ 'port' => $this->port,
188
+ 'path' => $this->path,
189
+ 'query' => $this->query,
190
+ 'fragment' => $this->fragment,
191
+ );
192
+ }
193
+
194
+ /**
195
+ * Set the host of the request.
196
+ *
197
+ * @param string $host Host to set (e.g. www.yahoo.com, yahoo.com)
198
+ *
199
+ * @return Url
200
+ */
201
+ public function setHost($host)
202
+ {
203
+ if (strpos($host, ':') === false) {
204
+ $this->host = $host;
205
+ } else {
206
+ list($host, $port) = explode(':', $host);
207
+ $this->host = $host;
208
+ $this->setPort($port);
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Get the host part of the URL
214
+ *
215
+ * @return string
216
+ */
217
+ public function getHost()
218
+ {
219
+ return $this->host;
220
+ }
221
+
222
+ /**
223
+ * Set the scheme part of the URL (http, https, ftp, etc.)
224
+ *
225
+ * @param string $scheme Scheme to set
226
+ */
227
+ public function setScheme($scheme)
228
+ {
229
+ // Remove the default port if one is specified
230
+ if ($this->port
231
+ && isset(self::$defaultPorts[$this->scheme])
232
+ && self::$defaultPorts[$this->scheme] == $this->port
233
+ ) {
234
+ $this->port = null;
235
+ }
236
+
237
+ $this->scheme = strtolower($scheme);
238
+ }
239
+
240
+ /**
241
+ * Get the scheme part of the URL
242
+ *
243
+ * @return string
244
+ */
245
+ public function getScheme()
246
+ {
247
+ return $this->scheme;
248
+ }
249
+
250
+ /**
251
+ * Set the port part of the URL
252
+ *
253
+ * @param int $port Port to set
254
+ */
255
+ public function setPort($port)
256
+ {
257
+ $this->port = $port;
258
+ }
259
+
260
+ /**
261
+ * Get the port part of the URl.
262
+ *
263
+ * If no port was set, this method will return the default port for the
264
+ * scheme of the URI.
265
+ *
266
+ * @return int|null
267
+ */
268
+ public function getPort()
269
+ {
270
+ if ($this->port) {
271
+ return $this->port;
272
+ } elseif (isset(self::$defaultPorts[$this->scheme])) {
273
+ return self::$defaultPorts[$this->scheme];
274
+ }
275
+
276
+ return null;
277
+ }
278
+
279
+ /**
280
+ * Set the path part of the URL.
281
+ *
282
+ * The provided URL is URL encoded as necessary.
283
+ *
284
+ * @param string $path Path string to set
285
+ */
286
+ public function setPath($path)
287
+ {
288
+ $this->path = self::encodePath($path);
289
+ }
290
+
291
+ /**
292
+ * Removes dot segments from a URL
293
+ * @link http://tools.ietf.org/html/rfc3986#section-5.2.4
294
+ */
295
+ public function removeDotSegments()
296
+ {
297
+ static $noopPaths = ['' => true, '/' => true, '*' => true];
298
+ static $ignoreSegments = ['.' => true, '..' => true];
299
+
300
+ if (isset($noopPaths[$this->path])) {
301
+ return;
302
+ }
303
+
304
+ $results = [];
305
+ $segments = $this->getPathSegments();
306
+ foreach ($segments as $segment) {
307
+ if ($segment == '..') {
308
+ array_pop($results);
309
+ } elseif (!isset($ignoreSegments[$segment])) {
310
+ $results[] = $segment;
311
+ }
312
+ }
313
+
314
+ $newPath = implode('/', $results);
315
+
316
+ // Add the leading slash if necessary
317
+ if (substr($this->path, 0, 1) === '/' &&
318
+ substr($newPath, 0, 1) !== '/'
319
+ ) {
320
+ $newPath = '/' . $newPath;
321
+ }
322
+
323
+ // Add the trailing slash if necessary
324
+ if ($newPath != '/' && isset($ignoreSegments[end($segments)])) {
325
+ $newPath .= '/';
326
+ }
327
+
328
+ $this->path = $newPath;
329
+ }
330
+
331
+ /**
332
+ * Add a relative path to the currently set path.
333
+ *
334
+ * @param string $relativePath Relative path to add
335
+ */
336
+ public function addPath($relativePath)
337
+ {
338
+ if ($relativePath != '/' &&
339
+ is_string($relativePath) &&
340
+ strlen($relativePath) > 0
341
+ ) {
342
+ // Add a leading slash if needed
343
+ if ($relativePath[0] !== '/' &&
344
+ substr($this->path, -1, 1) !== '/'
345
+ ) {
346
+ $relativePath = '/' . $relativePath;
347
+ }
348
+
349
+ $this->setPath($this->path . $relativePath);
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Get the path part of the URL
355
+ *
356
+ * @return string
357
+ */
358
+ public function getPath()
359
+ {
360
+ return $this->path;
361
+ }
362
+
363
+ /**
364
+ * Get the path segments of the URL as an array
365
+ *
366
+ * @return array
367
+ */
368
+ public function getPathSegments()
369
+ {
370
+ return explode('/', $this->path);
371
+ }
372
+
373
+ /**
374
+ * Set the password part of the URL
375
+ *
376
+ * @param string $password Password to set
377
+ */
378
+ public function setPassword($password)
379
+ {
380
+ $this->password = $password;
381
+ }
382
+
383
+ /**
384
+ * Get the password part of the URL
385
+ *
386
+ * @return null|string
387
+ */
388
+ public function getPassword()
389
+ {
390
+ return $this->password;
391
+ }
392
+
393
+ /**
394
+ * Set the username part of the URL
395
+ *
396
+ * @param string $username Username to set
397
+ */
398
+ public function setUsername($username)
399
+ {
400
+ $this->username = $username;
401
+ }
402
+
403
+ /**
404
+ * Get the username part of the URl
405
+ *
406
+ * @return null|string
407
+ */
408
+ public function getUsername()
409
+ {
410
+ return $this->username;
411
+ }
412
+
413
+ /**
414
+ * Get the query part of the URL as a Query object
415
+ *
416
+ * @return Query
417
+ */
418
+ public function getQuery()
419
+ {
420
+ // Convert the query string to a query object if not already done.
421
+ if (!$this->query instanceof Query) {
422
+ $this->query = $this->query === null
423
+ ? new Query()
424
+ : Query::fromString($this->query);
425
+ }
426
+
427
+ return $this->query;
428
+ }
429
+
430
+ /**
431
+ * Set the query part of the URL.
432
+ *
433
+ * You may provide a query string as a string and pass $rawString as true
434
+ * to provide a query string that is not parsed until a call to getQuery()
435
+ * is made. Setting a raw query string will still encode invalid characters
436
+ * in a query string.
437
+ *
438
+ * @param Query|string|array $query Query string value to set. Can
439
+ * be a string that will be parsed into a Query object, an array
440
+ * of key value pairs, or a Query object.
441
+ * @param bool $rawString Set to true when providing a raw query string.
442
+ *
443
+ * @throws \InvalidArgumentException
444
+ */
445
+ public function setQuery($query, $rawString = false)
446
+ {
447
+ if ($query instanceof Query) {
448
+ $this->query = $query;
449
+ } elseif (is_string($query)) {
450
+ if (!$rawString) {
451
+ $this->query = Query::fromString($query);
452
+ } else {
453
+ // Ensure the query does not have illegal characters.
454
+ $this->query = preg_replace_callback(
455
+ self::$queryPattern,
456
+ [__CLASS__, 'encodeMatch'],
457
+ $query
458
+ );
459
+ }
460
+
461
+ } elseif (is_array($query)) {
462
+ $this->query = new Query($query);
463
+ } else {
464
+ throw new \InvalidArgumentException('Query must be a Query, '
465
+ . 'array, or string. Got ' . Core::describeType($query));
466
+ }
467
+ }
468
+
469
+ /**
470
+ * Get the fragment part of the URL
471
+ *
472
+ * @return null|string
473
+ */
474
+ public function getFragment()
475
+ {
476
+ return $this->fragment;
477
+ }
478
+
479
+ /**
480
+ * Set the fragment part of the URL
481
+ *
482
+ * @param string $fragment Fragment to set
483
+ */
484
+ public function setFragment($fragment)
485
+ {
486
+ $this->fragment = $fragment;
487
+ }
488
+
489
+ /**
490
+ * Check if this is an absolute URL
491
+ *
492
+ * @return bool
493
+ */
494
+ public function isAbsolute()
495
+ {
496
+ return $this->scheme && $this->host;
497
+ }
498
+
499
+ /**
500
+ * Combine the URL with another URL and return a new URL instance.
501
+ *
502
+ * Follows the rules specific in RFC 3986 section 5.4.
503
+ *
504
+ * @param string $url Relative URL to combine with
505
+ *
506
+ * @return Url
507
+ * @throws \InvalidArgumentException
508
+ * @link http://tools.ietf.org/html/rfc3986#section-5.4
509
+ */
510
+ public function combine($url)
511
+ {
512
+ $url = static::fromString($url);
513
+
514
+ // Use the more absolute URL as the base URL
515
+ if (!$this->isAbsolute() && $url->isAbsolute()) {
516
+ $url = $url->combine($this);
517
+ }
518
+
519
+ $parts = $url->getParts();
520
+
521
+ // Passing a URL with a scheme overrides everything
522
+ if ($parts['scheme']) {
523
+ return clone $url;
524
+ }
525
+
526
+ // Setting a host overrides the entire rest of the URL
527
+ if ($parts['host']) {
528
+ return new static(
529
+ $this->scheme,
530
+ $parts['host'],
531
+ $parts['user'],
532
+ $parts['pass'],
533
+ $parts['port'],
534
+ $parts['path'],
535
+ $parts['query'] instanceof Query
536
+ ? clone $parts['query']
537
+ : $parts['query'],
538
+ $parts['fragment']
539
+ );
540
+ }
541
+
542
+ if (!$parts['path'] && $parts['path'] !== '0') {
543
+ // The relative URL has no path, so check if it is just a query
544
+ $path = $this->path ?: '';
545
+ $query = $parts['query'] ?: $this->query;
546
+ } else {
547
+ $query = $parts['query'];
548
+ if ($parts['path'][0] == '/' || !$this->path) {
549
+ // Overwrite the existing path if the rel path starts with "/"
550
+ $path = $parts['path'];
551
+ } else {
552
+ // If the relative URL does not have a path or the base URL
553
+ // path does not end in a "/" then overwrite the existing path
554
+ // up to the last "/"
555
+ $path = substr($this->path, 0, strrpos($this->path, '/') + 1) . $parts['path'];
556
+ }
557
+ }
558
+
559
+ $result = new self(
560
+ $this->scheme,
561
+ $this->host,
562
+ $this->username,
563
+ $this->password,
564
+ $this->port,
565
+ $path,
566
+ $query instanceof Query ? clone $query : $query,
567
+ $parts['fragment']
568
+ );
569
+
570
+ if ($path) {
571
+ $result->removeDotSegments();
572
+ }
573
+
574
+ return $result;
575
+ }
576
+
577
+ /**
578
+ * Encodes the path part of a URL without double-encoding percent-encoded
579
+ * key value pairs.
580
+ *
581
+ * @param string $path Path to encode
582
+ *
583
+ * @return string
584
+ */
585
+ public static function encodePath($path)
586
+ {
587
+ static $cb = [__CLASS__, 'encodeMatch'];
588
+ return preg_replace_callback(self::$pathPattern, $cb, $path);
589
+ }
590
+
591
+ private static function encodeMatch(array $match)
592
+ {
593
+ return rawurlencode($match[0]);
594
+ }
595
+ }
vendor/guzzlehttp/guzzle/src/Utils.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Ring\Client\CurlHandler;
5
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
6
+ use GuzzleHttp\Ring\Client\StreamHandler;
7
+ use GuzzleHttp\Ring\Client\Middleware;
8
+
9
+ /**
10
+ * Utility methods used throughout Guzzle.
11
+ */
12
+ final class Utils
13
+ {
14
+ /**
15
+ * Gets a value from an array using a path syntax to retrieve nested data.
16
+ *
17
+ * This method does not allow for keys that contain "/". You must traverse
18
+ * the array manually or using something more advanced like JMESPath to
19
+ * work with keys that contain "/".
20
+ *
21
+ * // Get the bar key of a set of nested arrays.
22
+ * // This is equivalent to $collection['foo']['baz']['bar'] but won't
23
+ * // throw warnings for missing keys.
24
+ * GuzzleHttp\get_path($data, 'foo/baz/bar');
25
+ *
26
+ * @param array $data Data to retrieve values from
27
+ * @param string $path Path to traverse and retrieve a value from
28
+ *
29
+ * @return mixed|null
30
+ */
31
+ public static function getPath($data, $path)
32
+ {
33
+ $path = explode('/', $path);
34
+
35
+ while (null !== ($part = array_shift($path))) {
36
+ if (!is_array($data) || !isset($data[$part])) {
37
+ return null;
38
+ }
39
+ $data = $data[$part];
40
+ }
41
+
42
+ return $data;
43
+ }
44
+
45
+ /**
46
+ * Set a value in a nested array key. Keys will be created as needed to set
47
+ * the value.
48
+ *
49
+ * This function does not support keys that contain "/" or "[]" characters
50
+ * because these are special tokens used when traversing the data structure.
51
+ * A value may be prepended to an existing array by using "[]" as the final
52
+ * key of a path.
53
+ *
54
+ * GuzzleHttp\get_path($data, 'foo/baz'); // null
55
+ * GuzzleHttp\set_path($data, 'foo/baz/[]', 'a');
56
+ * GuzzleHttp\set_path($data, 'foo/baz/[]', 'b');
57
+ * GuzzleHttp\get_path($data, 'foo/baz');
58
+ * // Returns ['a', 'b']
59
+ *
60
+ * @param array $data Data to modify by reference
61
+ * @param string $path Path to set
62
+ * @param mixed $value Value to set at the key
63
+ *
64
+ * @throws \RuntimeException when trying to setPath using a nested path
65
+ * that travels through a scalar value.
66
+ */
67
+ public static function setPath(&$data, $path, $value)
68
+ {
69
+ $queue = explode('/', $path);
70
+ // Optimization for simple sets.
71
+ if (count($queue) === 1) {
72
+ $data[$path] = $value;
73
+ return;
74
+ }
75
+
76
+ $current =& $data;
77
+ while (null !== ($key = array_shift($queue))) {
78
+ if (!is_array($current)) {
79
+ throw new \RuntimeException("Trying to setPath {$path}, but "
80
+ . "{$key} is set and is not an array");
81
+ } elseif (!$queue) {
82
+ if ($key == '[]') {
83
+ $current[] = $value;
84
+ } else {
85
+ $current[$key] = $value;
86
+ }
87
+ } elseif (isset($current[$key])) {
88
+ $current =& $current[$key];
89
+ } else {
90
+ $current[$key] = [];
91
+ $current =& $current[$key];
92
+ }
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Expands a URI template
98
+ *
99
+ * @param string $template URI template
100
+ * @param array $variables Template variables
101
+ *
102
+ * @return string
103
+ */
104
+ public static function uriTemplate($template, array $variables)
105
+ {
106
+ if (function_exists('\\uri_template')) {
107
+ return \uri_template($template, $variables);
108
+ }
109
+
110
+ static $uriTemplate;
111
+ if (!$uriTemplate) {
112
+ $uriTemplate = new UriTemplate();
113
+ }
114
+
115
+ return $uriTemplate->expand($template, $variables);
116
+ }
117
+
118
+ /**
119
+ * Wrapper for JSON decode that implements error detection with helpful
120
+ * error messages.
121
+ *
122
+ * @param string $json JSON data to parse
123
+ * @param bool $assoc When true, returned objects will be converted
124
+ * into associative arrays.
125
+ * @param int $depth User specified recursion depth.
126
+ * @param int $options Bitmask of JSON decode options.
127
+ *
128
+ * @return mixed
129
+ * @throws \InvalidArgumentException if the JSON cannot be parsed.
130
+ * @link http://www.php.net/manual/en/function.json-decode.php
131
+ */
132
+ public static function jsonDecode($json, $assoc = false, $depth = 512, $options = 0)
133
+ {
134
+ if ($json === '' || $json === null) {
135
+ return null;
136
+ }
137
+
138
+ static $jsonErrors = [
139
+ JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH - Maximum stack depth exceeded',
140
+ JSON_ERROR_STATE_MISMATCH => 'JSON_ERROR_STATE_MISMATCH - Underflow or the modes mismatch',
141
+ JSON_ERROR_CTRL_CHAR => 'JSON_ERROR_CTRL_CHAR - Unexpected control character found',
142
+ JSON_ERROR_SYNTAX => 'JSON_ERROR_SYNTAX - Syntax error, malformed JSON',
143
+ JSON_ERROR_UTF8 => 'JSON_ERROR_UTF8 - Malformed UTF-8 characters, possibly incorrectly encoded'
144
+ ];
145
+
146
+ $data = \json_decode($json, $assoc, $depth, $options);
147
+
148
+ if (JSON_ERROR_NONE !== json_last_error()) {
149
+ $last = json_last_error();
150
+ throw new \InvalidArgumentException(
151
+ 'Unable to parse JSON data: '
152
+ . (isset($jsonErrors[$last])
153
+ ? $jsonErrors[$last]
154
+ : 'Unknown error')
155
+ );
156
+ }
157
+
158
+ return $data;
159
+ }
160
+
161
+ /**
162
+ * Get the default User-Agent string to use with Guzzle
163
+ *
164
+ * @return string
165
+ */
166
+ public static function getDefaultUserAgent()
167
+ {
168
+ static $defaultAgent = '';
169
+ if (!$defaultAgent) {
170
+ $defaultAgent = 'Guzzle/' . ClientInterface::VERSION;
171
+ if (extension_loaded('curl')) {
172
+ $defaultAgent .= ' curl/' . curl_version()['version'];
173
+ }
174
+ $defaultAgent .= ' PHP/' . PHP_VERSION;
175
+ }
176
+
177
+ return $defaultAgent;
178
+ }
179
+
180
+ /**
181
+ * Create a default handler to use based on the environment
182
+ *
183
+ * @throws \RuntimeException if no viable Handler is available.
184
+ */
185
+ public static function getDefaultHandler()
186
+ {
187
+ $default = $future = null;
188
+
189
+ if (extension_loaded('curl')) {
190
+ $config = [
191
+ 'select_timeout' => getenv('GUZZLE_CURL_SELECT_TIMEOUT') ?: 1
192
+ ];
193
+ if ($maxHandles = getenv('GUZZLE_CURL_MAX_HANDLES')) {
194
+ $config['max_handles'] = $maxHandles;
195
+ }
196
+ if (function_exists('curl_reset')) {
197
+ $default = new CurlHandler();
198
+ $future = new CurlMultiHandler($config);
199
+ } else {
200
+ $default = new CurlMultiHandler($config);
201
+ }
202
+ }
203
+
204
+ if (ini_get('allow_url_fopen')) {
205
+ $default = !$default
206
+ ? new StreamHandler()
207
+ : Middleware::wrapStreaming($default, new StreamHandler());
208
+ } elseif (!$default) {
209
+ throw new \RuntimeException('Guzzle requires cURL, the '
210
+ . 'allow_url_fopen ini setting, or a custom HTTP handler.');
211
+ }
212
+
213
+ return $future ? Middleware::wrapFuture($default, $future) : $default;
214
+ }
215
+ }
vendor/guzzlehttp/ringphp/.travis.yml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+
3
+ cache:
4
+ directories:
5
+ - $HOME/.composer/cache/files
6
+
7
+ php:
8
+ - 5.4
9
+ - 5.5
10
+ - 5.6
11
+ - 7.0
12
+ - 7.1
13
+ - 7.2
14
+ - hhvm
15
+ - nightly
16
+
17
+ env:
18
+ global:
19
+ - TEST_COMMAND="composer test"
20
+
21
+ matrix:
22
+ allow_failures:
23
+ - php: hhvm
24
+ - php: nightly
25
+ fast_finish: true
26
+ include:
27
+ - php: 5.4
28
+ env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest"
29
+
30
+ before_install:
31
+ - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
32
+
33
+ install:
34
+ # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
35
+ - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
36
+ - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
37
+
38
+ before_script:
39
+ - ~/.nvm/nvm.sh install v0.6.14
40
+ - ~/.nvm/nvm.sh run v0.6.14
41
+
42
+ script:
43
+ - $TEST_COMMAND
vendor/guzzlehttp/ringphp/CHANGELOG.md ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+
4
+ All notable changes to this project will be documented in this file.
5
+
6
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
7
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
8
+
9
+
10
+ ## [Unreleased]
11
+
12
+
13
+ ## [1.1.1] - 2018-07-31
14
+
15
+ ### Fixed
16
+
17
+ - `continue` keyword usage on PHP 7.3
18
+
19
+
20
+ ## [1.1.0] - 2015-05-19
21
+
22
+ ### Added
23
+
24
+ - Added `CURL_HTTP_VERSION_2_0`
25
+
26
+ ### Changed
27
+
28
+ - The PHP stream wrapper handler now sets `allow_self_signed` to `false` to
29
+ match the cURL handler when `verify` is set to `true` or a certificate file.
30
+ - Ensuring that a directory exists before using the `save_to` option.
31
+ - Response protocol version is now correctly extracted from a response.
32
+
33
+ ### Fixed
34
+
35
+ - Fixed a bug in which the result of `CurlFactory::retryFailedRewind` did not
36
+ return an array.
37
+
38
+
39
+ ## [1.0.7] - 2015-03-29
40
+
41
+ ### Fixed
42
+
43
+ - PHP 7 fixes.
44
+
45
+
46
+ ## [1.0.6] - 2015-02-26
47
+
48
+ ### Changed
49
+
50
+ - The multi handle of the CurlMultiHandler is now created lazily.
51
+
52
+ ### Fixed
53
+
54
+ - Bug fix: futures now extend from React's PromiseInterface to ensure that they
55
+ are properly forwarded down the promise chain.
56
+
57
+
58
+ ## [1.0.5] - 2014-12-10
59
+
60
+ ### Added
61
+
62
+ - Adding more error information to PHP stream wrapper exceptions.
63
+ - Added digest auth integration test support to test server.
64
+
65
+
66
+ ## [1.0.4] - 2014-12-01
67
+
68
+ ### Added
69
+
70
+ - Added support for older versions of cURL that do not have CURLOPT_TIMEOUT_MS.
71
+ - Added a fix to the StreamHandler to return a `FutureArrayInterface` when an
72
+
73
+ ### Changed
74
+
75
+ - Setting debug to `false` does not enable debug output. error occurs.
76
+
77
+
78
+ ## [1.0.3] - 2014-11-03
79
+
80
+ ### Fixed
81
+
82
+ - Setting the `header` stream option as a string to be compatible with GAE.
83
+ - Header parsing now ensures that header order is maintained in the parsed
84
+ message.
85
+
86
+
87
+ ## [1.0.2] - 2014-10-28
88
+
89
+ ### Fixed
90
+
91
+ - Now correctly honoring a `version` option is supplied in a request.
92
+ See https://github.com/guzzle/RingPHP/pull/8
93
+
94
+
95
+ ## [1.0.1] - 2014-10-26
96
+
97
+ ### Fixed
98
+
99
+ - Fixed a header parsing issue with the `CurlHandler` and `CurlMultiHandler`
100
+ that caused cURL requests with multiple responses to merge repsonses together
101
+ (e.g., requests with digest authentication).
102
+
103
+
104
+ ## 1.0.0 - 2014-10-12
105
+
106
+ - Initial release
107
+
108
+
109
+ [Unreleased]: https://github.com/guzzle/RingPHP/compare/1.1.1...HEAD
110
+ [1.1.1]: https://github.com/guzzle/RingPHP/compare/1.1.0...1.1.1
111
+ [1.1.0]: https://github.com/guzzle/RingPHP/compare/1.0.7...1.1.0
112
+ [1.0.7]: https://github.com/guzzle/RingPHP/compare/1.0.6...1.0.7
113
+ [1.0.6]: https://github.com/guzzle/RingPHP/compare/1.0.5...1.0.6
114
+ [1.0.5]: https://github.com/guzzle/RingPHP/compare/1.0.4...1.0.5
115
+ [1.0.4]: https://github.com/guzzle/RingPHP/compare/1.0.3...1.0.4
116
+ [1.0.3]: https://github.com/guzzle/RingPHP/compare/1.0.2...1.0.3
117
+ [1.0.2]: https://github.com/guzzle/RingPHP/compare/1.0.1...1.0.2
118
+ [1.0.1]: https://github.com/guzzle/RingPHP/compare/1.0.0...1.0.1
vendor/guzzlehttp/ringphp/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/ringphp/Makefile ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ all: clean coverage docs
2
+
3
+ docs:
4
+ cd docs && make html
5
+
6
+ view-docs:
7
+ open docs/_build/html/index.html
8
+
9
+ start-server: stop-server
10
+ node tests/Client/server.js &> /dev/null &
11
+
12
+ stop-server:
13
+ @PID=$(shell ps axo pid,command \
14
+ | grep 'tests/Client/server.js' \
15
+ | grep -v grep \
16
+ | cut -f 1 -d " "\
17
+ ) && [ -n "$$PID" ] && kill $$PID || true
18
+
19
+ test: start-server
20
+ vendor/bin/phpunit $(TEST)
21
+ $(MAKE) stop-server
22
+
23
+ coverage: start-server
24
+ vendor/bin/phpunit --coverage-html=build/artifacts/coverage $(TEST)
25
+ $(MAKE) stop-server
26
+
27
+ view-coverage:
28
+ open build/artifacts/coverage/index.html
29
+
30
+ clean:
31
+ rm -rf build/artifacts/*
32
+ cd docs && make clean
33
+
34
+ tag:
35
+ $(if $(TAG),,$(error TAG is not defined. Pass via "make tag TAG=4.2.1"))
36
+ @echo Tagging $(TAG)
37
+ chag update -m '$(TAG) ()'
38
+ git add -A
39
+ git commit -m '$(TAG) release'
40
+ chag tag
41
+
42
+ perf: start-server
43
+ php tests/perf.php
44
+ $(MAKE) stop-server
45
+
46
+ .PHONY: docs
vendor/guzzlehttp/ringphp/README.rst ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =======
2
+ RingPHP
3
+ =======
4
+
5
+ Provides a simple API and specification that abstracts away the details of HTTP
6
+ into a single PHP function. RingPHP be used to power HTTP clients and servers
7
+ through a PHP function that accepts a request hash and returns a response hash
8
+ that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
9
+ allowing RingPHP to support both synchronous and asynchronous workflows.
10
+
11
+ By abstracting the implementation details of different HTTP clients and
12
+ servers, RingPHP allows you to utilize pluggable HTTP clients and servers
13
+ without tying your application to a specific implementation.
14
+
15
+ .. code-block:: php
16
+
17
+ <?php
18
+ require 'vendor/autoload.php';
19
+
20
+ use GuzzleHttp\Ring\Client\CurlHandler;
21
+
22
+ $handler = new CurlHandler();
23
+ $response = $handler([
24
+ 'http_method' => 'GET',
25
+ 'uri' => '/',
26
+ 'headers' => [
27
+ 'host' => ['www.google.com'],
28
+ 'x-foo' => ['baz']
29
+ ]
30
+ ]);
31
+
32
+ $response->then(function (array $response) {
33
+ echo $response['status'];
34
+ });
35
+
36
+ $response->wait();
37
+
38
+ RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
39
+ which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
40
+ utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
41
+ HTTP requests.
42
+
43
+ Documentation
44
+ -------------
45
+
46
+ See http://ringphp.readthedocs.org/ for the full online documentation.
vendor/guzzlehttp/ringphp/composer.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "guzzlehttp/ringphp",
3
+ "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
4
+ "license": "MIT",
5
+ "authors": [
6
+ {
7
+ "name": "Michael Dowling",
8
+ "email": "mtdowling@gmail.com",
9
+ "homepage": "https://github.com/mtdowling"
10
+ }
11
+ ],
12
+ "require": {
13
+ "php": ">=5.4.0",
14
+ "guzzlehttp/streams": "~3.0",
15
+ "react/promise": "~2.0"
16
+ },
17
+ "require-dev": {
18
+ "ext-curl": "*",
19
+ "phpunit/phpunit": "~4.0"
20
+ },
21
+ "suggest": {
22
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
23
+ },
24
+ "autoload": {
25
+ "psr-4": {
26
+ "GuzzleHttp\\Ring\\": "src/"
27
+ }
28
+ },
29
+ "autoload-dev": {
30
+ "psr-4": {
31
+ "GuzzleHttp\\Tests\\Ring\\": "tests/"
32
+ }
33
+ },
34
+ "scripts": {
35
+ "test": "make test",
36
+ "test-ci": "make coverage"
37
+ },
38
+ "extra": {
39
+ "branch-alias": {
40
+ "dev-master": "1.1-dev"
41
+ }
42
+ }
43
+ }
vendor/guzzlehttp/ringphp/docs/Makefile ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Makefile for Sphinx documentation
2
+ #
3
+
4
+ # You can set these variables from the command line.
5
+ SPHINXOPTS =
6
+ SPHINXBUILD = sphinx-build
7
+ PAPER =
8
+ BUILDDIR = _build
9
+
10
+ # Internal variables.
11
+ PAPEROPT_a4 = -D latex_paper_size=a4
12
+ PAPEROPT_letter = -D latex_paper_size=letter
13
+ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
14
+ # the i18n builder cannot share the environment and doctrees with the others
15
+ I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
16
+
17
+ .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
18
+
19
+ help:
20
+ @echo "Please use \`make <target>' where <target> is one of"
21
+ @echo " html to make standalone HTML files"
22
+ @echo " dirhtml to make HTML files named index.html in directories"
23
+ @echo " singlehtml to make a single large HTML file"
24
+ @echo " pickle to make pickle files"
25
+ @echo " json to make JSON files"
26
+ @echo " htmlhelp to make HTML files and a HTML help project"
27
+ @echo " qthelp to make HTML files and a qthelp project"
28
+ @echo " devhelp to make HTML files and a Devhelp project"
29
+ @echo " epub to make an epub"
30
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
31
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
32
+ @echo " text to make text files"
33
+ @echo " man to make manual pages"
34
+ @echo " texinfo to make Texinfo files"
35
+ @echo " info to make Texinfo files and run them through makeinfo"
36
+ @echo " gettext to make PO message catalogs"
37
+ @echo " changes to make an overview of all changed/added/deprecated items"
38
+ @echo " linkcheck to check all external links for integrity"
39
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40
+
41
+ clean:
42
+ -rm -rf $(BUILDDIR)/*
43
+
44
+ html:
45
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46
+ @echo
47
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
48
+
49
+ dirhtml:
50
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
51
+ @echo
52
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
53
+
54
+ singlehtml:
55
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
56
+ @echo
57
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
58
+
59
+ pickle:
60
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
61
+ @echo
62
+ @echo "Build finished; now you can process the pickle files."
63
+
64
+ json:
65
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
66
+ @echo
67
+ @echo "Build finished; now you can process the JSON files."
68
+
69
+ htmlhelp:
70
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
71
+ @echo
72
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
73
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
74
+
75
+ qthelp:
76
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
77
+ @echo
78
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
79
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
80
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GuzzleRing.qhcp"
81
+ @echo "To view the help file:"
82
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GuzzleRing.qhc"
83
+
84
+ devhelp:
85
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
86
+ @echo
87
+ @echo "Build finished."
88
+ @echo "To view the help file:"
89
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/GuzzleRing"
90
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GuzzleRing"
91
+ @echo "# devhelp"
92
+
93
+ epub:
94
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
95
+ @echo
96
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
97
+
98
+ latex:
99
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
100
+ @echo
101
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
102
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
103
+ "(use \`make latexpdf' here to do that automatically)."
104
+
105
+ latexpdf:
106
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
107
+ @echo "Running LaTeX files through pdflatex..."
108
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
109
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
110
+
111
+ text:
112
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
113
+ @echo
114
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
115
+
116
+ man:
117
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
118
+ @echo
119
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
120
+
121
+ texinfo:
122
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
123
+ @echo
124
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
125
+ @echo "Run \`make' in that directory to run these through makeinfo" \
126
+ "(use \`make info' here to do that automatically)."
127
+
128
+ info:
129
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
130
+ @echo "Running Texinfo files through makeinfo..."
131
+ make -C $(BUILDDIR)/texinfo info
132
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
133
+
134
+ gettext:
135
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
136
+ @echo
137
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
138
+
139
+ changes:
140
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
141
+ @echo
142
+ @echo "The overview file is in $(BUILDDIR)/changes."
143
+
144
+ linkcheck:
145
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
146
+ @echo
147
+ @echo "Link check complete; look for any errors in the above output " \
148
+ "or in $(BUILDDIR)/linkcheck/output.txt."
149
+
150
+ doctest:
151
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
152
+ @echo "Testing of doctests in the sources finished, look at the " \
153
+ "results in $(BUILDDIR)/doctest/output.txt."
vendor/guzzlehttp/ringphp/docs/client_handlers.rst ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ===============
2
+ Client Handlers
3
+ ===============
4
+
5
+ Client handlers accept a request array and return a future response array that
6
+ can be used synchronously as an array or asynchronously using a promise.
7
+
8
+ Built-In Handlers
9
+ -----------------
10
+
11
+ RingPHP comes with three built-in client handlers.
12
+
13
+ Stream Handler
14
+ ~~~~~~~~~~~~~~
15
+
16
+ The ``GuzzleHttp\Ring\Client\StreamHandler`` uses PHP's
17
+ `http stream wrapper <http://php.net/manual/en/wrappers.http.php>`_ to send
18
+ requests.
19
+
20
+ .. note::
21
+
22
+ This handler cannot send requests concurrently.
23
+
24
+ You can provide an associative array of custom stream context options to the
25
+ StreamHandler using the ``stream_context`` key of the ``client`` request
26
+ option.
27
+
28
+ .. code-block:: php
29
+
30
+ use GuzzleHttp\Ring\Client\StreamHandler;
31
+
32
+ $response = $handler([
33
+ 'http_method' => 'GET',
34
+ 'uri' => '/',
35
+ 'headers' => ['host' => ['httpbin.org']],
36
+ 'client' => [
37
+ 'stream_context' => [
38
+ 'http' => [
39
+ 'request_fulluri' => true,
40
+ 'method' => 'HEAD'
41
+ ],
42
+ 'socket' => [
43
+ 'bindto' => '127.0.0.1:0'
44
+ ],
45
+ 'ssl' => [
46
+ 'verify_peer' => false
47
+ ]
48
+ ]
49
+ ]
50
+ ]);
51
+
52
+ // Even though it's already completed, you can still use a promise
53
+ $response->then(function ($response) {
54
+ echo $response['status']; // 200
55
+ });
56
+
57
+ // Or access the response using the future interface
58
+ echo $response['status']; // 200
59
+
60
+ cURL Handler
61
+ ~~~~~~~~~~~~
62
+
63
+ The ``GuzzleHttp\Ring\Client\CurlHandler`` can be used with PHP 5.5+ to send
64
+ requests using cURL easy handles. This handler is great for sending requests
65
+ one at a time because the execute and select loop is implemented in C code
66
+ which executes faster and consumes less memory than using PHP's
67
+ ``curl_multi_*`` interface.
68
+
69
+ .. note::
70
+
71
+ This handler cannot send requests concurrently.
72
+
73
+ When using the CurlHandler, custom curl options can be specified as an
74
+ associative array of `cURL option constants <http://php.net/manual/en/curl.constants.php>`_
75
+ mapping to values in the ``client`` option of a requst using the **curl** key.
76
+
77
+ .. code-block:: php
78
+
79
+ use GuzzleHttp\Ring\Client\CurlHandler;
80
+
81
+ $handler = new CurlHandler();
82
+
83
+ $request = [
84
+ 'http_method' => 'GET',
85
+ 'headers' => ['host' => [Server::$host]],
86
+ 'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]]
87
+ ];
88
+
89
+ $response = $handler($request);
90
+
91
+ // The response can be used directly as an array.
92
+ echo $response['status']; // 200
93
+
94
+ // Or, it can be used as a promise (that has already fulfilled).
95
+ $response->then(function ($response) {
96
+ echo $response['status']; // 200
97
+ });
98
+
99
+ cURL Multi Handler
100
+ ~~~~~~~~~~~~~~~~~~
101
+
102
+ The ``GuzzleHttp\Ring\Client\CurlMultiHandler`` transfers requests using
103
+ cURL's `multi API <http://curl.haxx.se/libcurl/c/libcurl-multi.html>`_. The
104
+ ``CurlMultiHandler`` is great for sending requests concurrently.
105
+
106
+ .. code-block:: php
107
+
108
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
109
+
110
+ $handler = new CurlMultiHandler();
111
+
112
+ $request = [
113
+ 'http_method' => 'GET',
114
+ 'headers' => ['host' => [Server::$host]]
115
+ ];
116
+
117
+ // this call returns a future array immediately.
118
+ $response = $handler($request);
119
+
120
+ // Ideally, you should use the promise API to not block.
121
+ $response
122
+ ->then(function ($response) {
123
+ // Got the response at some point in the future
124
+ echo $response['status']; // 200
125
+ // Don't break the chain
126
+ return $response;
127
+ })->then(function ($response) {
128
+ // ...
129
+ });
130
+
131
+ // If you really need to block, then you can use the response as an
132
+ // associative array. This will block until it has completed.
133
+ echo $response['status']; // 200
134
+
135
+ Just like the ``CurlHandler``, the ``CurlMultiHandler`` accepts custom curl
136
+ option in the ``curl`` key of the ``client`` request option.
137
+
138
+ Mock Handler
139
+ ~~~~~~~~~~~~
140
+
141
+ The ``GuzzleHttp\Ring\Client\MockHandler`` is used to return mock responses.
142
+ When constructed, the handler can be configured to return the same response
143
+ array over and over, a future response, or a the evaluation of a callback
144
+ function.
145
+
146
+ .. code-block:: php
147
+
148
+ use GuzzleHttp\Ring\Client\MockHandler;
149
+
150
+ // Return a canned response.
151
+ $mock = new MockHandler(['status' => 200]);
152
+ $response = $mock([]);
153
+ assert(200 == $response['status']);
154
+ assert([] == $response['headers']);
155
+
156
+ Implementing Handlers
157
+ ---------------------
158
+
159
+ Client handlers are just PHP callables (functions or classes that have the
160
+ ``__invoke`` magic method). The callable accepts a request array and MUST
161
+ return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface`` so that
162
+ the response can be used by both blocking and non-blocking consumers.
163
+
164
+ Handlers need to follow a few simple rules:
165
+
166
+ 1. Do not throw exceptions. If an error is encountered, return an array that
167
+ contains the ``error`` key that maps to an ``\Exception`` value.
168
+ 2. If the request has a ``delay`` client option, then the handler should only
169
+ send the request after the specified delay time in seconds. Blocking
170
+ handlers may find it convenient to just let the
171
+ ``GuzzleHttp\Ring\Core::doSleep($request)`` function handle this for them.
172
+ 3. Always return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface``.
173
+ 4. Complete any outstanding requests when the handler is destructed.
vendor/guzzlehttp/ringphp/docs/client_middleware.rst ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =================
2
+ Client Middleware
3
+ =================
4
+
5
+ Middleware intercepts requests before they are sent over the wire and can be
6
+ used to add functionality to handlers.
7
+
8
+ Modifying Requests
9
+ ------------------
10
+
11
+ Let's say you wanted to modify requests before they are sent over the wire
12
+ so that they always add specific headers. This can be accomplished by creating
13
+ a function that accepts a handler and returns a new function that adds the
14
+ composed behavior.
15
+
16
+ .. code-block:: php
17
+
18
+ use GuzzleHttp\Ring\Client\CurlHandler;
19
+
20
+ $handler = new CurlHandler();
21
+
22
+ $addHeaderHandler = function (callable $handler, array $headers = []) {
23
+ return function (array $request) use ($handler, $headers) {
24
+ // Add our custom headers
25
+ foreach ($headers as $key => $value) {
26
+ $request['headers'][$key] = $value;
27
+ }
28
+
29
+ // Send the request using the handler and return the response.
30
+ return $handler($request);
31
+ }
32
+ };
33
+
34
+ // Create a new handler that adds headers to each request.
35
+ $handler = $addHeaderHandler($handler, [
36
+ 'X-AddMe' => 'hello',
37
+ 'Authorization' => 'Basic xyz'
38
+ ]);
39
+
40
+ $response = $handler([
41
+ 'http_method' => 'GET',
42
+ 'headers' => ['Host' => ['httpbin.org']]
43
+ ]);
44
+
45
+ Modifying Responses
46
+ -------------------
47
+
48
+ You can change a response as it's returned from a middleware. Remember that
49
+ responses returned from an handler (including middleware) must implement
50
+ ``GuzzleHttp\Ring\Future\FutureArrayInterface``. In order to be a good citizen,
51
+ you should not expect that the responses returned through your middleware will
52
+ be completed synchronously. Instead, you should use the
53
+ ``GuzzleHttp\Ring\Core::proxy()`` function to modify the response when the
54
+ underlying promise is resolved. This function is a helper function that makes it
55
+ easy to create a new instance of ``FutureArrayInterface`` that wraps an existing
56
+ ``FutureArrayInterface`` object.
57
+
58
+ Let's say you wanted to add headers to a response as they are returned from
59
+ your middleware, but you want to make sure you aren't causing future
60
+ responses to be dereferenced right away. You can achieve this by modifying the
61
+ incoming request and using the ``Core::proxy`` function.
62
+
63
+ .. code-block:: php
64
+
65
+ use GuzzleHttp\Ring\Core;
66
+ use GuzzleHttp\Ring\Client\CurlHandler;
67
+
68
+ $handler = new CurlHandler();
69
+
70
+ $responseHeaderHandler = function (callable $handler, array $headers) {
71
+ return function (array $request) use ($handler, $headers) {
72
+ // Send the request using the wrapped handler.
73
+ return Core::proxy($handler($request), function ($response) use ($headers) {
74
+ // Add the headers to the response when it is available.
75
+ foreach ($headers as $key => $value) {
76
+ $response['headers'][$key] = (array) $value;
77
+ }
78
+ // Note that you can return a regular response array when using
79
+ // the proxy method.
80
+ return $response;
81
+ });
82
+ }
83
+ };
84
+
85
+ // Create a new handler that adds headers to each response.
86
+ $handler = $responseHeaderHandler($handler, ['X-Header' => 'hello!']);
87
+
88
+ $response = $handler([
89
+ 'http_method' => 'GET',
90
+ 'headers' => ['Host' => ['httpbin.org']]
91
+ ]);
92
+
93
+ assert($response['headers']['X-Header'] == 'hello!');
94
+
95
+ Built-In Middleware
96
+ -------------------
97
+
98
+ RingPHP comes with a few basic client middlewares that modify requests
99
+ and responses.
100
+
101
+ Streaming Middleware
102
+ ~~~~~~~~~~~~~~~~~~~~
103
+
104
+ If you want to send all requests with the ``streaming`` option to a specific
105
+ handler but other requests to a different handler, then use the streaming
106
+ middleware.
107
+
108
+ .. code-block:: php
109
+
110
+ use GuzzleHttp\Ring\Client\CurlHandler;
111
+ use GuzzleHttp\Ring\Client\StreamHandler;
112
+ use GuzzleHttp\Ring\Client\Middleware;
113
+
114
+ $defaultHandler = new CurlHandler();
115
+ $streamingHandler = new StreamHandler();
116
+ $streamingHandler = Middleware::wrapStreaming(
117
+ $defaultHandler,
118
+ $streamingHandler
119
+ );
120
+
121
+ // Send the request using the streaming handler.
122
+ $response = $streamingHandler([
123
+ 'http_method' => 'GET',
124
+ 'headers' => ['Host' => ['www.google.com']],
125
+ 'stream' => true
126
+ ]);
127
+
128
+ // Send the request using the default handler.
129
+ $response = $streamingHandler([
130
+ 'http_method' => 'GET',
131
+ 'headers' => ['Host' => ['www.google.com']]
132
+ ]);
133
+
134
+ Future Middleware
135
+ ~~~~~~~~~~~~~~~~~
136
+
137
+ If you want to send all requests with the ``future`` option to a specific
138
+ handler but other requests to a different handler, then use the future
139
+ middleware.
140
+
141
+ .. code-block:: php
142
+
143
+ use GuzzleHttp\Ring\Client\CurlHandler;
144
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
145
+ use GuzzleHttp\Ring\Client\Middleware;
146
+
147
+ $defaultHandler = new CurlHandler();
148
+ $futureHandler = new CurlMultiHandler();
149
+ $futureHandler = Middleware::wrapFuture(
150
+ $defaultHandler,
151
+ $futureHandler
152
+ );
153
+
154
+ // Send the request using the blocking CurlHandler.
155
+ $response = $futureHandler([
156
+ 'http_method' => 'GET',
157
+ 'headers' => ['Host' => ['www.google.com']]
158
+ ]);
159
+
160
+ // Send the request using the non-blocking CurlMultiHandler.
161
+ $response = $futureHandler([
162
+ 'http_method' => 'GET',
163
+ 'headers' => ['Host' => ['www.google.com']],
164
+ 'future' => true
165
+ ]);
vendor/guzzlehttp/ringphp/docs/conf.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys, os
2
+ import sphinx_rtd_theme
3
+ from sphinx.highlighting import lexers
4
+ from pygments.lexers.web import PhpLexer
5
+
6
+
7
+ lexers['php'] = PhpLexer(startinline=True, linenos=1)
8
+ lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
9
+ primary_domain = 'php'
10
+
11
+ extensions = []
12
+ templates_path = ['_templates']
13
+ source_suffix = '.rst'
14
+ master_doc = 'index'
15
+ project = u'RingPHP'
16
+ copyright = u'2014, Michael Dowling'
17
+ version = '1.0.0-alpha'
18
+ exclude_patterns = ['_build']
19
+
20
+ html_title = "RingPHP"
21
+ html_short_title = "RingPHP"
22
+ html_theme = "sphinx_rtd_theme"
23
+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
vendor/guzzlehttp/ringphp/docs/futures.rst ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =======
2
+ Futures
3
+ =======
4
+
5
+ Futures represent a computation that may have not yet completed. RingPHP
6
+ uses hybrid of futures and promises to provide a consistent API that can be
7
+ used for both blocking and non-blocking consumers.
8
+
9
+ Promises
10
+ --------
11
+
12
+ You can get the result of a future when it is ready using the promise interface
13
+ of a future. Futures expose a promise API via a ``then()`` method that utilizes
14
+ `React's promise library <https://github.com/reactphp/promise>`_. You should
15
+ use this API when you do not wish to block.
16
+
17
+ .. code-block:: php
18
+
19
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
20
+
21
+ $request = [
22
+ 'http_method' => 'GET',
23
+ 'uri' => '/',
24
+ 'headers' => ['host' => ['httpbin.org']]
25
+ ];
26
+
27
+ $response = $handler($request);
28
+
29
+ // Use the then() method to use the promise API of the future.
30
+ $response->then(function ($response) {
31
+ echo $response['status'];
32
+ });
33
+
34
+ You can get the promise used by a future, an instance of
35
+ ``React\Promise\PromiseInterface``, by calling the ``promise()`` method.
36
+
37
+ .. code-block:: php
38
+
39
+ $response = $handler($request);
40
+ $promise = $response->promise();
41
+ $promise->then(function ($response) {
42
+ echo $response['status'];
43
+ });
44
+
45
+ This promise value can be used with React's
46
+ `aggregate promise functions <https://github.com/reactphp/promise#functions>`_.
47
+
48
+ Waiting
49
+ -------
50
+
51
+ You can wait on a future to complete and retrieve the value, or *dereference*
52
+ the future, using the ``wait()`` method. Calling the ``wait()`` method of a
53
+ future will block until the result is available. The result is then returned or
54
+ an exception is thrown if and exception was encountered while waiting on the
55
+ the result. Subsequent calls to dereference a future will return the previously
56
+ completed result or throw the previously encountered exception. Futures can be
57
+ cancelled, which stops the computation if possible.
58
+
59
+ .. code-block:: php
60
+
61
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
62
+
63
+ $response = $handler([
64
+ 'http_method' => 'GET',
65
+ 'uri' => '/',
66
+ 'headers' => ['host' => ['httpbin.org']]
67
+ ]);
68
+
69
+ // You can explicitly call block to wait on a result.
70
+ $realizedResponse = $response->wait();
71
+
72
+ // Future responses can be used like a regular PHP array.
73
+ echo $response['status'];
74
+
75
+ In addition to explicitly calling the ``wait()`` function, using a future like
76
+ a normal value will implicitly trigger the ``wait()`` function.
77
+
78
+ Future Responses
79
+ ----------------
80
+
81
+ RingPHP uses futures to return asynchronous responses immediately. Client
82
+ handlers always return future responses that implement
83
+ ``GuzzleHttp\Ring\Future\ArrayFutureInterface``. These future responses act
84
+ just like normal PHP associative arrays for blocking access and provide a
85
+ promise interface for non-blocking access.
86
+
87
+ .. code-block:: php
88
+
89
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
90
+
91
+ $handler = new CurlMultiHandler();
92
+
93
+ $request = [
94
+ 'http_method' => 'GET',
95
+ 'uri' => '/',
96
+ 'headers' => ['Host' => ['www.google.com']]
97
+ ];
98
+
99
+ $response = $handler($request);
100
+
101
+ // Use the promise API for non-blocking access to the response. The actual
102
+ // response value will be delivered to the promise.
103
+ $response->then(function ($response) {
104
+ echo $response['status'];
105
+ });
106
+
107
+ // You can wait (block) until the future is completed.
108
+ $response->wait();
109
+
110
+ // This will implicitly call wait(), and will block too!
111
+ $response['status'];
112
+
113
+ .. important::
114
+
115
+ Futures that are not completed by the time the underlying handler is
116
+ destructed will be completed when the handler is shutting down.
117
+
118
+ Cancelling
119
+ ----------
120
+
121
+ Futures can be cancelled if they have not already been dereferenced.
122
+
123
+ RingPHP futures are typically implemented with the
124
+ ``GuzzleHttp\Ring\Future\BaseFutureTrait``. This trait provides the cancellation
125
+ functionality that should be common to most implementations. Cancelling a
126
+ future response will try to prevent the request from sending over the wire.
127
+
128
+ When a future is cancelled, the cancellation function is invoked and performs
129
+ the actual work needed to cancel the request from sending if possible
130
+ (e.g., telling an event loop to stop sending a request or to close a socket).
131
+ If no cancellation function is provided, then a request cannot be cancelled. If
132
+ a cancel function is provided, then it should accept the future as an argument
133
+ and return true if the future was successfully cancelled or false if it could
134
+ not be cancelled.
135
+
136
+ Wrapping an existing Promise
137
+ ----------------------------
138
+
139
+ You can easily create a future from any existing promise using the
140
+ ``GuzzleHttp\Ring\Future\FutureValue`` class. This class's constructor
141
+ accepts a promise as the first argument, a wait function as the second
142
+ argument, and a cancellation function as the third argument. The dereference
143
+ function is used to force the promise to resolve (for example, manually ticking
144
+ an event loop). The cancel function is optional and is used to tell the thing
145
+ that created the promise that it can stop computing the result (for example,
146
+ telling an event loop to stop transferring a request).
147
+
148
+ .. code-block:: php
149
+
150
+ use GuzzleHttp\Ring\Future\FutureValue;
151
+ use React\Promise\Deferred;
152
+
153
+ $deferred = new Deferred();
154
+ $promise = $deferred->promise();
155
+
156
+ $f = new FutureValue(
157
+ $promise,
158
+ function () use ($deferred) {
159
+ // This function is responsible for blocking and resolving the
160
+ // promise. Here we pass in a reference to the deferred so that
161
+ // it can be resolved or rejected.
162
+ $deferred->resolve('foo');
163
+ }
164
+ );
vendor/guzzlehttp/ringphp/docs/index.rst ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =======
2
+ RingPHP
3
+ =======
4
+
5
+ Provides a simple API and specification that abstracts away the details of HTTP
6
+ into a single PHP function. RingPHP be used to power HTTP clients and servers
7
+ through a PHP function that accepts a request hash and returns a response hash
8
+ that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
9
+ allowing RingPHP to support both synchronous and asynchronous workflows.
10
+
11
+ By abstracting the implementation details of different HTTP clients and
12
+ servers, RingPHP allows you to utilize pluggable HTTP clients and servers
13
+ without tying your application to a specific implementation.
14
+
15
+ .. toctree::
16
+ :maxdepth: 2
17
+
18
+ spec
19
+ futures
20
+ client_middleware
21
+ client_handlers
22
+ testing
23
+
24
+ .. code-block:: php
25
+
26
+ <?php
27
+ require 'vendor/autoload.php';
28
+
29
+ use GuzzleHttp\Ring\Client\CurlHandler;
30
+
31
+ $handler = new CurlHandler();
32
+ $response = $handler([
33
+ 'http_method' => 'GET',
34
+ 'uri' => '/',
35
+ 'headers' => [
36
+ 'host' => ['www.google.com'],
37
+ 'x-foo' => ['baz']
38
+ ]
39
+ ]);
40
+
41
+ $response->then(function (array $response) {
42
+ echo $response['status'];
43
+ });
44
+
45
+ $response->wait();
46
+
47
+ RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
48
+ which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
49
+ utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
50
+ HTTP requests.
vendor/guzzlehttp/ringphp/docs/requirements.txt ADDED
@@ -0,0 +1 @@
 
1
+ sphinx_rtd_theme
vendor/guzzlehttp/ringphp/docs/spec.rst ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =============
2
+ Specification
3
+ =============
4
+
5
+ RingPHP applications consist of handlers, requests, responses, and
6
+ middleware.
7
+
8
+ Handlers
9
+ --------
10
+
11
+ Handlers are implemented as a PHP ``callable`` that accept a request array
12
+ and return a response array (``GuzzleHttp\Ring\Future\FutureArrayInterface``).
13
+
14
+ For example:
15
+
16
+ .. code-block:: php
17
+
18
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
19
+
20
+ $mockHandler = function (array $request) {
21
+ return new CompletedFutureArray([
22
+ 'status' => 200,
23
+ 'headers' => ['X-Foo' => ['Bar']],
24
+ 'body' => 'Hello!'
25
+ ]);
26
+ };
27
+
28
+ This handler returns the same response each time it is invoked. All RingPHP
29
+ handlers must return a ``GuzzleHttp\Ring\Future\FutureArrayInterface``. Use
30
+ ``GuzzleHttp\Ring\Future\CompletedFutureArray`` when returning a response that
31
+ has already completed.
32
+
33
+ Requests
34
+ --------
35
+
36
+ A request array is a PHP associative array that contains the configuration
37
+ settings need to send a request.
38
+
39
+ .. code-block:: php
40
+
41
+ $request = [
42
+ 'http_method' => 'GET',
43
+ 'scheme' => 'http',
44
+ 'uri' => '/',
45
+ 'body' => 'hello!',
46
+ 'client' => ['timeout' => 1.0],
47
+ 'headers' => [
48
+ 'host' => ['httpbin.org'],
49
+ 'X-Foo' => ['baz', 'bar']
50
+ ]
51
+ ];
52
+
53
+ The request array contains the following key value pairs:
54
+
55
+ request_method
56
+ (string, required) The HTTP request method, must be all caps corresponding
57
+ to a HTTP request method, such as ``GET`` or ``POST``.
58
+
59
+ scheme
60
+ (string) The transport protocol, must be one of ``http`` or ``https``.
61
+ Defaults to ``http``.
62
+
63
+ uri
64
+ (string, required) The request URI excluding the query string. Must
65
+ start with "/".
66
+
67
+ query_string
68
+ (string) The query string, if present (e.g., ``foo=bar``).
69
+
70
+ version
71
+ (string) HTTP protocol version. Defaults to ``1.1``.
72
+
73
+ headers
74
+ (required, array) Associative array of headers. Each key represents the
75
+ header name. Each value contains an array of strings where each entry of
76
+ the array SHOULD be sent over the wire on a separate header line.
77
+
78
+ body
79
+ (string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
80
+ The body of the request, if present. Can be a string, resource returned
81
+ from fopen, an ``Iterator`` that yields chunks of data, an object that
82
+ implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
83
+
84
+ future
85
+ (bool, string) Controls the asynchronous behavior of a response.
86
+
87
+ Set to ``true`` or omit the ``future`` option to *request* that a request
88
+ will be completed asynchronously. Keep in mind that your request might not
89
+ necessarily be completed asynchronously based on the handler you are using.
90
+ Set the ``future`` option to ``false`` to request that a synchronous
91
+ response be provided.
92
+
93
+ You can provide a string value to specify fine-tuned future behaviors that
94
+ may be specific to the underlying handlers you are using. There are,
95
+ however, some common future options that handlers should implement if
96
+ possible.
97
+
98
+ lazy
99
+ Requests that the handler does not open and send the request
100
+ immediately, but rather only opens and sends the request once the
101
+ future is dereferenced. This option is often useful for sending a large
102
+ number of requests concurrently to allow handlers to take better
103
+ advantage of non-blocking transfers by first building up a pool of
104
+ requests.
105
+
106
+ If an handler does not implement or understand a provided string value,
107
+ then the request MUST be treated as if the user provided ``true`` rather
108
+ than the string value.
109
+
110
+ Future responses created by asynchronous handlers MUST attempt to complete
111
+ any outstanding future responses when they are destructed. Asynchronous
112
+ handlers MAY choose to automatically complete responses when the number
113
+ of outstanding requests reaches an handler-specific threshold.
114
+
115
+ Client Specific Options
116
+ ~~~~~~~~~~~~~~~~~~~~~~~
117
+
118
+ The following options are only used in ring client handlers.
119
+
120
+ .. _client-options:
121
+
122
+ client
123
+ (array) Associative array of client specific transfer options. The
124
+ ``client`` request key value pair can contain the following keys:
125
+
126
+ cert
127
+ (string, array) Set to a string to specify the path to a file
128
+ containing a PEM formatted SSL client side certificate. If a password
129
+ is required, then set ``cert`` to an array containing the path to the
130
+ PEM file in the first array element followed by the certificate
131
+ password in the second array element.
132
+
133
+ connect_timeout
134
+ (float) Float describing the number of seconds to wait while trying to
135
+ connect to a server. Use ``0`` to wait indefinitely (the default
136
+ behavior).
137
+
138
+ debug
139
+ (bool, fopen() resource) Set to true or set to a PHP stream returned by
140
+ fopen() to enable debug output with the handler used to send a request.
141
+ If set to ``true``, the output is written to PHP's STDOUT. If a PHP
142
+ ``fopen`` resource handle is provided, the output is written to the
143
+ stream.
144
+
145
+ "Debug output" is handler specific: different handlers will yield
146
+ different output and various various level of detail. For example, when
147
+ using cURL to transfer requests, cURL's `CURLOPT_VERBOSE <http://curl.haxx.se/libcurl/c/CURLOPT_VERBOSE.html>`_
148
+ will be used. When using the PHP stream wrapper, `stream notifications <http://php.net/manual/en/function.stream-notification-callback.php>`_
149
+ will be emitted.
150
+
151
+ decode_content
152
+ (bool) Specify whether or not ``Content-Encoding`` responses
153
+ (gzip, deflate, etc.) are automatically decoded. Set to ``true`` to
154
+ automatically decode encoded responses. Set to ``false`` to not decode
155
+ responses. By default, content is *not* decoded automatically.
156
+
157
+ delay
158
+ (int) The number of milliseconds to delay before sending the request.
159
+ This is often used for delaying before retrying a request. Handlers
160
+ SHOULD implement this if possible, but it is not a strict requirement.
161
+
162
+ progress
163
+ (function) Defines a function to invoke when transfer progress is made.
164
+ The function accepts the following arguments:
165
+
166
+ 1. The total number of bytes expected to be downloaded
167
+ 2. The number of bytes downloaded so far
168
+ 3. The number of bytes expected to be uploaded
169
+ 4. The number of bytes uploaded so far
170
+
171
+ proxy
172
+ (string, array) Pass a string to specify an HTTP proxy, or an
173
+ associative array to specify different proxies for different protocols
174
+ where the scheme is the key and the value is the proxy address.
175
+
176
+ .. code-block:: php
177
+
178
+ $request = [
179
+ 'http_method' => 'GET',
180
+ 'headers' => ['host' => ['httpbin.org']],
181
+ 'client' => [
182
+ // Use different proxies for different URI schemes.
183
+ 'proxy' => [
184
+ 'http' => 'http://proxy.example.com:5100',
185
+ 'https' => 'https://proxy.example.com:6100'
186
+ ]
187
+ ]
188
+ ];
189
+
190
+ ssl_key
191
+ (string, array) Specify the path to a file containing a private SSL key
192
+ in PEM format. If a password is required, then set to an array
193
+ containing the path to the SSL key in the first array element followed
194
+ by the password required for the certificate in the second element.
195
+
196
+ save_to
197
+ (string, fopen resource, ``GuzzleHttp\Stream\StreamInterface``)
198
+ Specifies where the body of the response is downloaded. Pass a string to
199
+ open a local file on disk and save the output to the file. Pass an fopen
200
+ resource to save the output to a PHP stream resource. Pass a
201
+ ``GuzzleHttp\Stream\StreamInterface`` to save the output to a Guzzle
202
+ StreamInterface. Omitting this option will typically save the body of a
203
+ response to a PHP temp stream.
204
+
205
+ stream
206
+ (bool) Set to true to stream a response rather than download it all
207
+ up-front. This option will only be utilized when the corresponding
208
+ handler supports it.
209
+
210
+ timeout
211
+ (float) Float describing the timeout of the request in seconds. Use 0 to
212
+ wait indefinitely (the default behavior).
213
+
214
+ verify
215
+ (bool, string) Describes the SSL certificate verification behavior of a
216
+ request. Set to true to enable SSL certificate verification using the
217
+ system CA bundle when available (the default). Set to false to disable
218
+ certificate verification (this is insecure!). Set to a string to provide
219
+ the path to a CA bundle on disk to enable verification using a custom
220
+ certificate.
221
+
222
+ version
223
+ (string) HTTP protocol version to use with the request.
224
+
225
+ Server Specific Options
226
+ ~~~~~~~~~~~~~~~~~~~~~~~
227
+
228
+ The following options are only used in ring server handlers.
229
+
230
+ server_port
231
+ (integer) The port on which the request is being handled. This is only
232
+ used with ring servers, and is required.
233
+
234
+ server_name
235
+ (string) The resolved server name, or the server IP address. Required when
236
+ using a Ring server.
237
+
238
+ remote_addr
239
+ (string) The IP address of the client or the last proxy that sent the
240
+ request. Required when using a Ring server.
241
+
242
+ Responses
243
+ ---------
244
+
245
+ A response is an array-like object that implements
246
+ ``GuzzleHttp\Ring\Future\FutureArrayInterface``. Responses contain the
247
+ following key value pairs:
248
+
249
+ body
250
+ (string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
251
+ The body of the response, if present. Can be a string, resource returned
252
+ from fopen, an ``Iterator`` that yields chunks of data, an object that
253
+ implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
254
+
255
+ effective_url
256
+ (string) The URL that returned the resulting response.
257
+
258
+ error
259
+ (``\Exception``) Contains an exception describing any errors that were
260
+ encountered during the transfer.
261
+
262
+ headers
263
+ (Required, array) Associative array of headers. Each key represents the
264
+ header name. Each value contains an array of strings where each entry of
265
+ the array is a header line. The headers array MAY be an empty array in the
266
+ event an error occurred before a response was received.
267
+
268
+ reason
269
+ (string) Optional reason phrase. This option should be provided when the
270
+ reason phrase does not match the typical reason phrase associated with the
271
+ ``status`` code. See `RFC 7231 <http://tools.ietf.org/html/rfc7231#section-6.1>`_
272
+ for a list of HTTP reason phrases mapped to status codes.
273
+
274
+ status
275
+ (Required, integer) The HTTP status code. The status code MAY be set to
276
+ ``null`` in the event an error occurred before a response was received
277
+ (e.g., a networking error).
278
+
279
+ transfer_stats
280
+ (array) Provides an associative array of arbitrary transfer statistics if
281
+ provided by the underlying handler.
282
+
283
+ version
284
+ (string) HTTP protocol version. Defaults to ``1.1``.
285
+
286
+ Middleware
287
+ ----------
288
+
289
+ Ring middleware augments the functionality of handlers by invoking them in the
290
+ process of generating responses. Middleware is typically implemented as a
291
+ higher-order function that takes one or more handlers as arguments followed by
292
+ an optional associative array of options as the last argument, returning a new
293
+ handler with the desired compound behavior.
294
+
295
+ Here's an example of a middleware that adds a Content-Type header to each
296
+ request.
297
+
298
+ .. code-block:: php
299
+
300
+ use GuzzleHttp\Ring\Client\CurlHandler;
301
+ use GuzzleHttp\Ring\Core;
302
+
303
+ $contentTypeHandler = function(callable $handler, $contentType) {
304
+ return function (array $request) use ($handler, $contentType) {
305
+ return $handler(Core::setHeader('Content-Type', $contentType));
306
+ };
307
+ };
308
+
309
+ $baseHandler = new CurlHandler();
310
+ $wrappedHandler = $contentTypeHandler($baseHandler, 'text/html');
311
+ $response = $wrappedHandler([/** request hash **/]);
vendor/guzzlehttp/ringphp/docs/testing.rst ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =======
2
+ Testing
3
+ =======
4
+
5
+ RingPHP tests client handlers using `PHPUnit <https://phpunit.de/>`_ and a
6
+ built-in node.js web server.
7
+
8
+ Running Tests
9
+ -------------
10
+
11
+ First, install the dependencies using `Composer <https://getcomposer.org>`_.
12
+
13
+ composer.phar install
14
+
15
+ Next, run the unit tests using ``Make``.
16
+
17
+ make test
18
+
19
+ The tests are also run on Travis-CI on each commit: https://travis-ci.org/guzzle/guzzle-ring
20
+
21
+ Test Server
22
+ -----------
23
+
24
+ Testing client handlers usually involves actually sending HTTP requests.
25
+ RingPHP provides a node.js web server that returns canned responses and
26
+ keep a list of the requests that have been received. The server can then
27
+ be queried to get a list of the requests that were sent by the client so that
28
+ you can ensure that the client serialized and transferred requests as intended.
29
+
30
+ The server keeps a list of queued responses and returns responses that are
31
+ popped off of the queue as HTTP requests are received. When there are not
32
+ more responses to serve, the server returns a 500 error response.
33
+
34
+ The test server uses the ``GuzzleHttp\Tests\Ring\Client\Server`` class to
35
+ control the server.
36
+
37
+ .. code-block:: php
38
+
39
+ use GuzzleHttp\Ring\Client\StreamHandler;
40
+ use GuzzleHttp\Tests\Ring\Client\Server;
41
+
42
+ // First return a 200 followed by a 404 response.
43
+ Server::enqueue([
44
+ ['status' => 200],
45
+ ['status' => 404]
46
+ ]);
47
+
48
+ $handler = new StreamHandler();
49
+
50
+ $response = $handler([
51
+ 'http_method' => 'GET',
52
+ 'headers' => ['host' => [Server::$host]],
53
+ 'uri' => '/'
54
+ ]);
55
+
56
+ assert(200 == $response['status']);
57
+
58
+ $response = $handler([
59
+ 'http_method' => 'HEAD',
60
+ 'headers' => ['host' => [Server::$host]],
61
+ 'uri' => '/'
62
+ ]);
63
+
64
+ assert(404 == $response['status']);
65
+
66
+ After requests have been sent, you can get a list of the requests as they
67
+ were sent over the wire to ensure they were sent correctly.
68
+
69
+ .. code-block:: php
70
+
71
+ $received = Server::received();
72
+
73
+ assert('GET' == $received[0]['http_method']);
74
+ assert('HEAD' == $received[1]['http_method']);
vendor/guzzlehttp/ringphp/phpunit.xml.dist ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <phpunit bootstrap="./tests/bootstrap.php"
3
+ colors="true">
4
+ <testsuites>
5
+ <testsuite>
6
+ <directory>tests</directory>
7
+ </testsuite>
8
+ </testsuites>
9
+ <filter>
10
+ <whitelist>
11
+ <directory suffix=".php">src</directory>
12
+ </whitelist>
13
+ </filter>
14
+ </phpunit>
vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Client;
3
+
4
+ /**
5
+ * Client specific utility functions.
6
+ */
7
+ class ClientUtils
8
+ {
9
+ /**
10
+ * Returns the default cacert bundle for the current system.
11
+ *
12
+ * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
13
+ * If those settings are not configured, then the common locations for
14
+ * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
15
+ * and Windows are checked. If any of these file locations are found on
16
+ * disk, they will be utilized.
17
+ *
18
+ * Note: the result of this function is cached for subsequent calls.
19
+ *
20
+ * @return string
21
+ * @throws \RuntimeException if no bundle can be found.
22
+ */
23
+ public static function getDefaultCaBundle()
24
+ {
25
+ static $cached = null;
26
+ static $cafiles = [
27
+ // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
28
+ '/etc/pki/tls/certs/ca-bundle.crt',
29
+ // Ubuntu, Debian (provided by the ca-certificates package)
30
+ '/etc/ssl/certs/ca-certificates.crt',
31
+ // FreeBSD (provided by the ca_root_nss package)
32
+ '/usr/local/share/certs/ca-root-nss.crt',
33
+ // OS X provided by homebrew (using the default path)
34
+ '/usr/local/etc/openssl/cert.pem',
35
+ // Windows?
36
+ 'C:\\windows\\system32\\curl-ca-bundle.crt',
37
+ 'C:\\windows\\curl-ca-bundle.crt',
38
+ ];
39
+
40
+ if ($cached) {
41
+ return $cached;
42
+ }
43
+
44
+ if ($ca = ini_get('openssl.cafile')) {
45
+ return $cached = $ca;
46
+ }
47
+
48
+ if ($ca = ini_get('curl.cainfo')) {
49
+ return $cached = $ca;
50
+ }
51
+
52
+ foreach ($cafiles as $filename) {
53
+ if (file_exists($filename)) {
54
+ return $cached = $filename;
55
+ }
56
+ }
57
+
58
+ throw new \RuntimeException(self::CA_ERR);
59
+ }
60
+
61
+ const CA_ERR = "
62
+ No system CA bundle could be found in any of the the common system locations.
63
+ PHP versions earlier than 5.6 are not properly configured to use the system's
64
+ CA bundle by default. In order to verify peer certificates, you will need to
65
+ supply the path on disk to a certificate bundle to the 'verify' request
66
+ option: http://docs.guzzlephp.org/en/5.3/clients.html#verify. If you do not
67
+ need a specific certificate bundle, then Mozilla provides a commonly used CA
68
+ bundle which can be downloaded here (provided by the maintainer of cURL):
69
+ https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
70
+ you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
71
+ ini setting to point to the path to the file, allowing you to omit the 'verify'
72
+ request option. See http://curl.haxx.se/docs/sslcerts.html for more
73
+ information.";
74
+ }
vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php ADDED
@@ -0,0 +1,560 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Core;
5
+ use GuzzleHttp\Ring\Exception\ConnectException;
6
+ use GuzzleHttp\Ring\Exception\RingException;
7
+ use GuzzleHttp\Stream\LazyOpenStream;
8
+ use GuzzleHttp\Stream\StreamInterface;
9
+
10
+ /**
11
+ * Creates curl resources from a request
12
+ */
13
+ class CurlFactory
14
+ {
15
+ /**
16
+ * Creates a cURL handle, header resource, and body resource based on a
17
+ * transaction.
18
+ *
19
+ * @param array $request Request hash
20
+ * @param null|resource $handle Optionally provide a curl handle to modify
21
+ *
22
+ * @return array Returns an array of the curl handle, headers array, and
23
+ * response body handle.
24
+ * @throws \RuntimeException when an option cannot be applied
25
+ */
26
+ public function __invoke(array $request, $handle = null)
27
+ {
28
+ $headers = [];
29
+ $options = $this->getDefaultOptions($request, $headers);
30
+ $this->applyMethod($request, $options);
31
+
32
+ if (isset($request['client'])) {
33
+ $this->applyHandlerOptions($request, $options);
34
+ }
35
+
36
+ $this->applyHeaders($request, $options);
37
+ unset($options['_headers']);
38
+
39
+ // Add handler options from the request's configuration options
40
+ if (isset($request['client']['curl'])) {
41
+ $options = $this->applyCustomCurlOptions(
42
+ $request['client']['curl'],
43
+ $options
44
+ );
45
+ }
46
+
47
+ if (!$handle) {
48
+ $handle = curl_init();
49
+ }
50
+
51
+ $body = $this->getOutputBody($request, $options);
52
+ curl_setopt_array($handle, $options);
53
+
54
+ return [$handle, &$headers, $body];
55
+ }
56
+
57
+ /**
58
+ * Creates a response hash from a cURL result.
59
+ *
60
+ * @param callable $handler Handler that was used.
61
+ * @param array $request Request that sent.
62
+ * @param array $response Response hash to update.
63
+ * @param array $headers Headers received during transfer.
64
+ * @param resource $body Body fopen response.
65
+ *
66
+ * @return array
67
+ */
68
+ public static function createResponse(
69
+ callable $handler,
70
+ array $request,
71
+ array $response,
72
+ array $headers,
73
+ $body
74
+ ) {
75
+ if (isset($response['transfer_stats']['url'])) {
76
+ $response['effective_url'] = $response['transfer_stats']['url'];
77
+ }
78
+
79
+ if (!empty($headers)) {
80
+ $startLine = explode(' ', array_shift($headers), 3);
81
+ $headerList = Core::headersFromLines($headers);
82
+ $response['headers'] = $headerList;
83
+ $response['version'] = isset($startLine[0]) ? substr($startLine[0], 5) : null;
84
+ $response['status'] = isset($startLine[1]) ? (int) $startLine[1] : null;
85
+ $response['reason'] = isset($startLine[2]) ? $startLine[2] : null;
86
+ $response['body'] = $body;
87
+ Core::rewindBody($response);
88
+ }
89
+
90
+ return !empty($response['curl']['errno']) || !isset($response['status'])
91
+ ? self::createErrorResponse($handler, $request, $response)
92
+ : $response;
93
+ }
94
+
95
+ private static function createErrorResponse(
96
+ callable $handler,
97
+ array $request,
98
+ array $response
99
+ ) {
100
+ static $connectionErrors = [
101
+ CURLE_OPERATION_TIMEOUTED => true,
102
+ CURLE_COULDNT_RESOLVE_HOST => true,
103
+ CURLE_COULDNT_CONNECT => true,
104
+ CURLE_SSL_CONNECT_ERROR => true,
105
+ CURLE_GOT_NOTHING => true,
106
+ ];
107
+
108
+ // Retry when nothing is present or when curl failed to rewind.
109
+ if (!isset($response['err_message'])
110
+ && (empty($response['curl']['errno'])
111
+ || $response['curl']['errno'] == 65)
112
+ ) {
113
+ return self::retryFailedRewind($handler, $request, $response);
114
+ }
115
+
116
+ $message = isset($response['err_message'])
117
+ ? $response['err_message']
118
+ : sprintf('cURL error %s: %s',
119
+ $response['curl']['errno'],
120
+ isset($response['curl']['error'])
121
+ ? $response['curl']['error']
122
+ : 'See http://curl.haxx.se/libcurl/c/libcurl-errors.html');
123
+
124
+ $error = isset($response['curl']['errno'])
125
+ && isset($connectionErrors[$response['curl']['errno']])
126
+ ? new ConnectException($message)
127
+ : new RingException($message);
128
+
129
+ return $response + [
130
+ 'status' => null,
131
+ 'reason' => null,
132
+ 'body' => null,
133
+ 'headers' => [],
134
+ 'error' => $error,
135
+ ];
136
+ }
137
+
138
+ private function getOutputBody(array $request, array &$options)
139
+ {
140
+ // Determine where the body of the response (if any) will be streamed.
141
+ if (isset($options[CURLOPT_WRITEFUNCTION])) {
142
+ return $request['client']['save_to'];
143
+ }
144
+
145
+ if (isset($options[CURLOPT_FILE])) {
146
+ return $options[CURLOPT_FILE];
147
+ }
148
+
149
+ if ($request['http_method'] != 'HEAD') {
150
+ // Create a default body if one was not provided
151
+ return $options[CURLOPT_FILE] = fopen('php://temp', 'w+');
152
+ }
153
+
154
+ return null;
155
+ }
156
+
157
+ private function getDefaultOptions(array $request, array &$headers)
158
+ {
159
+ $url = Core::url($request);
160
+ $startingResponse = false;
161
+
162
+ $options = [
163
+ '_headers' => $request['headers'],
164
+ CURLOPT_CUSTOMREQUEST => $request['http_method'],
165
+ CURLOPT_URL => $url,
166
+ CURLOPT_RETURNTRANSFER => false,
167
+ CURLOPT_HEADER => false,
168
+ CURLOPT_CONNECTTIMEOUT => 150,
169
+ CURLOPT_HEADERFUNCTION => function ($ch, $h) use (&$headers, &$startingResponse) {
170
+ $value = trim($h);
171
+ if ($value === '') {
172
+ $startingResponse = true;
173
+ } elseif ($startingResponse) {
174
+ $startingResponse = false;
175
+ $headers = [$value];
176
+ } else {
177
+ $headers[] = $value;
178
+ }
179
+ return strlen($h);
180
+ },
181
+ ];
182
+
183
+ if (isset($request['version'])) {
184
+ if ($request['version'] == 2.0) {
185
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
186
+ } else if ($request['version'] == 1.1) {
187
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
188
+ } else {
189
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
190
+ }
191
+ }
192
+
193
+ if (defined('CURLOPT_PROTOCOLS')) {
194
+ $options[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
195
+ }
196
+
197
+ return $options;
198
+ }
199
+
200
+ private function applyMethod(array $request, array &$options)
201
+ {
202
+ if (isset($request['body'])) {
203
+ $this->applyBody($request, $options);
204
+ return;
205
+ }
206
+
207
+ switch ($request['http_method']) {
208
+ case 'PUT':
209
+ case 'POST':
210
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
211
+ if (!Core::hasHeader($request, 'Content-Length')) {
212
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
213
+ }
214
+ break;
215
+ case 'HEAD':
216
+ $options[CURLOPT_NOBODY] = true;
217
+ unset(
218
+ $options[CURLOPT_WRITEFUNCTION],
219
+ $options[CURLOPT_READFUNCTION],
220
+ $options[CURLOPT_FILE],
221
+ $options[CURLOPT_INFILE]
222
+ );
223
+ }
224
+ }
225
+
226
+ private function applyBody(array $request, array &$options)
227
+ {
228
+ $contentLength = Core::firstHeader($request, 'Content-Length');
229
+ $size = $contentLength !== null ? (int) $contentLength : null;
230
+
231
+ // Send the body as a string if the size is less than 1MB OR if the
232
+ // [client][curl][body_as_string] request value is set.
233
+ if (($size !== null && $size < 1000000) ||
234
+ isset($request['client']['curl']['body_as_string']) ||
235
+ is_string($request['body'])
236
+ ) {
237
+ $options[CURLOPT_POSTFIELDS] = Core::body($request);
238
+ // Don't duplicate the Content-Length header
239
+ $this->removeHeader('Content-Length', $options);
240
+ $this->removeHeader('Transfer-Encoding', $options);
241
+ } else {
242
+ $options[CURLOPT_UPLOAD] = true;
243
+ if ($size !== null) {
244
+ // Let cURL handle setting the Content-Length header
245
+ $options[CURLOPT_INFILESIZE] = $size;
246
+ $this->removeHeader('Content-Length', $options);
247
+ }
248
+ $this->addStreamingBody($request, $options);
249
+ }
250
+
251
+ // If the Expect header is not present, prevent curl from adding it
252
+ if (!Core::hasHeader($request, 'Expect')) {
253
+ $options[CURLOPT_HTTPHEADER][] = 'Expect:';
254
+ }
255
+
256
+ // cURL sometimes adds a content-type by default. Prevent this.
257
+ if (!Core::hasHeader($request, 'Content-Type')) {
258
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Type:';
259
+ }
260
+ }
261
+
262
+ private function addStreamingBody(array $request, array &$options)
263
+ {
264
+ $body = $request['body'];
265
+
266
+ if ($body instanceof StreamInterface) {
267
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
268
+ return (string) $body->read($length);
269
+ };
270
+ if (!isset($options[CURLOPT_INFILESIZE])) {
271
+ if ($size = $body->getSize()) {
272
+ $options[CURLOPT_INFILESIZE] = $size;
273
+ }
274
+ }
275
+ } elseif (is_resource($body)) {
276
+ $options[CURLOPT_INFILE] = $body;
277
+ } elseif ($body instanceof \Iterator) {
278
+ $buf = '';
279
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body, &$buf) {
280
+ if ($body->valid()) {
281
+ $buf .= $body->current();
282
+ $body->next();
283
+ }
284
+ $result = (string) substr($buf, 0, $length);
285
+ $buf = substr($buf, $length);
286
+ return $result;
287
+ };
288
+ } else {
289
+ throw new \InvalidArgumentException('Invalid request body provided');
290
+ }
291
+ }
292
+
293
+ private function applyHeaders(array $request, array &$options)
294
+ {
295
+ foreach ($options['_headers'] as $name => $values) {
296
+ foreach ($values as $value) {
297
+ $options[CURLOPT_HTTPHEADER][] = "$name: $value";
298
+ }
299
+ }
300
+
301
+ // Remove the Accept header if one was not set
302
+ if (!Core::hasHeader($request, 'Accept')) {
303
+ $options[CURLOPT_HTTPHEADER][] = 'Accept:';
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Takes an array of curl options specified in the 'curl' option of a
309
+ * request's configuration array and maps them to CURLOPT_* options.
310
+ *
311
+ * This method is only called when a request has a 'curl' config setting.
312
+ *
313
+ * @param array $config Configuration array of custom curl option
314
+ * @param array $options Array of existing curl options
315
+ *
316
+ * @return array Returns a new array of curl options
317
+ */
318
+ private function applyCustomCurlOptions(array $config, array $options)
319
+ {
320
+ $curlOptions = [];
321
+ foreach ($config as $key => $value) {
322
+ if (is_int($key)) {
323
+ $curlOptions[$key] = $value;
324
+ }
325
+ }
326
+
327
+ return $curlOptions + $options;
328
+ }
329
+
330
+ /**
331
+ * Remove a header from the options array.
332
+ *
333
+ * @param string $name Case-insensitive header to remove
334
+ * @param array $options Array of options to modify
335
+ */
336
+ private function removeHeader($name, array &$options)
337
+ {
338
+ foreach (array_keys($options['_headers']) as $key) {
339
+ if (!strcasecmp($key, $name)) {
340
+ unset($options['_headers'][$key]);
341
+ return;
342
+ }
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Applies an array of request client options to a the options array.
348
+ *
349
+ * This method uses a large switch rather than double-dispatch to save on
350
+ * high overhead of calling functions in PHP.
351
+ */
352
+ private function applyHandlerOptions(array $request, array &$options)
353
+ {
354
+ foreach ($request['client'] as $key => $value) {
355
+ switch ($key) {
356
+ // Violating PSR-4 to provide more room.
357
+ case 'verify':
358
+
359
+ if ($value === false) {
360
+ unset($options[CURLOPT_CAINFO]);
361
+ $options[CURLOPT_SSL_VERIFYHOST] = 0;
362
+ $options[CURLOPT_SSL_VERIFYPEER] = false;
363
+ continue 2;
364
+ }
365
+
366
+ $options[CURLOPT_SSL_VERIFYHOST] = 2;
367
+ $options[CURLOPT_SSL_VERIFYPEER] = true;
368
+
369
+ if (is_string($value)) {
370
+ $options[CURLOPT_CAINFO] = $value;
371
+ if (!file_exists($value)) {
372
+ throw new \InvalidArgumentException(
373
+ "SSL CA bundle not found: $value"
374
+ );
375
+ }
376
+ }
377
+ break;
378
+
379
+ case 'decode_content':
380
+
381
+ if ($value === false) {
382
+ continue 2;
383
+ }
384
+
385
+ $accept = Core::firstHeader($request, 'Accept-Encoding');
386
+ if ($accept) {
387
+ $options[CURLOPT_ENCODING] = $accept;
388
+ } else {
389
+ $options[CURLOPT_ENCODING] = '';
390
+ // Don't let curl send the header over the wire
391
+ $options[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
392
+ }
393
+ break;
394
+
395
+ case 'save_to':
396
+
397
+ if (is_string($value)) {
398
+ if (!is_dir(dirname($value))) {
399
+ throw new \RuntimeException(sprintf(
400
+ 'Directory %s does not exist for save_to value of %s',
401
+ dirname($value),
402
+ $value
403
+ ));
404
+ }
405
+ $value = new LazyOpenStream($value, 'w+');
406
+ }
407
+
408
+ if ($value instanceof StreamInterface) {
409
+ $options[CURLOPT_WRITEFUNCTION] =
410
+ function ($ch, $write) use ($value) {
411
+ return $value->write($write);
412
+ };
413
+ } elseif (is_resource($value)) {
414
+ $options[CURLOPT_FILE] = $value;
415
+ } else {
416
+ throw new \InvalidArgumentException('save_to must be a '
417
+ . 'GuzzleHttp\Stream\StreamInterface or resource');
418
+ }
419
+ break;
420
+
421
+ case 'timeout':
422
+
423
+ if (defined('CURLOPT_TIMEOUT_MS')) {
424
+ $options[CURLOPT_TIMEOUT_MS] = $value * 1000;
425
+ } else {
426
+ $options[CURLOPT_TIMEOUT] = $value;
427
+ }
428
+ break;
429
+
430
+ case 'connect_timeout':
431
+
432
+ if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
433
+ $options[CURLOPT_CONNECTTIMEOUT_MS] = $value * 1000;
434
+ } else {
435
+ $options[CURLOPT_CONNECTTIMEOUT] = $value;
436
+ }
437
+ break;
438
+
439
+ case 'proxy':
440
+
441
+ if (!is_array($value)) {
442
+ $options[CURLOPT_PROXY] = $value;
443
+ } elseif (isset($request['scheme'])) {
444
+ $scheme = $request['scheme'];
445
+ if (isset($value[$scheme])) {
446
+ $options[CURLOPT_PROXY] = $value[$scheme];
447
+ }
448
+ }
449
+ break;
450
+
451
+ case 'cert':
452
+
453
+ if (is_array($value)) {
454
+ $options[CURLOPT_SSLCERTPASSWD] = $value[1];
455
+ $value = $value[0];
456
+ }
457
+
458
+ if (!file_exists($value)) {
459
+ throw new \InvalidArgumentException(
460
+ "SSL certificate not found: {$value}"
461
+ );
462
+ }
463
+
464
+ $options[CURLOPT_SSLCERT] = $value;
465
+ break;
466
+
467
+ case 'ssl_key':
468
+
469
+ if (is_array($value)) {
470
+ $options[CURLOPT_SSLKEYPASSWD] = $value[1];
471
+ $value = $value[0];
472
+ }
473
+
474
+ if (!file_exists($value)) {
475
+ throw new \InvalidArgumentException(
476
+ "SSL private key not found: {$value}"
477
+ );
478
+ }
479
+
480
+ $options[CURLOPT_SSLKEY] = $value;
481
+ break;
482
+
483
+ case 'progress':
484
+
485
+ if (!is_callable($value)) {
486
+ throw new \InvalidArgumentException(
487
+ 'progress client option must be callable'
488
+ );
489
+ }
490
+
491
+ $options[CURLOPT_NOPROGRESS] = false;
492
+ $options[CURLOPT_PROGRESSFUNCTION] =
493
+ function () use ($value) {
494
+ $args = func_get_args();
495
+ // PHP 5.5 pushed the handle onto the start of the args
496
+ if (is_resource($args[0])) {
497
+ array_shift($args);
498
+ }
499
+ call_user_func_array($value, $args);
500
+ };
501
+ break;
502
+
503
+ case 'debug':
504
+
505
+ if ($value) {
506
+ $options[CURLOPT_STDERR] = Core::getDebugResource($value);
507
+ $options[CURLOPT_VERBOSE] = true;
508
+ }
509
+ break;
510
+ }
511
+ }
512
+ }
513
+
514
+ /**
515
+ * This function ensures that a response was set on a transaction. If one
516
+ * was not set, then the request is retried if possible. This error
517
+ * typically means you are sending a payload, curl encountered a
518
+ * "Connection died, retrying a fresh connect" error, tried to rewind the
519
+ * stream, and then encountered a "necessary data rewind wasn't possible"
520
+ * error, causing the request to be sent through curl_multi_info_read()
521
+ * without an error status.
522
+ */
523
+ private static function retryFailedRewind(
524
+ callable $handler,
525
+ array $request,
526
+ array $response
527
+ ) {
528
+ // If there is no body, then there is some other kind of issue. This
529
+ // is weird and should probably never happen.
530
+ if (!isset($request['body'])) {
531
+ $response['err_message'] = 'No response was received for a request '
532
+ . 'with no body. This could mean that you are saturating your '
533
+ . 'network.';
534
+ return self::createErrorResponse($handler, $request, $response);
535
+ }
536
+
537
+ if (!Core::rewindBody($request)) {
538
+ $response['err_message'] = 'The connection unexpectedly failed '
539
+ . 'without providing an error. The request would have been '
540
+ . 'retried, but attempting to rewind the request body failed.';
541
+ return self::createErrorResponse($handler, $request, $response);
542
+ }
543
+
544
+ // Retry no more than 3 times before giving up.
545
+ if (!isset($request['curl']['retries'])) {
546
+ $request['curl']['retries'] = 1;
547
+ } elseif ($request['curl']['retries'] == 2) {
548
+ $response['err_message'] = 'The cURL request was retried 3 times '
549
+ . 'and did no succeed. cURL was unable to rewind the body of '
550
+ . 'the request and subsequent retries resulted in the same '
551
+ . 'error. Turn on the debug option to see what went wrong. '
552
+ . 'See https://bugs.php.net/bug.php?id=47204 for more information.';
553
+ return self::createErrorResponse($handler, $request, $response);
554
+ } else {
555
+ $request['curl']['retries']++;
556
+ }
557
+
558
+ return $handler($request);
559
+ }
560
+ }
vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
5
+ use GuzzleHttp\Ring\Core;
6
+
7
+ /**
8
+ * HTTP handler that uses cURL easy handles as a transport layer.
9
+ *
10
+ * Requires PHP 5.5+
11
+ *
12
+ * When using the CurlHandler, custom curl options can be specified as an
13
+ * associative array of curl option constants mapping to values in the
14
+ * **curl** key of the "client" key of the request.
15
+ */
16
+ class CurlHandler
17
+ {
18
+ /** @var callable */
19
+ private $factory;
20
+
21
+ /** @var array Array of curl easy handles */
22
+ private $handles = [];
23
+
24
+ /** @var array Array of owned curl easy handles */
25
+ private $ownedHandles = [];
26
+
27
+ /** @var int Total number of idle handles to keep in cache */
28
+ private $maxHandles;
29
+
30
+ /**
31
+ * Accepts an associative array of options:
32
+ *
33
+ * - factory: Optional callable factory used to create cURL handles.
34
+ * The callable is passed a request hash when invoked, and returns an
35
+ * array of the curl handle, headers resource, and body resource.
36
+ * - max_handles: Maximum number of idle handles (defaults to 5).
37
+ *
38
+ * @param array $options Array of options to use with the handler
39
+ */
40
+ public function __construct(array $options = [])
41
+ {
42
+ $this->handles = $this->ownedHandles = [];
43
+ $this->factory = isset($options['handle_factory'])
44
+ ? $options['handle_factory']
45
+ : new CurlFactory();
46
+ $this->maxHandles = isset($options['max_handles'])
47
+ ? $options['max_handles']
48
+ : 5;
49
+ }
50
+
51
+ public function __destruct()
52
+ {
53
+ foreach ($this->handles as $handle) {
54
+ if (is_resource($handle)) {
55
+ curl_close($handle);
56
+ }
57
+ }
58
+ }
59
+
60
+ /**
61
+ * @param array $request
62
+ *
63
+ * @return CompletedFutureArray
64
+ */
65
+ public function __invoke(array $request)
66
+ {
67
+ return new CompletedFutureArray(
68
+ $this->_invokeAsArray($request)
69
+ );
70
+ }
71
+
72
+ /**
73
+ * @internal
74
+ *
75
+ * @param array $request
76
+ *
77
+ * @return array
78
+ */
79
+ public function _invokeAsArray(array $request)
80
+ {
81
+ $factory = $this->factory;
82
+
83
+ // Ensure headers are by reference. They're updated elsewhere.
84
+ $result = $factory($request, $this->checkoutEasyHandle());
85
+ $h = $result[0];
86
+ $hd =& $result[1];
87
+ $bd = $result[2];
88
+ Core::doSleep($request);
89
+ curl_exec($h);
90
+ $response = ['transfer_stats' => curl_getinfo($h)];
91
+ $response['curl']['error'] = curl_error($h);
92
+ $response['curl']['errno'] = curl_errno($h);
93
+ $response['transfer_stats'] = array_merge($response['transfer_stats'], $response['curl']);
94
+ $this->releaseEasyHandle($h);
95
+
96
+ return CurlFactory::createResponse([$this, '_invokeAsArray'], $request, $response, $hd, $bd);
97
+ }
98
+
99
+ private function checkoutEasyHandle()
100
+ {
101
+ // Find an unused handle in the cache
102
+ if (false !== ($key = array_search(false, $this->ownedHandles, true))) {
103
+ $this->ownedHandles[$key] = true;
104
+ return $this->handles[$key];
105
+ }
106
+
107
+ // Add a new handle
108
+ $handle = curl_init();
109
+ $id = (int) $handle;
110
+ $this->handles[$id] = $handle;
111
+ $this->ownedHandles[$id] = true;
112
+
113
+ return $handle;
114
+ }
115
+
116
+ private function releaseEasyHandle($handle)
117
+ {
118
+ $id = (int) $handle;
119
+ if (count($this->ownedHandles) > $this->maxHandles) {
120
+ curl_close($this->handles[$id]);
121
+ unset($this->handles[$id], $this->ownedHandles[$id]);
122
+ } else {
123
+ // curl_reset doesn't clear these out for some reason
124
+ static $unsetValues = [
125
+ CURLOPT_HEADERFUNCTION => null,
126
+ CURLOPT_WRITEFUNCTION => null,
127
+ CURLOPT_READFUNCTION => null,
128
+ CURLOPT_PROGRESSFUNCTION => null,
129
+ ];
130
+ curl_setopt_array($handle, $unsetValues);
131
+ curl_reset($handle);
132
+ $this->ownedHandles[$id] = false;
133
+ }
134
+ }
135
+ }
vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Future\FutureArray;
5
+ use React\Promise\Deferred;
6
+
7
+ /**
8
+ * Returns an asynchronous response using curl_multi_* functions.
9
+ *
10
+ * This handler supports future responses and the "delay" request client
11
+ * option that can be used to delay before sending a request.
12
+ *
13
+ * When using the CurlMultiHandler, custom curl options can be specified as an
14
+ * associative array of curl option constants mapping to values in the
15
+ * **curl** key of the "client" key of the request.
16
+ *
17
+ * @property resource $_mh Internal use only. Lazy loaded multi-handle.
18
+ */
19
+ class CurlMultiHandler
20
+ {
21
+ /** @var callable */
22
+ private $factory;
23
+ private $selectTimeout;
24
+ private $active;
25
+ private $handles = [];
26
+ private $delays = [];
27
+ private $maxHandles;
28
+
29
+ /**
30
+ * This handler accepts the following options:
31
+ *
32
+ * - mh: An optional curl_multi resource
33
+ * - handle_factory: An optional callable used to generate curl handle
34
+ * resources. the callable accepts a request hash and returns an array
35
+ * of the handle, headers file resource, and the body resource.
36
+ * - select_timeout: Optional timeout (in seconds) to block before timing
37
+ * out while selecting curl handles. Defaults to 1 second.
38
+ * - max_handles: Optional integer representing the maximum number of
39
+ * open requests. When this number is reached, the queued futures are
40
+ * flushed.
41
+ *
42
+ * @param array $options
43
+ */
44
+ public function __construct(array $options = [])
45
+ {
46
+ if (isset($options['mh'])) {
47
+ $this->_mh = $options['mh'];
48
+ }
49
+ $this->factory = isset($options['handle_factory'])
50
+ ? $options['handle_factory'] : new CurlFactory();
51
+ $this->selectTimeout = isset($options['select_timeout'])
52
+ ? $options['select_timeout'] : 1;
53
+ $this->maxHandles = isset($options['max_handles'])
54
+ ? $options['max_handles'] : 100;
55
+ }
56
+
57
+ public function __get($name)
58
+ {
59
+ if ($name === '_mh') {
60
+ return $this->_mh = curl_multi_init();
61
+ }
62
+
63
+ throw new \BadMethodCallException();
64
+ }
65
+
66
+ public function __destruct()
67
+ {
68
+ // Finish any open connections before terminating the script.
69
+ if ($this->handles) {
70
+ $this->execute();
71
+ }
72
+
73
+ if (isset($this->_mh)) {
74
+ curl_multi_close($this->_mh);
75
+ unset($this->_mh);
76
+ }
77
+ }
78
+
79
+ public function __invoke(array $request)
80
+ {
81
+ $factory = $this->factory;
82
+ $result = $factory($request);
83
+ $entry = [
84
+ 'request' => $request,
85
+ 'response' => [],
86
+ 'handle' => $result[0],
87
+ 'headers' => &$result[1],
88
+ 'body' => $result[2],
89
+ 'deferred' => new Deferred(),
90
+ ];
91
+
92
+ $id = (int) $result[0];
93
+
94
+ $future = new FutureArray(
95
+ $entry['deferred']->promise(),
96
+ [$this, 'execute'],
97
+ function () use ($id) {
98
+ return $this->cancel($id);
99
+ }
100
+ );
101
+
102
+ $this->addRequest($entry);
103
+
104
+ // Transfer outstanding requests if there are too many open handles.
105
+ if (count($this->handles) >= $this->maxHandles) {
106
+ $this->execute();
107
+ }
108
+
109
+ return $future;
110
+ }
111
+
112
+ /**
113
+ * Runs until all outstanding connections have completed.
114
+ */
115
+ public function execute()
116
+ {
117
+ do {
118
+
119
+ if ($this->active &&
120
+ curl_multi_select($this->_mh, $this->selectTimeout) === -1
121
+ ) {
122
+ // Perform a usleep if a select returns -1.
123
+ // See: https://bugs.php.net/bug.php?id=61141
124
+ usleep(250);
125
+ }
126
+
127
+ // Add any delayed futures if needed.
128
+ if ($this->delays) {
129
+ $this->addDelays();
130
+ }
131
+
132
+ do {
133
+ $mrc = curl_multi_exec($this->_mh, $this->active);
134
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
135
+
136
+ $this->processMessages();
137
+
138
+ // If there are delays but no transfers, then sleep for a bit.
139
+ if (!$this->active && $this->delays) {
140
+ usleep(500);
141
+ }
142
+
143
+ } while ($this->active || $this->handles);
144
+ }
145
+
146
+ private function addRequest(array &$entry)
147
+ {
148
+ $id = (int) $entry['handle'];
149
+ $this->handles[$id] = $entry;
150
+
151
+ // If the request is a delay, then add the reques to the curl multi
152
+ // pool only after the specified delay.
153
+ if (isset($entry['request']['client']['delay'])) {
154
+ $this->delays[$id] = microtime(true) + ($entry['request']['client']['delay'] / 1000);
155
+ } elseif (empty($entry['request']['future'])) {
156
+ curl_multi_add_handle($this->_mh, $entry['handle']);
157
+ } else {
158
+ curl_multi_add_handle($this->_mh, $entry['handle']);
159
+ // "lazy" futures are only sent once the pool has many requests.
160
+ if ($entry['request']['future'] !== 'lazy') {
161
+ do {
162
+ $mrc = curl_multi_exec($this->_mh, $this->active);
163
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
164
+ $this->processMessages();
165
+ }
166
+ }
167
+ }
168
+
169
+ private function removeProcessed($id)
170
+ {
171
+ if (isset($this->handles[$id])) {
172
+ curl_multi_remove_handle(
173
+ $this->_mh,
174
+ $this->handles[$id]['handle']
175
+ );
176
+ curl_close($this->handles[$id]['handle']);
177
+ unset($this->handles[$id], $this->delays[$id]);
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Cancels a handle from sending and removes references to it.
183
+ *
184
+ * @param int $id Handle ID to cancel and remove.
185
+ *
186
+ * @return bool True on success, false on failure.
187
+ */
188
+ private function cancel($id)
189
+ {
190
+ // Cannot cancel if it has been processed.
191
+ if (!isset($this->handles[$id])) {
192
+ return false;
193
+ }
194
+
195
+ $handle = $this->handles[$id]['handle'];
196
+ unset($this->delays[$id], $this->handles[$id]);
197
+ curl_multi_remove_handle($this->_mh, $handle);
198
+ curl_close($handle);
199
+
200
+ return true;
201
+ }
202
+
203
+ private function addDelays()
204
+ {
205
+ $currentTime = microtime(true);
206
+
207
+ foreach ($this->delays as $id => $delay) {
208
+ if ($currentTime >= $delay) {
209
+ unset($this->delays[$id]);
210
+ curl_multi_add_handle(
211
+ $this->_mh,
212
+ $this->handles[$id]['handle']
213
+ );
214
+ }
215
+ }
216
+ }
217
+
218
+ private function processMessages()
219
+ {
220
+ while ($done = curl_multi_info_read($this->_mh)) {
221
+ $id = (int) $done['handle'];
222
+
223
+ if (!isset($this->handles[$id])) {
224
+ // Probably was cancelled.
225
+ continue;
226
+ }
227
+
228
+ $entry = $this->handles[$id];
229
+ $entry['response']['transfer_stats'] = curl_getinfo($done['handle']);
230
+
231
+ if ($done['result'] !== CURLM_OK) {
232
+ $entry['response']['curl']['errno'] = $done['result'];
233
+ $entry['response']['curl']['error'] = curl_error($done['handle']);
234
+ }
235
+
236
+ $result = CurlFactory::createResponse(
237
+ $this,
238
+ $entry['request'],
239
+ $entry['response'],
240
+ $entry['headers'],
241
+ $entry['body']
242
+ );
243
+
244
+ $this->removeProcessed($id);
245
+ $entry['deferred']->resolve($result);
246
+ }
247
+ }
248
+ }
vendor/guzzlehttp/ringphp/src/Client/Middleware.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Client;
3
+
4
+ /**
5
+ * Provides basic middleware wrappers.
6
+ *
7
+ * If a middleware is more complex than a few lines of code, then it should
8
+ * be implemented in a class rather than a static method.
9
+ */
10
+ class Middleware
11
+ {
12
+ /**
13
+ * Sends future requests to a future compatible handler while sending all
14
+ * other requests to a default handler.
15
+ *
16
+ * When the "future" option is not provided on a request, any future responses
17
+ * are automatically converted to synchronous responses and block.
18
+ *
19
+ * @param callable $default Handler used for non-streaming responses
20
+ * @param callable $future Handler used for future responses
21
+ *
22
+ * @return callable Returns the composed handler.
23
+ */
24
+ public static function wrapFuture(
25
+ callable $default,
26
+ callable $future
27
+ ) {
28
+ return function (array $request) use ($default, $future) {
29
+ return empty($request['client']['future'])
30
+ ? $default($request)
31
+ : $future($request);
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Sends streaming requests to a streaming compatible handler while sendin
37
+ * all other requests to a default handler.
38
+ *
39
+ * This, for example, could be useful for taking advantage of the
40
+ * performance benefits of curl while still supporting true streaming
41
+ * through the StreamHandler.
42
+ *
43
+ * @param callable $default Handler used for non-streaming responses
44
+ * @param callable $streaming Handler used for streaming responses
45
+ *
46
+ * @return callable Returns the composed handler.
47
+ */
48
+ public static function wrapStreaming(
49
+ callable $default,
50
+ callable $streaming
51
+ ) {
52
+ return function (array $request) use ($default, $streaming) {
53
+ return empty($request['client']['stream'])
54
+ ? $default($request)
55
+ : $streaming($request);
56
+ };
57
+ }
58
+ }
vendor/guzzlehttp/ringphp/src/Client/MockHandler.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Core;
5
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
6
+ use GuzzleHttp\Ring\Future\FutureArrayInterface;
7
+
8
+ /**
9
+ * Ring handler that returns a canned response or evaluated function result.
10
+ */
11
+ class MockHandler
12
+ {
13
+ /** @var callable|array|FutureArrayInterface */
14
+ private $result;
15
+
16
+ /**
17
+ * Provide an array or future to always return the same value. Provide a
18
+ * callable that accepts a request object and returns an array or future
19
+ * to dynamically create a response.
20
+ *
21
+ * @param array|FutureArrayInterface|callable $result Mock return value.
22
+ */
23
+ public function __construct($result)
24
+ {
25
+ $this->result = $result;
26
+ }
27
+
28
+ public function __invoke(array $request)
29
+ {
30
+ Core::doSleep($request);
31
+ $response = is_callable($this->result)
32
+ ? call_user_func($this->result, $request)
33
+ : $this->result;
34
+
35
+ if (is_array($response)) {
36
+ $response = new CompletedFutureArray($response + [
37
+ 'status' => null,
38
+ 'body' => null,
39
+ 'headers' => [],
40
+ 'reason' => null,
41
+ 'effective_url' => null,
42
+ ]);
43
+ } elseif (!$response instanceof FutureArrayInterface) {
44
+ throw new \InvalidArgumentException(
45
+ 'Response must be an array or FutureArrayInterface. Found '
46
+ . Core::describeType($request)
47
+ );
48
+ }
49
+
50
+ return $response;
51
+ }
52
+ }
vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Core;
5
+ use GuzzleHttp\Ring\Exception\ConnectException;
6
+ use GuzzleHttp\Ring\Exception\RingException;
7
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
8
+ use GuzzleHttp\Stream\InflateStream;
9
+ use GuzzleHttp\Stream\StreamInterface;
10
+ use GuzzleHttp\Stream\Stream;
11
+ use GuzzleHttp\Stream\Utils;
12
+
13
+ /**
14
+ * RingPHP client handler that uses PHP's HTTP stream wrapper.
15
+ */
16
+ class StreamHandler
17
+ {
18
+ private $options;
19
+ private $lastHeaders;
20
+
21
+ public function __construct(array $options = [])
22
+ {
23
+ $this->options = $options;
24
+ }
25
+
26
+ public function __invoke(array $request)
27
+ {
28
+ $url = Core::url($request);
29
+ Core::doSleep($request);
30
+
31
+ try {
32
+ // Does not support the expect header.
33
+ $request = Core::removeHeader($request, 'Expect');
34
+ $stream = $this->createStream($url, $request);
35
+ return $this->createResponse($request, $url, $stream);
36
+ } catch (RingException $e) {
37
+ return $this->createErrorResponse($url, $e);
38
+ }
39
+ }
40
+
41
+ private function createResponse(array $request, $url, $stream)
42
+ {
43
+ $hdrs = $this->lastHeaders;
44
+ $this->lastHeaders = null;
45
+ $parts = explode(' ', array_shift($hdrs), 3);
46
+ $response = [
47
+ 'version' => substr($parts[0], 5),
48
+ 'status' => $parts[1],
49
+ 'reason' => isset($parts[2]) ? $parts[2] : null,
50
+ 'headers' => Core::headersFromLines($hdrs),
51
+ 'effective_url' => $url,
52
+ ];
53
+
54
+ $stream = $this->checkDecode($request, $response, $stream);
55
+
56
+ // If not streaming, then drain the response into a stream.
57
+ if (empty($request['client']['stream'])) {
58
+ $dest = isset($request['client']['save_to'])
59
+ ? $request['client']['save_to']
60
+ : fopen('php://temp', 'r+');
61
+ $stream = $this->drain($stream, $dest);
62
+ }
63
+
64
+ $response['body'] = $stream;
65
+
66
+ return new CompletedFutureArray($response);
67
+ }
68
+
69
+ private function checkDecode(array $request, array $response, $stream)
70
+ {
71
+ // Automatically decode responses when instructed.
72
+ if (!empty($request['client']['decode_content'])) {
73
+ switch (Core::firstHeader($response, 'Content-Encoding', true)) {
74
+ case 'gzip':
75
+ case 'deflate':
76
+ $stream = new InflateStream(Stream::factory($stream));
77
+ break;
78
+ }
79
+ }
80
+
81
+ return $stream;
82
+ }
83
+
84
+ /**
85
+ * Drains the stream into the "save_to" client option.
86
+ *
87
+ * @param resource $stream
88
+ * @param string|resource|StreamInterface $dest
89
+ *
90
+ * @return Stream
91
+ * @throws \RuntimeException when the save_to option is invalid.
92
+ */
93
+ private function drain($stream, $dest)
94
+ {
95
+ if (is_resource($stream)) {
96
+ if (!is_resource($dest)) {
97
+ $stream = Stream::factory($stream);
98
+ } else {
99
+ stream_copy_to_stream($stream, $dest);
100
+ fclose($stream);
101
+ rewind($dest);
102
+ return $dest;
103
+ }
104
+ }
105
+
106
+ // Stream the response into the destination stream
107
+ $dest = is_string($dest)
108
+ ? new Stream(Utils::open($dest, 'r+'))
109
+ : Stream::factory($dest);
110
+
111
+ Utils::copyToStream($stream, $dest);
112
+ $dest->seek(0);
113
+ $stream->close();
114
+
115
+ return $dest;
116
+ }
117
+
118
+ /**
119
+ * Creates an error response for the given stream.
120
+ *
121
+ * @param string $url
122
+ * @param RingException $e
123
+ *
124
+ * @return array
125
+ */
126
+ private function createErrorResponse($url, RingException $e)
127
+ {
128
+ // Determine if the error was a networking error.
129
+ $message = $e->getMessage();
130
+
131
+ // This list can probably get more comprehensive.
132
+ if (strpos($message, 'getaddrinfo') // DNS lookup failed
133
+ || strpos($message, 'Connection refused')
134
+ ) {
135
+ $e = new ConnectException($e->getMessage(), 0, $e);
136
+ }
137
+
138
+ return new CompletedFutureArray([
139
+ 'status' => null,
140
+ 'body' => null,
141
+ 'headers' => [],
142
+ 'effective_url' => $url,
143
+ 'error' => $e
144
+ ]);
145
+ }
146
+
147
+ /**
148
+ * Create a resource and check to ensure it was created successfully
149
+ *
150
+ * @param callable $callback Callable that returns stream resource
151
+ *
152
+ * @return resource
153
+ * @throws \RuntimeException on error
154
+ */
155
+ private function createResource(callable $callback)
156
+ {
157
+ $errors = null;
158
+ set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
159
+ $errors[] = [
160
+ 'message' => $msg,
161
+ 'file' => $file,
162
+ 'line' => $line
163
+ ];
164
+ return true;
165
+ });
166
+
167
+ $resource = $callback();
168
+ restore_error_handler();
169
+
170
+ if (!$resource) {
171
+ $message = 'Error creating resource: ';
172
+ foreach ($errors as $err) {
173
+ foreach ($err as $key => $value) {
174
+ $message .= "[$key] $value" . PHP_EOL;
175
+ }
176
+ }
177
+ throw new RingException(trim($message));
178
+ }
179
+
180
+ return $resource;
181
+ }
182
+
183
+ private function createStream($url, array $request)
184
+ {
185
+ static $methods;
186
+ if (!$methods) {
187
+ $methods = array_flip(get_class_methods(__CLASS__));
188
+ }
189
+
190
+ // HTTP/1.1 streams using the PHP stream wrapper require a
191
+ // Connection: close header
192
+ if ((!isset($request['version']) || $request['version'] == '1.1')
193
+ && !Core::hasHeader($request, 'Connection')
194
+ ) {
195
+ $request['headers']['Connection'] = ['close'];
196
+ }
197
+
198
+ // Ensure SSL is verified by default
199
+ if (!isset($request['client']['verify'])) {
200
+ $request['client']['verify'] = true;
201
+ }
202
+
203
+ $params = [];
204
+ $options = $this->getDefaultOptions($request);
205
+
206
+ if (isset($request['client'])) {
207
+ foreach ($request['client'] as $key => $value) {
208
+ $method = "add_{$key}";
209
+ if (isset($methods[$method])) {
210
+ $this->{$method}($request, $options, $value, $params);
211
+ }
212
+ }
213
+ }
214
+
215
+ return $this->createStreamResource(
216
+ $url,
217
+ $request,
218
+ $options,
219
+ $this->createContext($request, $options, $params)
220
+ );
221
+ }
222
+
223
+ private function getDefaultOptions(array $request)
224
+ {
225
+ $headers = "";
226
+ foreach ($request['headers'] as $name => $value) {
227
+ foreach ((array) $value as $val) {
228
+ $headers .= "$name: $val\r\n";
229
+ }
230
+ }
231
+
232
+ $context = [
233
+ 'http' => [
234
+ 'method' => $request['http_method'],
235
+ 'header' => $headers,
236
+ 'protocol_version' => isset($request['version']) ? $request['version'] : 1.1,
237
+ 'ignore_errors' => true,
238
+ 'follow_location' => 0,
239
+ ],
240
+ ];
241
+
242
+ $body = Core::body($request);
243
+ if (isset($body)) {
244
+ $context['http']['content'] = $body;
245
+ // Prevent the HTTP handler from adding a Content-Type header.
246
+ if (!Core::hasHeader($request, 'Content-Type')) {
247
+ $context['http']['header'] .= "Content-Type:\r\n";
248
+ }
249
+ }
250
+
251
+ $context['http']['header'] = rtrim($context['http']['header']);
252
+
253
+ return $context;
254
+ }
255
+
256
+ private function add_proxy(array $request, &$options, $value, &$params)
257
+ {
258
+ if (!is_array($value)) {
259
+ $options['http']['proxy'] = $value;
260
+ } else {
261
+ $scheme = isset($request['scheme']) ? $request['scheme'] : 'http';
262
+ if (isset($value[$scheme])) {
263
+ $options['http']['proxy'] = $value[$scheme];
264
+ }
265
+ }
266
+ }
267
+
268
+ private function add_timeout(array $request, &$options, $value, &$params)
269
+ {
270
+ $options['http']['timeout'] = $value;
271
+ }
272
+
273
+ private function add_verify(array $request, &$options, $value, &$params)
274
+ {
275
+ if ($value === true) {
276
+ // PHP 5.6 or greater will find the system cert by default. When
277
+ // < 5.6, use the Guzzle bundled cacert.
278
+ if (PHP_VERSION_ID < 50600) {
279
+ $options['ssl']['cafile'] = ClientUtils::getDefaultCaBundle();
280
+ }
281
+ } elseif (is_string($value)) {
282
+ $options['ssl']['cafile'] = $value;
283
+ if (!file_exists($value)) {
284
+ throw new RingException("SSL CA bundle not found: $value");
285
+ }
286
+ } elseif ($value === false) {
287
+ $options['ssl']['verify_peer'] = false;
288
+ $options['ssl']['allow_self_signed'] = true;
289
+ return;
290
+ } else {
291
+ throw new RingException('Invalid verify request option');
292
+ }
293
+
294
+ $options['ssl']['verify_peer'] = true;
295
+ $options['ssl']['allow_self_signed'] = false;
296
+ }
297
+
298
+ private function add_cert(array $request, &$options, $value, &$params)
299
+ {
300
+ if (is_array($value)) {
301
+ $options['ssl']['passphrase'] = $value[1];
302
+ $value = $value[0];
303
+ }
304
+
305
+ if (!file_exists($value)) {
306
+ throw new RingException("SSL certificate not found: {$value}");
307
+ }
308
+
309
+ $options['ssl']['local_cert'] = $value;
310
+ }
311
+
312
+ private function add_progress(array $request, &$options, $value, &$params)
313
+ {
314
+ $fn = function ($code, $_1, $_2, $_3, $transferred, $total) use ($value) {
315
+ if ($code == STREAM_NOTIFY_PROGRESS) {
316
+ $value($total, $transferred, null, null);
317
+ }
318
+ };
319
+
320
+ // Wrap the existing function if needed.
321
+ $params['notification'] = isset($params['notification'])
322
+ ? Core::callArray([$params['notification'], $fn])
323
+ : $fn;
324
+ }
325
+
326
+ private function add_debug(array $request, &$options, $value, &$params)
327
+ {
328
+ if ($value === false) {
329
+ return;
330
+ }
331
+
332
+ static $map = [
333
+ STREAM_NOTIFY_CONNECT => 'CONNECT',
334
+ STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
335
+ STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
336
+ STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
337
+ STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
338
+ STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
339
+ STREAM_NOTIFY_PROGRESS => 'PROGRESS',
340
+ STREAM_NOTIFY_FAILURE => 'FAILURE',
341
+ STREAM_NOTIFY_COMPLETED => 'COMPLETED',
342
+ STREAM_NOTIFY_RESOLVE => 'RESOLVE',
343
+ ];
344
+
345
+ static $args = ['severity', 'message', 'message_code',
346
+ 'bytes_transferred', 'bytes_max'];
347
+
348
+ $value = Core::getDebugResource($value);
349
+ $ident = $request['http_method'] . ' ' . Core::url($request);
350
+ $fn = function () use ($ident, $value, $map, $args) {
351
+ $passed = func_get_args();
352
+ $code = array_shift($passed);
353
+ fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
354
+ foreach (array_filter($passed) as $i => $v) {
355
+ fwrite($value, $args[$i] . ': "' . $v . '" ');
356
+ }
357
+ fwrite($value, "\n");
358
+ };
359
+
360
+ // Wrap the existing function if needed.
361
+ $params['notification'] = isset($params['notification'])
362
+ ? Core::callArray([$params['notification'], $fn])
363
+ : $fn;
364
+ }
365
+
366
+ private function applyCustomOptions(array $request, array &$options)
367
+ {
368
+ if (!isset($request['client']['stream_context'])) {
369
+ return;
370
+ }
371
+
372
+ if (!is_array($request['client']['stream_context'])) {
373
+ throw new RingException('stream_context must be an array');
374
+ }
375
+
376
+ $options = array_replace_recursive(
377
+ $options,
378
+ $request['client']['stream_context']
379
+ );
380
+ }
381
+
382
+ private function createContext(array $request, array $options, array $params)
383
+ {
384
+ $this->applyCustomOptions($request, $options);
385
+ return $this->createResource(
386
+ function () use ($request, $options, $params) {
387
+ return stream_context_create($options, $params);
388
+ },
389
+ $request,
390
+ $options
391
+ );
392
+ }
393
+
394
+ private function createStreamResource(
395
+ $url,
396
+ array $request,
397
+ array $options,
398
+ $context
399
+ ) {
400
+ return $this->createResource(
401
+ function () use ($url, $context) {
402
+ if (false === strpos($url, 'http')) {
403
+ trigger_error("URL is invalid: {$url}", E_USER_WARNING);
404
+ return null;
405
+ }
406
+ $resource = fopen($url, 'r', null, $context);
407
+ $this->lastHeaders = $http_response_header;
408
+ return $resource;
409
+ },
410
+ $request,
411
+ $options
412
+ );
413
+ }
414
+ }
vendor/guzzlehttp/ringphp/src/Core.php ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring;
3
+
4
+ use GuzzleHttp\Stream\StreamInterface;
5
+ use GuzzleHttp\Ring\Future\FutureArrayInterface;
6
+ use GuzzleHttp\Ring\Future\FutureArray;
7
+
8
+ /**
9
+ * Provides core functionality of Ring handlers and middleware.
10
+ */
11
+ class Core
12
+ {
13
+ /**
14
+ * Returns a function that calls all of the provided functions, in order,
15
+ * passing the arguments provided to the composed function to each function.
16
+ *
17
+ * @param callable[] $functions Array of functions to proxy to.
18
+ *
19
+ * @return callable
20
+ */
21
+ public static function callArray(array $functions)
22
+ {
23
+ return function () use ($functions) {
24
+ $args = func_get_args();
25
+ foreach ($functions as $fn) {
26
+ call_user_func_array($fn, $args);
27
+ }
28
+ };
29
+ }
30
+
31
+ /**
32
+ * Gets an array of header line values from a message for a specific header
33
+ *
34
+ * This method searches through the "headers" key of a message for a header
35
+ * using a case-insensitive search.
36
+ *
37
+ * @param array $message Request or response hash.
38
+ * @param string $header Header to retrieve
39
+ *
40
+ * @return array
41
+ */
42
+ public static function headerLines($message, $header)
43
+ {
44
+ $result = [];
45
+
46
+ if (!empty($message['headers'])) {
47
+ foreach ($message['headers'] as $name => $value) {
48
+ if (!strcasecmp($name, $header)) {
49
+ $result = array_merge($result, $value);
50
+ }
51
+ }
52
+ }
53
+
54
+ return $result;
55
+ }
56
+
57
+ /**
58
+ * Gets a header value from a message as a string or null
59
+ *
60
+ * This method searches through the "headers" key of a message for a header
61
+ * using a case-insensitive search. The lines of the header are imploded
62
+ * using commas into a single string return value.
63
+ *
64
+ * @param array $message Request or response hash.
65
+ * @param string $header Header to retrieve
66
+ *
67
+ * @return string|null Returns the header string if found, or null if not.
68
+ */
69
+ public static function header($message, $header)
70
+ {
71
+ $match = self::headerLines($message, $header);
72
+ return $match ? implode(', ', $match) : null;
73
+ }
74
+
75
+ /**
76
+ * Returns the first header value from a message as a string or null. If
77
+ * a header line contains multiple values separated by a comma, then this
78
+ * function will return the first value in the list.
79
+ *
80
+ * @param array $message Request or response hash.
81
+ * @param string $header Header to retrieve
82
+ *
83
+ * @return string|null Returns the value as a string if found.
84
+ */
85
+ public static function firstHeader($message, $header)
86
+ {
87
+ if (!empty($message['headers'])) {
88
+ foreach ($message['headers'] as $name => $value) {
89
+ if (!strcasecmp($name, $header)) {
90
+ // Return the match itself if it is a single value.
91
+ $pos = strpos($value[0], ',');
92
+ return $pos ? substr($value[0], 0, $pos) : $value[0];
93
+ }
94
+ }
95
+ }
96
+
97
+ return null;
98
+ }
99
+
100
+ /**
101
+ * Returns true if a message has the provided case-insensitive header.
102
+ *
103
+ * @param array $message Request or response hash.
104
+ * @param string $header Header to check
105
+ *
106
+ * @return bool
107
+ */
108
+ public static function hasHeader($message, $header)
109
+ {
110
+ if (!empty($message['headers'])) {
111
+ foreach ($message['headers'] as $name => $value) {
112
+ if (!strcasecmp($name, $header)) {
113
+ return true;
114
+ }
115
+ }
116
+ }
117
+
118
+ return false;
119
+ }
120
+
121
+ /**
122
+ * Parses an array of header lines into an associative array of headers.
123
+ *
124
+ * @param array $lines Header lines array of strings in the following
125
+ * format: "Name: Value"
126
+ * @return array
127
+ */
128
+ public static function headersFromLines($lines)
129
+ {
130
+ $headers = [];
131
+
132
+ foreach ($lines as $line) {
133
+ $parts = explode(':', $line, 2);
134
+ $headers[trim($parts[0])][] = isset($parts[1])
135
+ ? trim($parts[1])
136
+ : null;
137
+ }
138
+
139
+ return $headers;
140
+ }
141
+
142
+ /**
143
+ * Removes a header from a message using a case-insensitive comparison.
144
+ *
145
+ * @param array $message Message that contains 'headers'
146
+ * @param string $header Header to remove
147
+ *
148
+ * @return array
149
+ */
150
+ public static function removeHeader(array $message, $header)
151
+ {
152
+ if (isset($message['headers'])) {
153
+ foreach (array_keys($message['headers']) as $key) {
154
+ if (!strcasecmp($header, $key)) {
155
+ unset($message['headers'][$key]);
156
+ }
157
+ }
158
+ }
159
+
160
+ return $message;
161
+ }
162
+
163
+ /**
164
+ * Replaces any existing case insensitive headers with the given value.
165
+ *
166
+ * @param array $message Message that contains 'headers'
167
+ * @param string $header Header to set.
168
+ * @param array $value Value to set.
169
+ *
170
+ * @return array
171
+ */
172
+ public static function setHeader(array $message, $header, array $value)
173
+ {
174
+ $message = self::removeHeader($message, $header);
175
+ $message['headers'][$header] = $value;
176
+
177
+ return $message;
178
+ }
179
+
180
+ /**
181
+ * Creates a URL string from a request.
182
+ *
183
+ * If the "url" key is present on the request, it is returned, otherwise
184
+ * the url is built up based on the scheme, host, uri, and query_string
185
+ * request values.
186
+ *
187
+ * @param array $request Request to get the URL from
188
+ *
189
+ * @return string Returns the request URL as a string.
190
+ * @throws \InvalidArgumentException if no Host header is present.
191
+ */
192
+ public static function url(array $request)
193
+ {
194
+ if (isset($request['url'])) {
195
+ return $request['url'];
196
+ }
197
+
198
+ $uri = (isset($request['scheme'])
199
+ ? $request['scheme'] : 'http') . '://';
200
+
201
+ if ($host = self::header($request, 'host')) {
202
+ $uri .= $host;
203
+ } else {
204
+ throw new \InvalidArgumentException('No Host header was provided');
205
+ }
206
+
207
+ if (isset($request['uri'])) {
208
+ $uri .= $request['uri'];
209
+ }
210
+
211
+ if (isset($request['query_string'])) {
212
+ $uri .= '?' . $request['query_string'];
213
+ }
214
+
215
+ return $uri;
216
+ }
217
+
218
+ /**
219
+ * Reads the body of a message into a string.
220
+ *
221
+ * @param array|FutureArrayInterface $message Array containing a "body" key
222
+ *
223
+ * @return null|string Returns the body as a string or null if not set.
224
+ * @throws \InvalidArgumentException if a request body is invalid.
225
+ */
226
+ public static function body($message)
227
+ {
228
+ if (!isset($message['body'])) {
229
+ return null;
230
+ }
231
+
232
+ if ($message['body'] instanceof StreamInterface) {
233
+ return (string) $message['body'];
234
+ }
235
+
236
+ switch (gettype($message['body'])) {
237
+ case 'string':
238
+ return $message['body'];
239
+ case 'resource':
240
+ return stream_get_contents($message['body']);
241
+ case 'object':
242
+ if ($message['body'] instanceof \Iterator) {
243
+ return implode('', iterator_to_array($message['body']));
244
+ } elseif (method_exists($message['body'], '__toString')) {
245
+ return (string) $message['body'];
246
+ }
247
+ default:
248
+ throw new \InvalidArgumentException('Invalid request body: '
249
+ . self::describeType($message['body']));
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Rewind the body of the provided message if possible.
255
+ *
256
+ * @param array $message Message that contains a 'body' field.
257
+ *
258
+ * @return bool Returns true on success, false on failure
259
+ */
260
+ public static function rewindBody($message)
261
+ {
262
+ if ($message['body'] instanceof StreamInterface) {
263
+ return $message['body']->seek(0);
264
+ }
265
+
266
+ if ($message['body'] instanceof \Generator) {
267
+ return false;
268
+ }
269
+
270
+ if ($message['body'] instanceof \Iterator) {
271
+ $message['body']->rewind();
272
+ return true;
273
+ }
274
+
275
+ if (is_resource($message['body'])) {
276
+ return rewind($message['body']);
277
+ }
278
+
279
+ return is_string($message['body'])
280
+ || (is_object($message['body'])
281
+ && method_exists($message['body'], '__toString'));
282
+ }
283
+
284
+ /**
285
+ * Debug function used to describe the provided value type and class.
286
+ *
287
+ * @param mixed $input
288
+ *
289
+ * @return string Returns a string containing the type of the variable and
290
+ * if a class is provided, the class name.
291
+ */
292
+ public static function describeType($input)
293
+ {
294
+ switch (gettype($input)) {
295
+ case 'object':
296
+ return 'object(' . get_class($input) . ')';
297
+ case 'array':
298
+ return 'array(' . count($input) . ')';
299
+ default:
300
+ ob_start();
301
+ var_dump($input);
302
+ // normalize float vs double
303
+ return str_replace('double(', 'float(', rtrim(ob_get_clean()));
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Sleep for the specified amount of time specified in the request's
309
+ * ['client']['delay'] option if present.
310
+ *
311
+ * This function should only be used when a non-blocking sleep is not
312
+ * possible.
313
+ *
314
+ * @param array $request Request to sleep
315
+ */
316
+ public static function doSleep(array $request)
317
+ {
318
+ if (isset($request['client']['delay'])) {
319
+ usleep($request['client']['delay'] * 1000);
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Returns a proxied future that modifies the dereferenced value of another
325
+ * future using a promise.
326
+ *
327
+ * @param FutureArrayInterface $future Future to wrap with a new future
328
+ * @param callable $onFulfilled Invoked when the future fulfilled
329
+ * @param callable $onRejected Invoked when the future rejected
330
+ * @param callable $onProgress Invoked when the future progresses
331
+ *
332
+ * @return FutureArray
333
+ */
334
+ public static function proxy(
335
+ FutureArrayInterface $future,
336
+ callable $onFulfilled = null,
337
+ callable $onRejected = null,
338
+ callable $onProgress = null
339
+ ) {
340
+ return new FutureArray(
341
+ $future->then($onFulfilled, $onRejected, $onProgress),
342
+ [$future, 'wait'],
343
+ [$future, 'cancel']
344
+ );
345
+ }
346
+
347
+ /**
348
+ * Returns a debug stream based on the provided variable.
349
+ *
350
+ * @param mixed $value Optional value
351
+ *
352
+ * @return resource
353
+ */
354
+ public static function getDebugResource($value = null)
355
+ {
356
+ if (is_resource($value)) {
357
+ return $value;
358
+ } elseif (defined('STDOUT')) {
359
+ return STDOUT;
360
+ } else {
361
+ return fopen('php://output', 'w');
362
+ }
363
+ }
364
+ }
vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Exception;
3
+
4
+ /**
5
+ * Marker interface for cancelled exceptions.
6
+ */
7
+ interface CancelledException {}
vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Exception;
3
+
4
+ class CancelledFutureAccessException extends RingException implements CancelledException {}
vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Exception;
3
+
4
+ /**
5
+ * Occurs when the connection failed.
6
+ */
7
+ class ConnectException extends RingException {}
vendor/guzzlehttp/ringphp/src/Exception/RingException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Exception;
3
+
4
+ class RingException extends \RuntimeException {};
vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
5
+ use GuzzleHttp\Ring\Exception\RingException;
6
+ use React\Promise\PromiseInterface;
7
+
8
+ /**
9
+ * Implements common future functionality built on top of promises.
10
+ */
11
+ trait BaseFutureTrait
12
+ {
13
+ /** @var callable */
14
+ private $waitfn;
15
+
16
+ /** @var callable */
17
+ private $cancelfn;
18
+
19
+ /** @var PromiseInterface */
20
+ private $wrappedPromise;
21
+
22
+ /** @var \Exception Error encountered. */
23
+ private $error;
24
+
25
+ /** @var mixed Result of the future */
26
+ private $result;
27
+
28
+ private $isRealized = false;
29
+
30
+ /**
31
+ * @param PromiseInterface $promise Promise to shadow with the future.
32
+ * @param callable $wait Function that blocks until the deferred
33
+ * computation has been resolved. This
34
+ * function MUST resolve the deferred value
35
+ * associated with the supplied promise.
36
+ * @param callable $cancel If possible and reasonable, provide a
37
+ * function that can be used to cancel the
38
+ * future from completing.
39
+ */
40
+ public function __construct(
41
+ PromiseInterface $promise,
42
+ callable $wait = null,
43
+ callable $cancel = null
44
+ ) {
45
+ $this->wrappedPromise = $promise;
46
+ $this->waitfn = $wait;
47
+ $this->cancelfn = $cancel;
48
+ }
49
+
50
+ public function wait()
51
+ {
52
+ if (!$this->isRealized) {
53
+ $this->addShadow();
54
+ if (!$this->isRealized && $this->waitfn) {
55
+ $this->invokeWait();
56
+ }
57
+ if (!$this->isRealized) {
58
+ $this->error = new RingException('Waiting did not resolve future');
59
+ }
60
+ }
61
+
62
+ if ($this->error) {
63
+ throw $this->error;
64
+ }
65
+
66
+ return $this->result;
67
+ }
68
+
69
+ public function promise()
70
+ {
71
+ return $this->wrappedPromise;
72
+ }
73
+
74
+ public function then(
75
+ callable $onFulfilled = null,
76
+ callable $onRejected = null,
77
+ callable $onProgress = null
78
+ ) {
79
+ return $this->wrappedPromise->then($onFulfilled, $onRejected, $onProgress);
80
+ }
81
+
82
+ public function cancel()
83
+ {
84
+ if (!$this->isRealized) {
85
+ $cancelfn = $this->cancelfn;
86
+ $this->waitfn = $this->cancelfn = null;
87
+ $this->isRealized = true;
88
+ $this->error = new CancelledFutureAccessException();
89
+ if ($cancelfn) {
90
+ $cancelfn($this);
91
+ }
92
+ }
93
+ }
94
+
95
+ private function addShadow()
96
+ {
97
+ // Get the result and error when the promise is resolved. Note that
98
+ // calling this function might trigger the resolution immediately.
99
+ $this->wrappedPromise->then(
100
+ function ($value) {
101
+ $this->isRealized = true;
102
+ $this->result = $value;
103
+ $this->waitfn = $this->cancelfn = null;
104
+ },
105
+ function ($error) {
106
+ $this->isRealized = true;
107
+ $this->error = $error;
108
+ $this->waitfn = $this->cancelfn = null;
109
+ }
110
+ );
111
+ }
112
+
113
+ private function invokeWait()
114
+ {
115
+ try {
116
+ $wait = $this->waitfn;
117
+ $this->waitfn = null;
118
+ $wait();
119
+ } catch (\Exception $e) {
120
+ // Defer can throw to reject.
121
+ $this->error = $e;
122
+ $this->isRealized = true;
123
+ }
124
+ }
125
+ }
vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ /**
5
+ * Represents a future array that has been completed successfully.
6
+ */
7
+ class CompletedFutureArray extends CompletedFutureValue implements FutureArrayInterface
8
+ {
9
+ public function __construct(array $result)
10
+ {
11
+ parent::__construct($result);
12
+ }
13
+
14
+ public function offsetExists($offset)
15
+ {
16
+ return isset($this->result[$offset]);
17
+ }
18
+
19
+ public function offsetGet($offset)
20
+ {
21
+ return $this->result[$offset];
22
+ }
23
+
24
+ public function offsetSet($offset, $value)
25
+ {
26
+ $this->result[$offset] = $value;
27
+ }
28
+
29
+ public function offsetUnset($offset)
30
+ {
31
+ unset($this->result[$offset]);
32
+ }
33
+
34
+ public function count()
35
+ {
36
+ return count($this->result);
37
+ }
38
+
39
+ public function getIterator()
40
+ {
41
+ return new \ArrayIterator($this->result);
42
+ }
43
+ }
vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ use React\Promise\FulfilledPromise;
5
+ use React\Promise\RejectedPromise;
6
+
7
+ /**
8
+ * Represents a future value that has been resolved or rejected.
9
+ */
10
+ class CompletedFutureValue implements FutureInterface
11
+ {
12
+ protected $result;
13
+ protected $error;
14
+
15
+ private $cachedPromise;
16
+
17
+ /**
18
+ * @param mixed $result Resolved result
19
+ * @param \Exception $e Error. Pass a GuzzleHttp\Ring\Exception\CancelledFutureAccessException
20
+ * to mark the future as cancelled.
21
+ */
22
+ public function __construct($result, \Exception $e = null)
23
+ {
24
+ $this->result = $result;
25
+ $this->error = $e;
26
+ }
27
+
28
+ public function wait()
29
+ {
30
+ if ($this->error) {
31
+ throw $this->error;
32
+ }
33
+
34
+ return $this->result;
35
+ }
36
+
37
+ public function cancel() {}
38
+
39
+ public function promise()
40
+ {
41
+ if (!$this->cachedPromise) {
42
+ $this->cachedPromise = $this->error
43
+ ? new RejectedPromise($this->error)
44
+ : new FulfilledPromise($this->result);
45
+ }
46
+
47
+ return $this->cachedPromise;
48
+ }
49
+
50
+ public function then(
51
+ callable $onFulfilled = null,
52
+ callable $onRejected = null,
53
+ callable $onProgress = null
54
+ ) {
55
+ return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
56
+ }
57
+ }
vendor/guzzlehttp/ringphp/src/Future/FutureArray.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ /**
5
+ * Represents a future array value that when dereferenced returns an array.
6
+ */
7
+ class FutureArray implements FutureArrayInterface
8
+ {
9
+ use MagicFutureTrait;
10
+
11
+ public function offsetExists($offset)
12
+ {
13
+ return isset($this->_value[$offset]);
14
+ }
15
+
16
+ public function offsetGet($offset)
17
+ {
18
+ return $this->_value[$offset];
19
+ }
20
+
21
+ public function offsetSet($offset, $value)
22
+ {
23
+ $this->_value[$offset] = $value;
24
+ }
25
+
26
+ public function offsetUnset($offset)
27
+ {
28
+ unset($this->_value[$offset]);
29
+ }
30
+
31
+ public function count()
32
+ {
33
+ return count($this->_value);
34
+ }
35
+
36
+ public function getIterator()
37
+ {
38
+ return new \ArrayIterator($this->_value);
39
+ }
40
+ }
vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ /**
5
+ * Future that provides array-like access.
6
+ */
7
+ interface FutureArrayInterface extends
8
+ FutureInterface,
9
+ \ArrayAccess,
10
+ \Countable,
11
+ \IteratorAggregate {};
vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ use React\Promise\PromiseInterface;
5
+ use React\Promise\PromisorInterface;
6
+
7
+ /**
8
+ * Represents the result of a computation that may not have completed yet.
9
+ *
10
+ * You can use the future in a blocking manner using the wait() function, or
11
+ * you can use a promise from the future to receive the result when the future
12
+ * has been resolved.
13
+ *
14
+ * When the future is dereferenced using wait(), the result of the computation
15
+ * is cached and returned for subsequent calls to wait(). If the result of the
16
+ * computation has not yet completed when wait() is called, the call to wait()
17
+ * will block until the future has completed.
18
+ */
19
+ interface FutureInterface extends PromiseInterface, PromisorInterface
20
+ {
21
+ /**
22
+ * Returns the result of the future either from cache or by blocking until
23
+ * it is complete.
24
+ *
25
+ * This method must block until the future has a result or is cancelled.
26
+ * Throwing an exception in the wait() method will mark the future as
27
+ * realized and will throw the exception each time wait() is called.
28
+ * Throwing an instance of GuzzleHttp\Ring\CancelledException will mark
29
+ * the future as realized, will not throw immediately, but will throw the
30
+ * exception if the future's wait() method is called again.
31
+ *
32
+ * @return mixed
33
+ */
34
+ public function wait();
35
+
36
+ /**
37
+ * Cancels the future, if possible.
38
+ */
39
+ public function cancel();
40
+ }
vendor/guzzlehttp/ringphp/src/Future/FutureValue.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ /**
5
+ * Represents a future value that responds to wait() to retrieve the promised
6
+ * value, but can also return promises that are delivered the value when it is
7
+ * available.
8
+ */
9
+ class FutureValue implements FutureInterface
10
+ {
11
+ use BaseFutureTrait;
12
+ }
vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Ring\Future;
3
+
4
+ /**
5
+ * Implements common future functionality that is triggered when the result
6
+ * property is accessed via a magic __get method.
7
+ *
8
+ * @property mixed $_value Actual data used by the future. Accessing this
9
+ * property will cause the future to block if needed.
10
+ */
11
+ trait MagicFutureTrait
12
+ {
13
+ use BaseFutureTrait;
14
+
15
+ /**
16
+ * This function handles retrieving the dereferenced result when requested.
17
+ *
18
+ * @param string $name Should always be "data" or an exception is thrown.
19
+ *
20
+ * @return mixed Returns the dereferenced data.
21
+ * @throws \RuntimeException
22
+ * @throws \GuzzleHttp\Ring\Exception\CancelledException
23
+ */
24
+ public function __get($name)
25
+ {
26
+ if ($name !== '_value') {
27
+ throw new \RuntimeException("Class has no {$name} property");
28
+ }
29
+
30
+ return $this->_value = $this->wait();
31
+ }
32
+ }
vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php ADDED
@@ -0,0 +1,821 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Override curl_setopt_array() to get the last set curl options
3
+ namespace GuzzleHttp\Ring\Client {
4
+ function curl_setopt_array($handle, array $options) {
5
+ if (!empty($_SERVER['curl_test'])) {
6
+ $_SERVER['_curl'] = $options;
7
+ } else {
8
+ unset($_SERVER['_curl']);
9
+ }
10
+ \curl_setopt_array($handle, $options);
11
+ }
12
+ }
13
+
14
+ namespace GuzzleHttp\Tests\Ring\Client {
15
+
16
+ use GuzzleHttp\Ring\Client\CurlFactory;
17
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
18
+ use GuzzleHttp\Ring\Client\MockHandler;
19
+ use GuzzleHttp\Ring\Core;
20
+ use GuzzleHttp\Stream\FnStream;
21
+ use GuzzleHttp\Stream\NoSeekStream;
22
+ use GuzzleHttp\Stream\Stream;
23
+
24
+ class CurlFactoryTest extends \PHPUnit_Framework_TestCase
25
+ {
26
+ public static function setUpBeforeClass()
27
+ {
28
+ $_SERVER['curl_test'] = true;
29
+ unset($_SERVER['_curl']);
30
+ }
31
+
32
+ public static function tearDownAfterClass()
33
+ {
34
+ unset($_SERVER['_curl'], $_SERVER['curl_test']);
35
+ }
36
+
37
+ public function testCreatesCurlHandle()
38
+ {
39
+ Server::flush();
40
+ Server::enqueue([[
41
+ 'status' => 200,
42
+ 'headers' => [
43
+ 'Foo' => ['Bar'],
44
+ 'Baz' => ['bam'],
45
+ 'Content-Length' => [2],
46
+ ],
47
+ 'body' => 'hi',
48
+ ]]);
49
+
50
+ $stream = Stream::factory();
51
+
52
+ $request = [
53
+ 'http_method' => 'PUT',
54
+ 'headers' => [
55
+ 'host' => [Server::$url],
56
+ 'Hi' => [' 123'],
57
+ ],
58
+ 'body' => 'testing',
59
+ 'client' => ['save_to' => $stream],
60
+ ];
61
+
62
+ $f = new CurlFactory();
63
+ $result = $f($request);
64
+ $this->assertInternalType('array', $result);
65
+ $this->assertCount(3, $result);
66
+ $this->assertInternalType('resource', $result[0]);
67
+ $this->assertInternalType('array', $result[1]);
68
+ $this->assertSame($stream, $result[2]);
69
+ curl_close($result[0]);
70
+
71
+ $this->assertEquals('PUT', $_SERVER['_curl'][CURLOPT_CUSTOMREQUEST]);
72
+ $this->assertEquals(
73
+ 'http://http://127.0.0.1:8125/',
74
+ $_SERVER['_curl'][CURLOPT_URL]
75
+ );
76
+ // Sends via post fields when the request is small enough
77
+ $this->assertEquals('testing', $_SERVER['_curl'][CURLOPT_POSTFIELDS]);
78
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_RETURNTRANSFER]);
79
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_HEADER]);
80
+ $this->assertEquals(150, $_SERVER['_curl'][CURLOPT_CONNECTTIMEOUT]);
81
+ $this->assertInstanceOf('Closure', $_SERVER['_curl'][CURLOPT_HEADERFUNCTION]);
82
+
83
+ if (defined('CURLOPT_PROTOCOLS')) {
84
+ $this->assertEquals(
85
+ CURLPROTO_HTTP | CURLPROTO_HTTPS,
86
+ $_SERVER['_curl'][CURLOPT_PROTOCOLS]
87
+ );
88
+ }
89
+
90
+ $this->assertContains('Expect:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
91
+ $this->assertContains('Accept:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
92
+ $this->assertContains('Content-Type:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
93
+ $this->assertContains('Hi: 123', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
94
+ $this->assertContains('host: http://127.0.0.1:8125/', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
95
+ }
96
+
97
+ public function testSendsHeadRequests()
98
+ {
99
+ Server::flush();
100
+ Server::enqueue([['status' => 200]]);
101
+ $a = new CurlMultiHandler();
102
+ $response = $a([
103
+ 'http_method' => 'HEAD',
104
+ 'headers' => ['host' => [Server::$host]],
105
+ ]);
106
+ $response->wait();
107
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_NOBODY]);
108
+ $checks = [CURLOPT_WRITEFUNCTION, CURLOPT_READFUNCTION, CURLOPT_FILE, CURLOPT_INFILE];
109
+ foreach ($checks as $check) {
110
+ $this->assertArrayNotHasKey($check, $_SERVER['_curl']);
111
+ }
112
+ $this->assertEquals('HEAD', Server::received()[0]['http_method']);
113
+ }
114
+
115
+ public function testCanAddCustomCurlOptions()
116
+ {
117
+ Server::flush();
118
+ Server::enqueue([['status' => 200]]);
119
+ $a = new CurlMultiHandler();
120
+ $a([
121
+ 'http_method' => 'GET',
122
+ 'headers' => ['host' => [Server::$host]],
123
+ 'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]],
124
+ ]);
125
+ $this->assertEquals(10, $_SERVER['_curl'][CURLOPT_LOW_SPEED_LIMIT]);
126
+ }
127
+
128
+ /**
129
+ * @expectedException \InvalidArgumentException
130
+ * @expectedExceptionMessage SSL CA bundle not found: /does/not/exist
131
+ */
132
+ public function testValidatesVerify()
133
+ {
134
+ $f = new CurlFactory();
135
+ $f([
136
+ 'http_method' => 'GET',
137
+ 'headers' => ['host' => ['foo.com']],
138
+ 'client' => ['verify' => '/does/not/exist'],
139
+ ]);
140
+ }
141
+
142
+ public function testCanSetVerifyToFile()
143
+ {
144
+ $f = new CurlFactory();
145
+ $f([
146
+ 'http_method' => 'GET',
147
+ 'headers' => ['host' => ['foo.com']],
148
+ 'client' => ['verify' => __FILE__],
149
+ ]);
150
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_CAINFO]);
151
+ $this->assertEquals(2, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
152
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
153
+ }
154
+
155
+ public function testAddsVerifyAsTrue()
156
+ {
157
+ $f = new CurlFactory();
158
+ $f([
159
+ 'http_method' => 'GET',
160
+ 'headers' => ['host' => ['foo.com']],
161
+ 'client' => ['verify' => true],
162
+ ]);
163
+ $this->assertEquals(2, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
164
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
165
+ $this->assertArrayNotHasKey(CURLOPT_CAINFO, $_SERVER['_curl']);
166
+ }
167
+
168
+ public function testCanDisableVerify()
169
+ {
170
+ $f = new CurlFactory();
171
+ $f([
172
+ 'http_method' => 'GET',
173
+ 'headers' => ['host' => ['foo.com']],
174
+ 'client' => ['verify' => false],
175
+ ]);
176
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
177
+ $this->assertEquals(false, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
178
+ }
179
+
180
+ public function testAddsProxy()
181
+ {
182
+ $f = new CurlFactory();
183
+ $f([
184
+ 'http_method' => 'GET',
185
+ 'headers' => ['host' => ['foo.com']],
186
+ 'client' => ['proxy' => 'http://bar.com'],
187
+ ]);
188
+ $this->assertEquals('http://bar.com', $_SERVER['_curl'][CURLOPT_PROXY]);
189
+ }
190
+
191
+ public function testAddsViaScheme()
192
+ {
193
+ $f = new CurlFactory();
194
+ $f([
195
+ 'http_method' => 'GET',
196
+ 'scheme' => 'http',
197
+ 'headers' => ['host' => ['foo.com']],
198
+ 'client' => [
199
+ 'proxy' => ['http' => 'http://bar.com', 'https' => 'https://t'],
200
+ ],
201
+ ]);
202
+ $this->assertEquals('http://bar.com', $_SERVER['_curl'][CURLOPT_PROXY]);
203
+ }
204
+
205
+ /**
206
+ * @expectedException \InvalidArgumentException
207
+ * @expectedExceptionMessage SSL private key not found: /does/not/exist
208
+ */
209
+ public function testValidatesSslKey()
210
+ {
211
+ $f = new CurlFactory();
212
+ $f([
213
+ 'http_method' => 'GET',
214
+ 'headers' => ['host' => ['foo.com']],
215
+ 'client' => ['ssl_key' => '/does/not/exist'],
216
+ ]);
217
+ }
218
+
219
+ public function testAddsSslKey()
220
+ {
221
+ $f = new CurlFactory();
222
+ $f([
223
+ 'http_method' => 'GET',
224
+ 'headers' => ['host' => ['foo.com']],
225
+ 'client' => ['ssl_key' => __FILE__],
226
+ ]);
227
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLKEY]);
228
+ }
229
+
230
+ public function testAddsSslKeyWithPassword()
231
+ {
232
+ $f = new CurlFactory();
233
+ $f([
234
+ 'http_method' => 'GET',
235
+ 'headers' => ['host' => ['foo.com']],
236
+ 'client' => ['ssl_key' => [__FILE__, 'test']],
237
+ ]);
238
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLKEY]);
239
+ $this->assertEquals('test', $_SERVER['_curl'][CURLOPT_SSLKEYPASSWD]);
240
+ }
241
+
242
+ /**
243
+ * @expectedException \InvalidArgumentException
244
+ * @expectedExceptionMessage SSL certificate not found: /does/not/exist
245
+ */
246
+ public function testValidatesCert()
247
+ {
248
+ $f = new CurlFactory();
249
+ $f([
250
+ 'http_method' => 'GET',
251
+ 'headers' => ['host' => ['foo.com']],
252
+ 'client' => ['cert' => '/does/not/exist'],
253
+ ]);
254
+ }
255
+
256
+ public function testAddsCert()
257
+ {
258
+ $f = new CurlFactory();
259
+ $f([
260
+ 'http_method' => 'GET',
261
+ 'headers' => ['host' => ['foo.com']],
262
+ 'client' => ['cert' => __FILE__],
263
+ ]);
264
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLCERT]);
265
+ }
266
+
267
+ public function testAddsCertWithPassword()
268
+ {
269
+ $f = new CurlFactory();
270
+ $f([
271
+ 'http_method' => 'GET',
272
+ 'headers' => ['host' => ['foo.com']],
273
+ 'client' => ['cert' => [__FILE__, 'test']],
274
+ ]);
275
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLCERT]);
276
+ $this->assertEquals('test', $_SERVER['_curl'][CURLOPT_SSLCERTPASSWD]);
277
+ }
278
+
279
+ /**
280
+ * @expectedException \InvalidArgumentException
281
+ * @expectedExceptionMessage progress client option must be callable
282
+ */
283
+ public function testValidatesProgress()
284
+ {
285
+ $f = new CurlFactory();
286
+ $f([
287
+ 'http_method' => 'GET',
288
+ 'headers' => ['host' => ['foo.com']],
289
+ 'client' => ['progress' => 'foo'],
290
+ ]);
291
+ }
292
+
293
+ public function testEmitsDebugInfoToStream()
294
+ {
295
+ $res = fopen('php://memory', 'r+');
296
+ Server::flush();
297
+ Server::enqueue([['status' => 200]]);
298
+ $a = new CurlMultiHandler();
299
+ $response = $a([
300
+ 'http_method' => 'HEAD',
301
+ 'headers' => ['host' => [Server::$host]],
302
+ 'client' => ['debug' => $res],
303
+ ]);
304
+ $response->wait();
305
+ rewind($res);
306
+ $output = str_replace("\r", '', stream_get_contents($res));
307
+ $this->assertContains(
308
+ "> HEAD / HTTP/1.1\nhost: 127.0.0.1:8125\n\n",
309
+ $output
310
+ );
311
+ $this->assertContains("< HTTP/1.1 200", $output);
312
+ fclose($res);
313
+ }
314
+
315
+ public function testEmitsProgressToFunction()
316
+ {
317
+ Server::flush();
318
+ Server::enqueue([['status' => 200]]);
319
+ $a = new CurlMultiHandler();
320
+ $called = [];
321
+ $response = $a([
322
+ 'http_method' => 'HEAD',
323
+ 'headers' => ['host' => [Server::$host]],
324
+ 'client' => [
325
+ 'progress' => function () use (&$called) {
326
+ $called[] = func_get_args();
327
+ },
328
+ ],
329
+ ]);
330
+ $response->wait();
331
+ $this->assertNotEmpty($called);
332
+ foreach ($called as $call) {
333
+ $this->assertCount(4, $call);
334
+ }
335
+ }
336
+
337
+ private function addDecodeResponse($withEncoding = true)
338
+ {
339
+ $content = gzencode('test');
340
+ $response = [
341
+ 'status' => 200,
342
+ 'reason' => 'OK',
343
+ 'headers' => ['Content-Length' => [strlen($content)]],
344
+ 'body' => $content,
345
+ ];
346
+
347
+ if ($withEncoding) {
348
+ $response['headers']['Content-Encoding'] = ['gzip'];
349
+ }
350
+
351
+ Server::flush();
352
+ Server::enqueue([$response]);
353
+
354
+ return $content;
355
+ }
356
+
357
+ public function testDecodesGzippedResponses()
358
+ {
359
+ $this->addDecodeResponse();
360
+ $handler = new CurlMultiHandler();
361
+ $response = $handler([
362
+ 'http_method' => 'GET',
363
+ 'headers' => ['host' => [Server::$host]],
364
+ 'client' => ['decode_content' => true],
365
+ ]);
366
+ $response->wait();
367
+ $this->assertEquals('test', Core::body($response));
368
+ $this->assertEquals('', $_SERVER['_curl'][CURLOPT_ENCODING]);
369
+ $sent = Server::received()[0];
370
+ $this->assertNull(Core::header($sent, 'Accept-Encoding'));
371
+ }
372
+
373
+ public function testDecodesGzippedResponsesWithHeader()
374
+ {
375
+ $this->addDecodeResponse();
376
+ $handler = new CurlMultiHandler();
377
+ $response = $handler([
378
+ 'http_method' => 'GET',
379
+ 'headers' => [
380
+ 'host' => [Server::$host],
381
+ 'Accept-Encoding' => ['gzip'],
382
+ ],
383
+ 'client' => ['decode_content' => true],
384
+ ]);
385
+ $response->wait();
386
+ $this->assertEquals('gzip', $_SERVER['_curl'][CURLOPT_ENCODING]);
387
+ $sent = Server::received()[0];
388
+ $this->assertEquals('gzip', Core::header($sent, 'Accept-Encoding'));
389
+ $this->assertEquals('test', Core::body($response));
390
+ }
391
+
392
+ public function testDoesNotForceDecode()
393
+ {
394
+ $content = $this->addDecodeResponse();
395
+ $handler = new CurlMultiHandler();
396
+ $response = $handler([
397
+ 'http_method' => 'GET',
398
+ 'headers' => ['host' => [Server::$host]],
399
+ 'client' => ['decode_content' => false],
400
+ ]);
401
+ $response->wait();
402
+ $sent = Server::received()[0];
403
+ $this->assertNull(Core::header($sent, 'Accept-Encoding'));
404
+ $this->assertEquals($content, Core::body($response));
405
+ }
406
+
407
+ public function testProtocolVersion()
408
+ {
409
+ Server::flush();
410
+ Server::enqueue([['status' => 200]]);
411
+ $a = new CurlMultiHandler();
412
+ $a([
413
+ 'http_method' => 'GET',
414
+ 'headers' => ['host' => [Server::$host]],
415
+ 'version' => 1.0,
416
+ ]);
417
+ $this->assertEquals(CURL_HTTP_VERSION_1_0, $_SERVER['_curl'][CURLOPT_HTTP_VERSION]);
418
+ }
419
+
420
+ /**
421
+ * @expectedException \InvalidArgumentException
422
+ */
423
+ public function testValidatesSaveTo()
424
+ {
425
+ $handler = new CurlMultiHandler();
426
+ $handler([
427
+ 'http_method' => 'GET',
428
+ 'headers' => ['host' => [Server::$host]],
429
+ 'client' => ['save_to' => true],
430
+ ]);
431
+ }
432
+
433
+ public function testSavesToStream()
434
+ {
435
+ $stream = fopen('php://memory', 'r+');
436
+ $this->addDecodeResponse();
437
+ $handler = new CurlMultiHandler();
438
+ $response = $handler([
439
+ 'http_method' => 'GET',
440
+ 'headers' => ['host' => [Server::$host]],
441
+ 'client' => [
442
+ 'decode_content' => true,
443
+ 'save_to' => $stream,
444
+ ],
445
+ ]);
446
+ $response->wait();
447
+ rewind($stream);
448
+ $this->assertEquals('test', stream_get_contents($stream));
449
+ }
450
+
451
+ public function testSavesToGuzzleStream()
452
+ {
453
+ $stream = Stream::factory();
454
+ $this->addDecodeResponse();
455
+ $handler = new CurlMultiHandler();
456
+ $response = $handler([
457
+ 'http_method' => 'GET',
458
+ 'headers' => ['host' => [Server::$host]],
459
+ 'client' => [
460
+ 'decode_content' => true,
461
+ 'save_to' => $stream,
462
+ ],
463
+ ]);
464
+ $response->wait();
465
+ $this->assertEquals('test', (string) $stream);
466
+ }
467
+
468
+ public function testSavesToFileOnDisk()
469
+ {
470
+ $tmpfile = tempnam(sys_get_temp_dir(), 'testfile');
471
+ $this->addDecodeResponse();
472
+ $handler = new CurlMultiHandler();
473
+ $response = $handler([
474
+ 'http_method' => 'GET',
475
+ 'headers' => ['host' => [Server::$host]],
476
+ 'client' => [
477
+ 'decode_content' => true,
478
+ 'save_to' => $tmpfile,
479
+ ],
480
+ ]);
481
+ $response->wait();
482
+ $this->assertEquals('test', file_get_contents($tmpfile));
483
+ unlink($tmpfile);
484
+ }
485
+
486
+ /**
487
+ * @expectedException \InvalidArgumentException
488
+ */
489
+ public function testValidatesBody()
490
+ {
491
+ $handler = new CurlMultiHandler();
492
+ $handler([
493
+ 'http_method' => 'GET',
494
+ 'headers' => ['host' => [Server::$host]],
495
+ 'body' => false,
496
+ ]);
497
+ }
498
+
499
+ public function testAddsLargePayloadFromStreamWithNoSizeUsingChunked()
500
+ {
501
+ $stream = Stream::factory('foo');
502
+ $stream = FnStream::decorate($stream, [
503
+ 'getSize' => function () {
504
+ return null;
505
+ }
506
+ ]);
507
+ $this->addDecodeResponse();
508
+ $handler = new CurlMultiHandler();
509
+ $response = $handler([
510
+ 'http_method' => 'GET',
511
+ 'headers' => ['host' => [Server::$host]],
512
+ 'body' => $stream,
513
+ ]);
514
+ $response->wait();
515
+ $sent = Server::received()[0];
516
+ $this->assertEquals('chunked', Core::header($sent, 'Transfer-Encoding'));
517
+ $this->assertNull(Core::header($sent, 'Content-Length'));
518
+ $this->assertEquals('foo', $sent['body']);
519
+ }
520
+
521
+ public function testAddsPayloadFromIterator()
522
+ {
523
+ $iter = new \ArrayIterator(['f', 'o', 'o']);
524
+ $this->addDecodeResponse();
525
+ $handler = new CurlMultiHandler();
526
+ $response = $handler([
527
+ 'http_method' => 'GET',
528
+ 'headers' => ['host' => [Server::$host]],
529
+ 'body' => $iter,
530
+ ]);
531
+ $response->wait();
532
+ $sent = Server::received()[0];
533
+ $this->assertEquals('chunked', Core::header($sent, 'Transfer-Encoding'));
534
+ $this->assertNull(Core::header($sent, 'Content-Length'));
535
+ $this->assertEquals('foo', $sent['body']);
536
+ }
537
+
538
+ public function testAddsPayloadFromResource()
539
+ {
540
+ $res = fopen('php://memory', 'r+');
541
+ $data = str_repeat('.', 1000000);
542
+ fwrite($res, $data);
543
+ rewind($res);
544
+ $this->addDecodeResponse();
545
+ $handler = new CurlMultiHandler();
546
+ $response = $handler([
547
+ 'http_method' => 'GET',
548
+ 'headers' => [
549
+ 'host' => [Server::$host],
550
+ 'content-length' => [1000000],
551
+ ],
552
+ 'body' => $res,
553
+ ]);
554
+ $response->wait();
555
+ $sent = Server::received()[0];
556
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
557
+ $this->assertEquals(1000000, Core::header($sent, 'Content-Length'));
558
+ $this->assertEquals($data, $sent['body']);
559
+ }
560
+
561
+ public function testAddsContentLengthFromStream()
562
+ {
563
+ $stream = Stream::factory('foo');
564
+ $this->addDecodeResponse();
565
+ $handler = new CurlMultiHandler();
566
+ $response = $handler([
567
+ 'http_method' => 'GET',
568
+ 'headers' => ['host' => [Server::$host]],
569
+ 'body' => $stream,
570
+ ]);
571
+ $response->wait();
572
+ $sent = Server::received()[0];
573
+ $this->assertEquals(3, Core::header($sent, 'Content-Length'));
574
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
575
+ $this->assertEquals('foo', $sent['body']);
576
+ }
577
+
578
+ public function testDoesNotAddMultipleContentLengthHeaders()
579
+ {
580
+ $this->addDecodeResponse();
581
+ $handler = new CurlMultiHandler();
582
+ $response = $handler([
583
+ 'http_method' => 'GET',
584
+ 'headers' => [
585
+ 'host' => [Server::$host],
586
+ 'content-length' => [3],
587
+ ],
588
+ 'body' => 'foo',
589
+ ]);
590
+ $response->wait();
591
+ $sent = Server::received()[0];
592
+ $this->assertEquals(3, Core::header($sent, 'Content-Length'));
593
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
594
+ $this->assertEquals('foo', $sent['body']);
595
+ }
596
+
597
+ public function testSendsPostWithNoBodyOrDefaultContentType()
598
+ {
599
+ Server::flush();
600
+ Server::enqueue([['status' => 200]]);
601
+ $handler = new CurlMultiHandler();
602
+ $response = $handler([
603
+ 'http_method' => 'POST',
604
+ 'uri' => '/',
605
+ 'headers' => ['host' => [Server::$host]],
606
+ ]);
607
+ $response->wait();
608
+ $received = Server::received()[0];
609
+ $this->assertEquals('POST', $received['http_method']);
610
+ $this->assertNull(Core::header($received, 'content-type'));
611
+ $this->assertSame('0', Core::firstHeader($received, 'content-length'));
612
+ }
613
+
614
+ public function testParseProtocolVersion()
615
+ {
616
+ $res = CurlFactory::createResponse(
617
+ function () {},
618
+ [],
619
+ ['curl' => ['errno' => null]],
620
+ ['HTTP/1.1 200 Ok'],
621
+ null
622
+ );
623
+
624
+ $this->assertSame('1.1', $res['version']);
625
+ }
626
+
627
+ public function testFailsWhenNoResponseAndNoBody()
628
+ {
629
+ $res = CurlFactory::createResponse(function () {}, [], [], [], null);
630
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\RingException', $res['error']);
631
+ $this->assertContains(
632
+ 'No response was received for a request with no body',
633
+ $res['error']->getMessage()
634
+ );
635
+ }
636
+
637
+ public function testFailsWhenCannotRewindRetry()
638
+ {
639
+ $res = CurlFactory::createResponse(function () {}, [
640
+ 'body' => new NoSeekStream(Stream::factory('foo'))
641
+ ], [], [], null);
642
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\RingException', $res['error']);
643
+ $this->assertContains(
644
+ 'rewind the request body failed',
645
+ $res['error']->getMessage()
646
+ );
647
+ }
648
+
649
+ public function testRetriesWhenBodyCanBeRewound()
650
+ {
651
+ $callHandler = $called = false;
652
+ $res = CurlFactory::createResponse(function () use (&$callHandler) {
653
+ $callHandler = true;
654
+ return ['status' => 200];
655
+ }, [
656
+ 'body' => FnStream::decorate(Stream::factory('test'), [
657
+ 'seek' => function () use (&$called) {
658
+ $called = true;
659
+ return true;
660
+ }
661
+ ])
662
+ ], [], [], null);
663
+
664
+ $this->assertTrue($callHandler);
665
+ $this->assertTrue($called);
666
+ $this->assertEquals('200', $res['status']);
667
+ }
668
+
669
+ public function testFailsWhenRetryMoreThanThreeTimes()
670
+ {
671
+ $call = 0;
672
+ $mock = new MockHandler(function (array $request) use (&$mock, &$call) {
673
+ $call++;
674
+ return CurlFactory::createResponse($mock, $request, [], [], null);
675
+ });
676
+ $response = $mock([
677
+ 'http_method' => 'GET',
678
+ 'body' => 'test',
679
+ ]);
680
+ $this->assertEquals(3, $call);
681
+ $this->assertArrayHasKey('error', $response);
682
+ $this->assertContains(
683
+ 'The cURL request was retried 3 times',
684
+ $response['error']->getMessage()
685
+ );
686
+ }
687
+
688
+ public function testHandles100Continue()
689
+ {
690
+ Server::flush();
691
+ Server::enqueue([
692
+ [
693
+ 'status' => '200',
694
+ 'reason' => 'OK',
695
+ 'headers' => [
696
+ 'Test' => ['Hello'],
697
+ 'Content-Length' => ['4'],
698
+ ],
699
+ 'body' => 'test',
700
+ ],
701
+ ]);
702
+
703
+ $request = [
704
+ 'http_method' => 'PUT',
705
+ 'headers' => [
706
+ 'Host' => [Server::$host],
707
+ 'Expect' => ['100-Continue'],
708
+ ],
709
+ 'body' => 'test',
710
+ ];
711
+
712
+ $handler = new CurlMultiHandler();
713
+ $response = $handler($request)->wait();
714
+ $this->assertEquals(200, $response['status']);
715
+ $this->assertEquals('OK', $response['reason']);
716
+ $this->assertEquals(['Hello'], $response['headers']['Test']);
717
+ $this->assertEquals(['4'], $response['headers']['Content-Length']);
718
+ $this->assertEquals('test', Core::body($response));
719
+ }
720
+
721
+ public function testCreatesConnectException()
722
+ {
723
+ $m = new \ReflectionMethod('GuzzleHttp\Ring\Client\CurlFactory', 'createErrorResponse');
724
+ $m->setAccessible(true);
725
+ $response = $m->invoke(
726
+ null,
727
+ function () {},
728
+ [],
729
+ [
730
+ 'err_message' => 'foo',
731
+ 'curl' => [
732
+ 'errno' => CURLE_COULDNT_CONNECT,
733
+ ]
734
+ ]
735
+ );
736
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\ConnectException', $response['error']);
737
+ }
738
+
739
+ public function testParsesLastResponseOnly()
740
+ {
741
+ $response1 = [
742
+ 'status' => 301,
743
+ 'headers' => [
744
+ 'Content-Length' => ['0'],
745
+ 'Location' => ['/foo']
746
+ ]
747
+ ];
748
+
749
+ $response2 = [
750
+ 'status' => 200,
751
+ 'headers' => [
752
+ 'Content-Length' => ['0'],
753
+ 'Foo' => ['bar']
754
+ ]
755
+ ];
756
+
757
+ Server::flush();
758
+ Server::enqueue([$response1, $response2]);
759
+
760
+ $a = new CurlMultiHandler();
761
+ $response = $a([
762
+ 'http_method' => 'GET',
763
+ 'headers' => ['Host' => [Server::$host]],
764
+ 'client' => [
765
+ 'curl' => [
766
+ CURLOPT_FOLLOWLOCATION => true
767
+ ]
768
+ ]
769
+ ])->wait();
770
+
771
+ $this->assertEquals(1, $response['transfer_stats']['redirect_count']);
772
+ $this->assertEquals('http://127.0.0.1:8125/foo', $response['effective_url']);
773
+ $this->assertEquals(['bar'], $response['headers']['Foo']);
774
+ $this->assertEquals(200, $response['status']);
775
+ $this->assertFalse(Core::hasHeader($response, 'Location'));
776
+ }
777
+
778
+ public function testMaintainsMultiHeaderOrder()
779
+ {
780
+ Server::flush();
781
+ Server::enqueue([
782
+ [
783
+ 'status' => 200,
784
+ 'headers' => [
785
+ 'Content-Length' => ['0'],
786
+ 'Foo' => ['a', 'b'],
787
+ 'foo' => ['c', 'd'],
788
+ ]
789
+ ]
790
+ ]);
791
+
792
+ $a = new CurlMultiHandler();
793
+ $response = $a([
794
+ 'http_method' => 'GET',
795
+ 'headers' => ['Host' => [Server::$host]]
796
+ ])->wait();
797
+
798
+ $this->assertEquals(
799
+ ['a', 'b', 'c', 'd'],
800
+ Core::headerLines($response, 'Foo')
801
+ );
802
+ }
803
+
804
+ /**
805
+ * @expectedException \RuntimeException
806
+ * @expectedExceptionMessage Directory /path/to/does/not does not exist for save_to value of /path/to/does/not/exist.txt
807
+ */
808
+ public function testThrowsWhenDirNotFound()
809
+ {
810
+ $request = [
811
+ 'http_method' => 'GET',
812
+ 'headers' => ['host' => [Server::$url]],
813
+ 'client' => ['save_to' => '/path/to/does/not/exist.txt'],
814
+ ];
815
+
816
+ $f = new CurlFactory();
817
+ $f($request);
818
+ }
819
+ }
820
+
821
+ }
vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Client\CurlHandler;
5
+
6
+ class CurlHandlerTest extends \PHPUnit_Framework_TestCase
7
+ {
8
+ protected function setUp()
9
+ {
10
+ if (!function_exists('curl_reset')) {
11
+ $this->markTestSkipped('curl_reset() is not available');
12
+ }
13
+ }
14
+
15
+ protected function getHandler($factory = null, $options = [])
16
+ {
17
+ return new CurlHandler($options);
18
+ }
19
+
20
+ public function testCanSetMaxHandles()
21
+ {
22
+ $a = new CurlHandler(['max_handles' => 10]);
23
+ $this->assertEquals(10, $this->readAttribute($a, 'maxHandles'));
24
+ }
25
+
26
+ public function testCreatesCurlErrors()
27
+ {
28
+ $handler = new CurlHandler();
29
+ $response = $handler([
30
+ 'http_method' => 'GET',
31
+ 'uri' => '/',
32
+ 'headers' => ['host' => ['localhost:123']],
33
+ 'client' => ['timeout' => 0.001, 'connect_timeout' => 0.001],
34
+ ]);
35
+ $this->assertNull($response['status']);
36
+ $this->assertNull($response['reason']);
37
+ $this->assertEquals([], $response['headers']);
38
+ $this->assertInstanceOf(
39
+ 'GuzzleHttp\Ring\Exception\RingException',
40
+ $response['error']
41
+ );
42
+
43
+ $this->assertEquals(
44
+ 1,
45
+ preg_match('/^cURL error \d+: .*$/', $response['error']->getMessage())
46
+ );
47
+ }
48
+
49
+ public function testReleasesAdditionalEasyHandles()
50
+ {
51
+ Server::flush();
52
+ $response = [
53
+ 'status' => 200,
54
+ 'headers' => ['Content-Length' => [4]],
55
+ 'body' => 'test',
56
+ ];
57
+
58
+ Server::enqueue([$response, $response, $response, $response]);
59
+ $a = new CurlHandler(['max_handles' => 2]);
60
+
61
+ $fn = function () use (&$calls, $a, &$fn) {
62
+ if (++$calls < 4) {
63
+ $a([
64
+ 'http_method' => 'GET',
65
+ 'headers' => ['host' => [Server::$host]],
66
+ 'client' => ['progress' => $fn],
67
+ ]);
68
+ }
69
+ };
70
+
71
+ $request = [
72
+ 'http_method' => 'GET',
73
+ 'headers' => ['host' => [Server::$host]],
74
+ 'client' => [
75
+ 'progress' => $fn,
76
+ ],
77
+ ];
78
+
79
+ $a($request);
80
+ $this->assertCount(2, $this->readAttribute($a, 'handles'));
81
+ }
82
+
83
+ public function testReusesHandles()
84
+ {
85
+ Server::flush();
86
+ $response = ['status' => 200];
87
+ Server::enqueue([$response, $response]);
88
+ $a = new CurlHandler();
89
+ $request = [
90
+ 'http_method' => 'GET',
91
+ 'headers' => ['host' => [Server::$host]],
92
+ ];
93
+ $a($request);
94
+ $a($request);
95
+ }
96
+ }
vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
5
+
6
+ class CurlMultiHandlerTest extends \PHPUnit_Framework_TestCase
7
+ {
8
+ public function testSendsRequest()
9
+ {
10
+ Server::enqueue([['status' => 200]]);
11
+ $a = new CurlMultiHandler();
12
+ $response = $a([
13
+ 'http_method' => 'GET',
14
+ 'headers' => ['host' => [Server::$host]],
15
+ ]);
16
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
17
+ $this->assertEquals(200, $response['status']);
18
+ $this->assertArrayHasKey('transfer_stats', $response);
19
+ $realUrl = trim($response['transfer_stats']['url'], '/');
20
+ $this->assertEquals(trim(Server::$url, '/'), $realUrl);
21
+ $this->assertArrayHasKey('effective_url', $response);
22
+ $this->assertEquals(
23
+ trim(Server::$url, '/'),
24
+ trim($response['effective_url'], '/')
25
+ );
26
+ }
27
+
28
+ public function testCreatesErrorResponses()
29
+ {
30
+ $url = 'http://localhost:123/';
31
+ $a = new CurlMultiHandler();
32
+ $response = $a([
33
+ 'http_method' => 'GET',
34
+ 'headers' => ['host' => ['localhost:123']],
35
+ ]);
36
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
37
+ $this->assertNull($response['status']);
38
+ $this->assertNull($response['reason']);
39
+ $this->assertEquals([], $response['headers']);
40
+ $this->assertArrayHasKey('error', $response);
41
+ $this->assertContains('cURL error ', $response['error']->getMessage());
42
+ $this->assertArrayHasKey('transfer_stats', $response);
43
+ $this->assertEquals(
44
+ trim($url, '/'),
45
+ trim($response['transfer_stats']['url'], '/')
46
+ );
47
+ $this->assertArrayHasKey('effective_url', $response);
48
+ $this->assertEquals(
49
+ trim($url, '/'),
50
+ trim($response['effective_url'], '/')
51
+ );
52
+ }
53
+
54
+ public function testSendsFuturesWhenDestructed()
55
+ {
56
+ Server::enqueue([['status' => 200]]);
57
+ $a = new CurlMultiHandler();
58
+ $response = $a([
59
+ 'http_method' => 'GET',
60
+ 'headers' => ['host' => [Server::$host]],
61
+ ]);
62
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
63
+ $a->__destruct();
64
+ $this->assertEquals(200, $response['status']);
65
+ }
66
+
67
+ public function testCanSetMaxHandles()
68
+ {
69
+ $a = new CurlMultiHandler(['max_handles' => 2]);
70
+ $this->assertEquals(2, $this->readAttribute($a, 'maxHandles'));
71
+ }
72
+
73
+ public function testCanSetSelectTimeout()
74
+ {
75
+ $a = new CurlMultiHandler(['select_timeout' => 2]);
76
+ $this->assertEquals(2, $this->readAttribute($a, 'selectTimeout'));
77
+ }
78
+
79
+ public function testSendsFuturesWhenMaxHandlesIsReached()
80
+ {
81
+ $request = [
82
+ 'http_method' => 'PUT',
83
+ 'headers' => ['host' => [Server::$host]],
84
+ 'future' => 'lazy', // passing this to control the test
85
+ ];
86
+ $response = ['status' => 200];
87
+ Server::flush();
88
+ Server::enqueue([$response, $response, $response]);
89
+ $a = new CurlMultiHandler(['max_handles' => 3]);
90
+ for ($i = 0; $i < 5; $i++) {
91
+ $responses[] = $a($request);
92
+ }
93
+ $this->assertCount(3, Server::received());
94
+ $responses[3]->cancel();
95
+ $responses[4]->cancel();
96
+ }
97
+
98
+ public function testCanCancel()
99
+ {
100
+ Server::flush();
101
+ $response = ['status' => 200];
102
+ Server::enqueue(array_fill_keys(range(0, 10), $response));
103
+ $a = new CurlMultiHandler();
104
+ $responses = [];
105
+
106
+ for ($i = 0; $i < 10; $i++) {
107
+ $response = $a([
108
+ 'http_method' => 'GET',
109
+ 'headers' => ['host' => [Server::$host]],
110
+ 'future' => 'lazy',
111
+ ]);
112
+ $response->cancel();
113
+ $responses[] = $response;
114
+ }
115
+
116
+ $this->assertCount(0, Server::received());
117
+
118
+ foreach ($responses as $response) {
119
+ $this->assertTrue($this->readAttribute($response, 'isRealized'));
120
+ }
121
+ }
122
+
123
+ public function testCannotCancelFinished()
124
+ {
125
+ Server::flush();
126
+ Server::enqueue([['status' => 200]]);
127
+ $a = new CurlMultiHandler();
128
+ $response = $a([
129
+ 'http_method' => 'GET',
130
+ 'headers' => ['host' => [Server::$host]],
131
+ ]);
132
+ $response->wait();
133
+ $response->cancel();
134
+ }
135
+
136
+ public function testDelaysInParallel()
137
+ {
138
+ Server::flush();
139
+ Server::enqueue([['status' => 200]]);
140
+ $a = new CurlMultiHandler();
141
+ $expected = microtime(true) + (100 / 1000);
142
+ $response = $a([
143
+ 'http_method' => 'GET',
144
+ 'headers' => ['host' => [Server::$host]],
145
+ 'client' => ['delay' => 100],
146
+ ]);
147
+ $response->wait();
148
+ $this->assertGreaterThanOrEqual($expected, microtime(true));
149
+ }
150
+
151
+ public function testSendsNonLazyFutures()
152
+ {
153
+ $request = [
154
+ 'http_method' => 'GET',
155
+ 'headers' => ['host' => [Server::$host]],
156
+ 'future' => true,
157
+ ];
158
+ Server::flush();
159
+ Server::enqueue([['status' => 202]]);
160
+ $a = new CurlMultiHandler();
161
+ $response = $a($request);
162
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
163
+ $this->assertEquals(202, $response['status']);
164
+ }
165
+
166
+ public function testExtractsErrors()
167
+ {
168
+ $request = [
169
+ 'http_method' => 'GET',
170
+ 'headers' => ['host' => ['127.0.0.1:123']],
171
+ 'future' => true,
172
+ ];
173
+ Server::flush();
174
+ Server::enqueue([['status' => 202]]);
175
+ $a = new CurlMultiHandler();
176
+ $response = $a($request);
177
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
178
+ $this->assertEquals(CURLE_COULDNT_CONNECT, $response['curl']['errno']);
179
+ $this->assertNotEmpty($response['curl']['error']);
180
+ }
181
+ }
vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Client\Middleware;
5
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
6
+
7
+ class MiddlewareTest extends \PHPUnit_Framework_TestCase
8
+ {
9
+ public function testFutureCallsDefaultHandler()
10
+ {
11
+ $future = new CompletedFutureArray(['status' => 200]);
12
+ $calledA = false;
13
+ $a = function (array $req) use (&$calledA, $future) {
14
+ $calledA = true;
15
+ return $future;
16
+ };
17
+ $calledB = false;
18
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
19
+ $s = Middleware::wrapFuture($a, $b);
20
+ $s([]);
21
+ $this->assertTrue($calledA);
22
+ $this->assertFalse($calledB);
23
+ }
24
+
25
+ public function testFutureCallsStreamingHandler()
26
+ {
27
+ $future = new CompletedFutureArray(['status' => 200]);
28
+ $calledA = false;
29
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
30
+ $calledB = false;
31
+ $b = function (array $req) use (&$calledB, $future) {
32
+ $calledB = true;
33
+ return $future;
34
+ };
35
+ $s = Middleware::wrapFuture($a, $b);
36
+ $result = $s(['client' => ['future' => true]]);
37
+ $this->assertFalse($calledA);
38
+ $this->assertTrue($calledB);
39
+ $this->assertSame($future, $result);
40
+ }
41
+
42
+ public function testStreamingCallsDefaultHandler()
43
+ {
44
+ $calledA = false;
45
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
46
+ $calledB = false;
47
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
48
+ $s = Middleware::wrapStreaming($a, $b);
49
+ $s([]);
50
+ $this->assertTrue($calledA);
51
+ $this->assertFalse($calledB);
52
+ }
53
+
54
+ public function testStreamingCallsStreamingHandler()
55
+ {
56
+ $calledA = false;
57
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
58
+ $calledB = false;
59
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
60
+ $s = Middleware::wrapStreaming($a, $b);
61
+ $s(['client' => ['stream' => true]]);
62
+ $this->assertFalse($calledA);
63
+ $this->assertTrue($calledB);
64
+ }
65
+ }
vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Client\MockHandler;
5
+ use GuzzleHttp\Ring\Future\FutureArray;
6
+ use React\Promise\Deferred;
7
+
8
+ class MockHandlerTest extends \PHPUnit_Framework_TestCase
9
+ {
10
+ public function testReturnsArray()
11
+ {
12
+ $mock = new MockHandler(['status' => 200]);
13
+ $response = $mock([]);
14
+ $this->assertEquals(200, $response['status']);
15
+ $this->assertEquals([], $response['headers']);
16
+ $this->assertNull($response['body']);
17
+ $this->assertNull($response['reason']);
18
+ $this->assertNull($response['effective_url']);
19
+ }
20
+
21
+ public function testReturnsFutures()
22
+ {
23
+ $deferred = new Deferred();
24
+ $future = new FutureArray(
25
+ $deferred->promise(),
26
+ function () use ($deferred) {
27
+ $deferred->resolve(['status' => 200]);
28
+ }
29
+ );
30
+ $mock = new MockHandler($future);
31
+ $response = $mock([]);
32
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
33
+ $this->assertEquals(200, $response['status']);
34
+ }
35
+
36
+ public function testReturnsFuturesWithThenCall()
37
+ {
38
+ $deferred = new Deferred();
39
+ $future = new FutureArray(
40
+ $deferred->promise(),
41
+ function () use ($deferred) {
42
+ $deferred->resolve(['status' => 200]);
43
+ }
44
+ );
45
+ $mock = new MockHandler($future);
46
+ $response = $mock([]);
47
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
48
+ $this->assertEquals(200, $response['status']);
49
+ $req = null;
50
+ $promise = $response->then(function ($value) use (&$req) {
51
+ $req = $value;
52
+ $this->assertEquals(200, $req['status']);
53
+ });
54
+ $this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
55
+ $this->assertEquals(200, $req['status']);
56
+ }
57
+
58
+ public function testReturnsFuturesAndProxiesCancel()
59
+ {
60
+ $c = null;
61
+ $deferred = new Deferred();
62
+ $future = new FutureArray(
63
+ $deferred->promise(),
64
+ function () {},
65
+ function () use (&$c) {
66
+ $c = true;
67
+ return true;
68
+ }
69
+ );
70
+ $mock = new MockHandler($future);
71
+ $response = $mock([]);
72
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
73
+ $response->cancel();
74
+ $this->assertTrue($c);
75
+ }
76
+
77
+ /**
78
+ * @expectedException \InvalidArgumentException
79
+ * @expectedExceptionMessage Response must be an array or FutureArrayInterface. Found
80
+ */
81
+ public function testEnsuresMockIsValid()
82
+ {
83
+ $mock = new MockHandler('foo');
84
+ $mock([]);
85
+ }
86
+ }
vendor/guzzlehttp/ringphp/tests/Client/Server.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Client\StreamHandler;
5
+ use GuzzleHttp\Ring\Core;
6
+
7
+ /**
8
+ * Class uses to control the test webserver.
9
+ *
10
+ * Queued responses will be served to requests using a FIFO order. All requests
11
+ * received by the server are stored on the node.js server and can be retrieved
12
+ * by calling {@see Server::received()}.
13
+ *
14
+ * Mock responses that don't require data to be transmitted over HTTP a great
15
+ * for testing. Mock response, however, cannot test the actual sending of an
16
+ * HTTP request using cURL. This test server allows the simulation of any
17
+ * number of HTTP request response transactions to test the actual sending of
18
+ * requests over the wire without having to leave an internal network.
19
+ */
20
+ class Server
21
+ {
22
+ public static $started;
23
+ public static $url = 'http://127.0.0.1:8125/';
24
+ public static $host = '127.0.0.1:8125';
25
+ public static $port = 8125;
26
+
27
+ /**
28
+ * Flush the received requests from the server
29
+ * @throws \RuntimeException
30
+ */
31
+ public static function flush()
32
+ {
33
+ self::send('DELETE', '/guzzle-server/requests');
34
+ }
35
+
36
+ /**
37
+ * Queue an array of responses or a single response on the server.
38
+ *
39
+ * Any currently queued responses will be overwritten. Subsequent requests
40
+ * on the server will return queued responses in FIFO order.
41
+ *
42
+ * @param array $responses An array of responses. The shape of a response
43
+ * is the shape described in the RingPHP spec.
44
+ * @throws \Exception
45
+ */
46
+ public static function enqueue(array $responses)
47
+ {
48
+ $data = [];
49
+
50
+ foreach ($responses as $response) {
51
+ if (!is_array($response)) {
52
+ throw new \Exception('Each response must be an array');
53
+ }
54
+
55
+ if (isset($response['body'])) {
56
+ $response['body'] = base64_encode($response['body']);
57
+ }
58
+
59
+ $response += ['headers' => [], 'reason' => '', 'body' => ''];
60
+ $data[] = $response;
61
+ }
62
+
63
+ self::send('PUT', '/guzzle-server/responses', json_encode($data));
64
+ }
65
+
66
+ /**
67
+ * Get all of the received requests as a RingPHP request structure.
68
+ *
69
+ * @return array
70
+ * @throws \RuntimeException
71
+ */
72
+ public static function received()
73
+ {
74
+ if (!self::$started) {
75
+ return [];
76
+ }
77
+
78
+ $response = self::send('GET', '/guzzle-server/requests');
79
+ $body = Core::body($response);
80
+ $result = json_decode($body, true);
81
+ if ($result === false) {
82
+ throw new \RuntimeException('Error decoding response: '
83
+ . json_last_error());
84
+ }
85
+
86
+ foreach ($result as &$res) {
87
+ if (isset($res['uri'])) {
88
+ $res['resource'] = $res['uri'];
89
+ }
90
+ if (isset($res['query_string'])) {
91
+ $res['resource'] .= '?' . $res['query_string'];
92
+ }
93
+ if (!isset($res['resource'])) {
94
+ $res['resource'] = '';
95
+ }
96
+ // Ensure that headers are all arrays
97
+ if (isset($res['headers'])) {
98
+ foreach ($res['headers'] as &$h) {
99
+ $h = (array) $h;
100
+ }
101
+ unset($h);
102
+ }
103
+ }
104
+
105
+ unset($res);
106
+ return $result;
107
+ }
108
+
109
+ /**
110
+ * Stop running the node.js server
111
+ */
112
+ public static function stop()
113
+ {
114
+ if (self::$started) {
115
+ self::send('DELETE', '/guzzle-server');
116
+ }
117
+
118
+ self::$started = false;
119
+ }
120
+
121
+ public static function wait($maxTries = 20)
122
+ {
123
+ $tries = 0;
124
+ while (!self::isListening() && ++$tries < $maxTries) {
125
+ usleep(100000);
126
+ }
127
+
128
+ if (!self::isListening()) {
129
+ throw new \RuntimeException('Unable to contact node.js server');
130
+ }
131
+ }
132
+
133
+ public static function start()
134
+ {
135
+ if (self::$started) {
136
+ return;
137
+ }
138
+
139
+ try {
140
+ self::wait();
141
+ } catch (\Exception $e) {
142
+ exec('node ' . __DIR__ . \DIRECTORY_SEPARATOR . 'server.js '
143
+ . self::$port . ' >> /tmp/server.log 2>&1 &');
144
+ self::wait();
145
+ }
146
+
147
+ self::$started = true;
148
+ }
149
+
150
+ private static function isListening()
151
+ {
152
+ $response = self::send('GET', '/guzzle-server/perf', null, [
153
+ 'connect_timeout' => 1,
154
+ 'timeout' => 1
155
+ ]);
156
+
157
+ return !isset($response['error']);
158
+ }
159
+
160
+ private static function send(
161
+ $method,
162
+ $path,
163
+ $body = null,
164
+ array $client = []
165
+ ) {
166
+ $handler = new StreamHandler();
167
+
168
+ $request = [
169
+ 'http_method' => $method,
170
+ 'uri' => $path,
171
+ 'request_port' => 8125,
172
+ 'headers' => ['host' => ['127.0.0.1:8125']],
173
+ 'body' => $body,
174
+ 'client' => $client,
175
+ ];
176
+
177
+ if ($body) {
178
+ $request['headers']['content-length'] = [strlen($body)];
179
+ }
180
+
181
+ return $handler($request);
182
+ }
183
+ }
vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php ADDED
@@ -0,0 +1,480 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Client;
3
+
4
+ use GuzzleHttp\Ring\Client\ClientUtils;
5
+ use GuzzleHttp\Ring\Core;
6
+ use GuzzleHttp\Ring\Client\StreamHandler;
7
+
8
+ class StreamHandlerTest extends \PHPUnit_Framework_TestCase
9
+ {
10
+ public function testReturnsResponseForSuccessfulRequest()
11
+ {
12
+ $this->queueRes();
13
+ $handler = new StreamHandler();
14
+ $response = $handler([
15
+ 'http_method' => 'GET',
16
+ 'uri' => '/',
17
+ 'headers' => [
18
+ 'host' => [Server::$host],
19
+ 'Foo' => ['Bar'],
20
+ ],
21
+ ]);
22
+
23
+ $this->assertEquals('1.1', $response['version']);
24
+ $this->assertEquals(200, $response['status']);
25
+ $this->assertEquals('OK', $response['reason']);
26
+ $this->assertEquals(['Bar'], $response['headers']['Foo']);
27
+ $this->assertEquals(['8'], $response['headers']['Content-Length']);
28
+ $this->assertEquals('hi there', Core::body($response));
29
+
30
+ $sent = Server::received()[0];
31
+ $this->assertEquals('GET', $sent['http_method']);
32
+ $this->assertEquals('/', $sent['resource']);
33
+ $this->assertEquals(['127.0.0.1:8125'], $sent['headers']['host']);
34
+ $this->assertEquals('Bar', Core::header($sent, 'foo'));
35
+ }
36
+
37
+ public function testAddsErrorToResponse()
38
+ {
39
+ $handler = new StreamHandler();
40
+ $result = $handler([
41
+ 'http_method' => 'GET',
42
+ 'headers' => ['host' => ['localhost:123']],
43
+ 'client' => ['timeout' => 0.01],
44
+ ]);
45
+ $this->assertInstanceOf(
46
+ 'GuzzleHttp\Ring\Future\CompletedFutureArray',
47
+ $result
48
+ );
49
+ $this->assertNull($result['status']);
50
+ $this->assertNull($result['body']);
51
+ $this->assertEquals([], $result['headers']);
52
+ $this->assertInstanceOf(
53
+ 'GuzzleHttp\Ring\Exception\RingException',
54
+ $result['error']
55
+ );
56
+ }
57
+
58
+ public function testEnsuresTheHttpProtocol()
59
+ {
60
+ $handler = new StreamHandler();
61
+ $result = $handler([
62
+ 'http_method' => 'GET',
63
+ 'url' => 'ftp://localhost:123',
64
+ ]);
65
+ $this->assertArrayHasKey('error', $result);
66
+ $this->assertContains(
67
+ 'URL is invalid: ftp://localhost:123',
68
+ $result['error']->getMessage()
69
+ );
70
+ }
71
+
72
+ public function testStreamAttributeKeepsStreamOpen()
73
+ {
74
+ $this->queueRes();
75
+ $handler = new StreamHandler();
76
+ $response = $handler([
77
+ 'http_method' => 'PUT',
78
+ 'uri' => '/foo',
79
+ 'query_string' => 'baz=bar',
80
+ 'headers' => [
81
+ 'host' => [Server::$host],
82
+ 'Foo' => ['Bar'],
83
+ ],
84
+ 'body' => 'test',
85
+ 'client' => ['stream' => true],
86
+ ]);
87
+
88
+ $this->assertEquals(200, $response['status']);
89
+ $this->assertEquals('OK', $response['reason']);
90
+ $this->assertEquals('8', Core::header($response, 'Content-Length'));
91
+ $body = $response['body'];
92
+ $this->assertTrue(is_resource($body));
93
+ $this->assertEquals('http', stream_get_meta_data($body)['wrapper_type']);
94
+ $this->assertEquals('hi there', stream_get_contents($body));
95
+ fclose($body);
96
+ $sent = Server::received()[0];
97
+ $this->assertEquals('PUT', $sent['http_method']);
98
+ $this->assertEquals('/foo', $sent['uri']);
99
+ $this->assertEquals('baz=bar', $sent['query_string']);
100
+ $this->assertEquals('/foo?baz=bar', $sent['resource']);
101
+ $this->assertEquals('127.0.0.1:8125', Core::header($sent, 'host'));
102
+ $this->assertEquals('Bar', Core::header($sent, 'foo'));
103
+ }
104
+
105
+ public function testDrainsResponseIntoTempStream()
106
+ {
107
+ $this->queueRes();
108
+ $handler = new StreamHandler();
109
+ $response = $handler([
110
+ 'http_method' => 'GET',
111
+ 'uri' => '/',
112
+ 'headers' => ['host' => [Server::$host]],
113
+ ]);
114
+ $body = $response['body'];
115
+ $this->assertEquals('php://temp', stream_get_meta_data($body)['uri']);
116
+ $this->assertEquals('hi', fread($body, 2));
117
+ fclose($body);
118
+ }
119
+
120
+ public function testDrainsResponseIntoSaveToBody()
121
+ {
122
+ $r = fopen('php://temp', 'r+');
123
+ $this->queueRes();
124
+ $handler = new StreamHandler();
125
+ $response = $handler([
126
+ 'http_method' => 'GET',
127
+ 'uri' => '/',
128
+ 'headers' => ['host' => [Server::$host]],
129
+ 'client' => ['save_to' => $r],
130
+ ]);
131
+ $body = $response['body'];
132
+ $this->assertEquals('php://temp', stream_get_meta_data($body)['uri']);
133
+ $this->assertEquals('hi', fread($body, 2));
134
+ $this->assertEquals(' there', stream_get_contents($r));
135
+ fclose($r);
136
+ }
137
+
138
+ public function testDrainsResponseIntoSaveToBodyAtPath()
139
+ {
140
+ $tmpfname = tempnam('/tmp', 'save_to_path');
141
+ $this->queueRes();
142
+ $handler = new StreamHandler();
143
+ $response = $handler([
144
+ 'http_method' => 'GET',
145
+ 'uri' => '/',
146
+ 'headers' => ['host' => [Server::$host]],
147
+ 'client' => ['save_to' => $tmpfname],
148
+ ]);
149
+ $body = $response['body'];
150
+ $this->assertInstanceOf('GuzzleHttp\Stream\StreamInterface', $body);
151
+ $this->assertEquals($tmpfname, $body->getMetadata('uri'));
152
+ $this->assertEquals('hi', $body->read(2));
153
+ $body->close();
154
+ unlink($tmpfname);
155
+ }
156
+
157
+ public function testAutomaticallyDecompressGzip()
158
+ {
159
+ Server::flush();
160
+ $content = gzencode('test');
161
+ Server::enqueue([
162
+ [
163
+ 'status' => 200,
164
+ 'reason' => 'OK',
165
+ 'headers' => [
166
+ 'Content-Encoding' => ['gzip'],
167
+ 'Content-Length' => [strlen($content)],
168
+ ],
169
+ 'body' => $content,
170
+ ],
171
+ ]);
172
+
173
+ $handler = new StreamHandler();
174
+ $response = $handler([
175
+ 'http_method' => 'GET',
176
+ 'headers' => ['host' => [Server::$host]],
177
+ 'uri' => '/',
178
+ 'client' => ['decode_content' => true],
179
+ ]);
180
+ $this->assertEquals('test', Core::body($response));
181
+ }
182
+
183
+ public function testDoesNotForceGzipDecode()
184
+ {
185
+ Server::flush();
186
+ $content = gzencode('test');
187
+ Server::enqueue([
188
+ [
189
+ 'status' => 200,
190
+ 'reason' => 'OK',
191
+ 'headers' => [
192
+ 'Content-Encoding' => ['gzip'],
193
+ 'Content-Length' => [strlen($content)],
194
+ ],
195
+ 'body' => $content,
196
+ ],
197
+ ]);
198
+
199
+ $handler = new StreamHandler();
200
+ $response = $handler([
201
+ 'http_method' => 'GET',
202
+ 'headers' => ['host' => [Server::$host]],
203
+ 'uri' => '/',
204
+ 'client' => ['stream' => true, 'decode_content' => false],
205
+ ]);
206
+ $this->assertSame($content, Core::body($response));
207
+ }
208
+
209
+ public function testProtocolVersion()
210
+ {
211
+ $this->queueRes();
212
+ $handler = new StreamHandler();
213
+ $handler([
214
+ 'http_method' => 'GET',
215
+ 'uri' => '/',
216
+ 'headers' => ['host' => [Server::$host]],
217
+ 'version' => 1.0,
218
+ ]);
219
+
220
+ $this->assertEquals(1.0, Server::received()[0]['version']);
221
+ }
222
+
223
+ protected function getSendResult(array $opts)
224
+ {
225
+ $this->queueRes();
226
+ $handler = new StreamHandler();
227
+ $opts['stream'] = true;
228
+ return $handler([
229
+ 'http_method' => 'GET',
230
+ 'uri' => '/',
231
+ 'headers' => ['host' => [Server::$host]],
232
+ 'client' => $opts,
233
+ ]);
234
+ }
235
+
236
+ public function testAddsProxy()
237
+ {
238
+ $res = $this->getSendResult(['stream' => true, 'proxy' => '127.0.0.1:8125']);
239
+ $opts = stream_context_get_options($res['body']);
240
+ $this->assertEquals('127.0.0.1:8125', $opts['http']['proxy']);
241
+ }
242
+
243
+ public function testAddsTimeout()
244
+ {
245
+ $res = $this->getSendResult(['stream' => true, 'timeout' => 200]);
246
+ $opts = stream_context_get_options($res['body']);
247
+ $this->assertEquals(200, $opts['http']['timeout']);
248
+ }
249
+
250
+ public function testVerifiesVerifyIsValidIfPath()
251
+ {
252
+ $res = $this->getSendResult(['verify' => '/does/not/exist']);
253
+ $this->assertContains(
254
+ 'SSL CA bundle not found: /does/not/exist',
255
+ (string) $res['error']
256
+ );
257
+ }
258
+
259
+ public function testVerifyCanBeDisabled()
260
+ {
261
+ $res = $this->getSendResult(['verify' => false]);
262
+ $this->assertArrayNotHasKey('error', $res);
263
+ }
264
+
265
+ public function testVerifiesCertIfValidPath()
266
+ {
267
+ $res = $this->getSendResult(['cert' => '/does/not/exist']);
268
+ $this->assertContains(
269
+ 'SSL certificate not found: /does/not/exist',
270
+ (string) $res['error']
271
+ );
272
+ }
273
+
274
+ public function testVerifyCanBeSetToPath()
275
+ {
276
+ $path = $path = ClientUtils::getDefaultCaBundle();
277
+ $res = $this->getSendResult(['verify' => $path]);
278
+ $this->assertArrayNotHasKey('error', $res);
279
+ $opts = stream_context_get_options($res['body']);
280
+ $this->assertEquals(true, $opts['ssl']['verify_peer']);
281
+ $this->assertEquals($path, $opts['ssl']['cafile']);
282
+ $this->assertTrue(file_exists($opts['ssl']['cafile']));
283
+ }
284
+
285
+ public function testUsesSystemDefaultBundle()
286
+ {
287
+ $path = $path = ClientUtils::getDefaultCaBundle();
288
+ $res = $this->getSendResult(['verify' => true]);
289
+ $this->assertArrayNotHasKey('error', $res);
290
+ $opts = stream_context_get_options($res['body']);
291
+ if (PHP_VERSION_ID < 50600) {
292
+ $this->assertEquals($path, $opts['ssl']['cafile']);
293
+ }
294
+ }
295
+
296
+ public function testEnsuresVerifyOptionIsValid()
297
+ {
298
+ $res = $this->getSendResult(['verify' => 10]);
299
+ $this->assertContains(
300
+ 'Invalid verify request option',
301
+ (string) $res['error']
302
+ );
303
+ }
304
+
305
+ public function testCanSetPasswordWhenSettingCert()
306
+ {
307
+ $path = __FILE__;
308
+ $res = $this->getSendResult(['cert' => [$path, 'foo']]);
309
+ $opts = stream_context_get_options($res['body']);
310
+ $this->assertEquals($path, $opts['ssl']['local_cert']);
311
+ $this->assertEquals('foo', $opts['ssl']['passphrase']);
312
+ }
313
+
314
+ public function testDebugAttributeWritesToStream()
315
+ {
316
+ $this->queueRes();
317
+ $f = fopen('php://temp', 'w+');
318
+ $this->getSendResult(['debug' => $f]);
319
+ fseek($f, 0);
320
+ $contents = stream_get_contents($f);
321
+ $this->assertContains('<GET http://127.0.0.1:8125/> [CONNECT]', $contents);
322
+ $this->assertContains('<GET http://127.0.0.1:8125/> [FILE_SIZE_IS]', $contents);
323
+ $this->assertContains('<GET http://127.0.0.1:8125/> [PROGRESS]', $contents);
324
+ }
325
+
326
+ public function testDebugAttributeWritesStreamInfoToBuffer()
327
+ {
328
+ $called = false;
329
+ $this->queueRes();
330
+ $buffer = fopen('php://temp', 'r+');
331
+ $this->getSendResult([
332
+ 'progress' => function () use (&$called) { $called = true; },
333
+ 'debug' => $buffer,
334
+ ]);
335
+ fseek($buffer, 0);
336
+ $contents = stream_get_contents($buffer);
337
+ $this->assertContains('<GET http://127.0.0.1:8125/> [CONNECT]', $contents);
338
+ $this->assertContains('<GET http://127.0.0.1:8125/> [FILE_SIZE_IS] message: "Content-Length: 8"', $contents);
339
+ $this->assertContains('<GET http://127.0.0.1:8125/> [PROGRESS] bytes_max: "8"', $contents);
340
+ $this->assertTrue($called);
341
+ }
342
+
343
+ public function testEmitsProgressInformation()
344
+ {
345
+ $called = [];
346
+ $this->queueRes();
347
+ $this->getSendResult([
348
+ 'progress' => function () use (&$called) {
349
+ $called[] = func_get_args();
350
+ },
351
+ ]);
352
+ $this->assertNotEmpty($called);
353
+ $this->assertEquals(8, $called[0][0]);
354
+ $this->assertEquals(0, $called[0][1]);
355
+ }
356
+
357
+ public function testEmitsProgressInformationAndDebugInformation()
358
+ {
359
+ $called = [];
360
+ $this->queueRes();
361
+ $buffer = fopen('php://memory', 'w+');
362
+ $this->getSendResult([
363
+ 'debug' => $buffer,
364
+ 'progress' => function () use (&$called) {
365
+ $called[] = func_get_args();
366
+ },
367
+ ]);
368
+ $this->assertNotEmpty($called);
369
+ $this->assertEquals(8, $called[0][0]);
370
+ $this->assertEquals(0, $called[0][1]);
371
+ rewind($buffer);
372
+ $this->assertNotEmpty(stream_get_contents($buffer));
373
+ fclose($buffer);
374
+ }
375
+
376
+ public function testAddsProxyByProtocol()
377
+ {
378
+ $url = str_replace('http', 'tcp', Server::$url);
379
+ $res = $this->getSendResult(['proxy' => ['http' => $url]]);
380
+ $opts = stream_context_get_options($res['body']);
381
+ $this->assertEquals($url, $opts['http']['proxy']);
382
+ }
383
+
384
+ public function testPerformsShallowMergeOfCustomContextOptions()
385
+ {
386
+ $res = $this->getSendResult([
387
+ 'stream_context' => [
388
+ 'http' => [
389
+ 'request_fulluri' => true,
390
+ 'method' => 'HEAD',
391
+ ],
392
+ 'socket' => [
393
+ 'bindto' => '127.0.0.1:0',
394
+ ],
395
+ 'ssl' => [
396
+ 'verify_peer' => false,
397
+ ],
398
+ ],
399
+ ]);
400
+
401
+ $opts = stream_context_get_options($res['body']);
402
+ $this->assertEquals('HEAD', $opts['http']['method']);
403
+ $this->assertTrue($opts['http']['request_fulluri']);
404
+ $this->assertFalse($opts['ssl']['verify_peer']);
405
+ $this->assertEquals('127.0.0.1:0', $opts['socket']['bindto']);
406
+ }
407
+
408
+ public function testEnsuresThatStreamContextIsAnArray()
409
+ {
410
+ $res = $this->getSendResult(['stream_context' => 'foo']);
411
+ $this->assertContains(
412
+ 'stream_context must be an array',
413
+ (string) $res['error']
414
+ );
415
+ }
416
+
417
+ public function testDoesNotAddContentTypeByDefault()
418
+ {
419
+ $this->queueRes();
420
+ $handler = new StreamHandler();
421
+ $handler([
422
+ 'http_method' => 'PUT',
423
+ 'uri' => '/',
424
+ 'headers' => ['host' => [Server::$host], 'content-length' => [3]],
425
+ 'body' => 'foo',
426
+ ]);
427
+ $req = Server::received()[0];
428
+ $this->assertEquals('', Core::header($req, 'Content-Type'));
429
+ $this->assertEquals(3, Core::header($req, 'Content-Length'));
430
+ }
431
+
432
+ private function queueRes()
433
+ {
434
+ Server::flush();
435
+ Server::enqueue([
436
+ [
437
+ 'status' => 200,
438
+ 'reason' => 'OK',
439
+ 'headers' => [
440
+ 'Foo' => ['Bar'],
441
+ 'Content-Length' => [8],
442
+ ],
443
+ 'body' => 'hi there',
444
+ ],
445
+ ]);
446
+ }
447
+
448
+ public function testSupports100Continue()
449
+ {
450
+ Server::flush();
451
+ Server::enqueue([
452
+ [
453
+ 'status' => '200',
454
+ 'reason' => 'OK',
455
+ 'headers' => [
456
+ 'Test' => ['Hello'],
457
+ 'Content-Length' => ['4'],
458
+ ],
459
+ 'body' => 'test',
460
+ ],
461
+ ]);
462
+
463
+ $request = [
464
+ 'http_method' => 'PUT',
465
+ 'headers' => [
466
+ 'Host' => [Server::$host],
467
+ 'Expect' => ['100-Continue'],
468
+ ],
469
+ 'body' => 'test',
470
+ ];
471
+
472
+ $handler = new StreamHandler();
473
+ $response = $handler($request);
474
+ $this->assertEquals(200, $response['status']);
475
+ $this->assertEquals('OK', $response['reason']);
476
+ $this->assertEquals(['Hello'], $response['headers']['Test']);
477
+ $this->assertEquals(['4'], $response['headers']['Content-Length']);
478
+ $this->assertEquals('test', Core::body($response));
479
+ }
480
+ }
vendor/guzzlehttp/ringphp/tests/Client/server.js ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Guzzle node.js test server to return queued responses to HTTP requests and
3
+ * expose a RESTful API for enqueueing responses and retrieving the requests
4
+ * that have been received.
5
+ *
6
+ * - Delete all requests that have been received:
7
+ * > DELETE /guzzle-server/requests
8
+ * > Host: 127.0.0.1:8125
9
+ *
10
+ * - Enqueue responses
11
+ * > PUT /guzzle-server/responses
12
+ * > Host: 127.0.0.1:8125
13
+ * >
14
+ * > [{'status': 200, 'reason': 'OK', 'headers': {}, 'body': '' }]
15
+ *
16
+ * - Get the received requests
17
+ * > GET /guzzle-server/requests
18
+ * > Host: 127.0.0.1:8125
19
+ *
20
+ * < HTTP/1.1 200 OK
21
+ * <
22
+ * < [{'http_method': 'GET', 'uri': '/', 'headers': {}, 'body': 'string'}]
23
+ *
24
+ * - Attempt access to the secure area
25
+ * > GET /secure/by-digest/qop-auth/guzzle-server/requests
26
+ * > Host: 127.0.0.1:8125
27
+ *
28
+ * < HTTP/1.1 401 Unauthorized
29
+ * < WWW-Authenticate: Digest realm="Digest Test", qop="auth", nonce="0796e98e1aeef43141fab2a66bf4521a", algorithm="MD5", stale="false"
30
+ * <
31
+ * < 401 Unauthorized
32
+ *
33
+ * - Shutdown the server
34
+ * > DELETE /guzzle-server
35
+ * > Host: 127.0.0.1:8125
36
+ *
37
+ * @package Guzzle PHP <http://www.guzzlephp.org>
38
+ * @license See the LICENSE file that was distributed with this source code.
39
+ */
40
+
41
+ var http = require('http');
42
+ var url = require('url');
43
+
44
+ /**
45
+ * Guzzle node.js server
46
+ * @class
47
+ */
48
+ var GuzzleServer = function(port, log) {
49
+
50
+ this.port = port;
51
+ this.log = log;
52
+ this.responses = [];
53
+ this.requests = [];
54
+ var that = this;
55
+
56
+ var md5 = function(input) {
57
+ var crypto = require('crypto');
58
+ var hasher = crypto.createHash('md5');
59
+ hasher.update(input);
60
+ return hasher.digest('hex');
61
+ }
62
+
63
+ /**
64
+ * Node.js HTTP server authentication module.
65
+ *
66
+ * It is only initialized on demand (by loadAuthentifier). This avoids
67
+ * requiring the dependency to http-auth on standard operations, and the
68
+ * performance hit at startup.
69
+ */
70
+ var auth;
71
+
72
+ /**
73
+ * Provides authentication handlers (Basic, Digest).
74
+ */
75
+ var loadAuthentifier = function(type, options) {
76
+ var typeId = type;
77
+ if (type == 'digest') {
78
+ typeId += '.'+(options && options.qop ? options.qop : 'none');
79
+ }
80
+ if (!loadAuthentifier[typeId]) {
81
+ if (!auth) {
82
+ try {
83
+ auth = require('http-auth');
84
+ } catch (e) {
85
+ if (e.code == 'MODULE_NOT_FOUND') {
86
+ return;
87
+ }
88
+ }
89
+ }
90
+ switch (type) {
91
+ case 'digest':
92
+ var digestParams = {
93
+ realm: 'Digest Test',
94
+ login: 'me',
95
+ password: 'test'
96
+ };
97
+ if (options && options.qop) {
98
+ digestParams.qop = options.qop;
99
+ }
100
+ loadAuthentifier[typeId] = auth.digest(digestParams, function(username, callback) {
101
+ callback(md5(digestParams.login + ':' + digestParams.realm + ':' + digestParams.password));
102
+ });
103
+ break
104
+ }
105
+ }
106
+ return loadAuthentifier[typeId];
107
+ };
108
+
109
+ var firewallRequest = function(request, req, res, requestHandlerCallback) {
110
+ var securedAreaUriParts = request.uri.match(/^\/secure\/by-(digest)(\/qop-([^\/]*))?(\/.*)$/);
111
+ if (securedAreaUriParts) {
112
+ var authentifier = loadAuthentifier(securedAreaUriParts[1], { qop: securedAreaUriParts[2] });
113
+ if (!authentifier) {
114
+ res.writeHead(501, 'HTTP authentication not implemented', { 'Content-Length': 0 });
115
+ res.end();
116
+ return;
117
+ }
118
+ authentifier.check(req, res, function(req, res) {
119
+ req.url = securedAreaUriParts[4];
120
+ requestHandlerCallback(request, req, res);
121
+ });
122
+ } else {
123
+ requestHandlerCallback(request, req, res);
124
+ }
125
+ };
126
+
127
+ var controlRequest = function(request, req, res) {
128
+ if (req.url == '/guzzle-server/perf') {
129
+ res.writeHead(200, 'OK', {'Content-Length': 16});
130
+ res.end('Body of response');
131
+ } else if (req.method == 'DELETE') {
132
+ if (req.url == '/guzzle-server/requests') {
133
+ // Clear the received requests
134
+ that.requests = [];
135
+ res.writeHead(200, 'OK', { 'Content-Length': 0 });
136
+ res.end();
137
+ if (that.log) {
138
+ console.log('Flushing requests');
139
+ }
140
+ } else if (req.url == '/guzzle-server') {
141
+ // Shutdown the server
142
+ res.writeHead(200, 'OK', { 'Content-Length': 0, 'Connection': 'close' });
143
+ res.end();
144
+ if (that.log) {
145
+ console.log('Shutting down');
146
+ }
147
+ that.server.close();
148
+ }
149
+ } else if (req.method == 'GET') {
150
+ if (req.url === '/guzzle-server/requests') {
151
+ if (that.log) {
152
+ console.log('Sending received requests');
153
+ }
154
+ // Get received requests
155
+ var body = JSON.stringify(that.requests);
156
+ res.writeHead(200, 'OK', { 'Content-Length': body.length });
157
+ res.end(body);
158
+ }
159
+ } else if (req.method == 'PUT' && req.url == '/guzzle-server/responses') {
160
+ if (that.log) {
161
+ console.log('Adding responses...');
162
+ }
163
+ if (!request.body) {
164
+ if (that.log) {
165
+ console.log('No response data was provided');
166
+ }
167
+ res.writeHead(400, 'NO RESPONSES IN REQUEST', { 'Content-Length': 0 });
168
+ } else {
169
+ that.responses = eval('(' + request.body + ')');
170
+ for (var i = 0; i < that.responses.length; i++) {
171
+ if (that.responses[i].body) {
172
+ that.responses[i].body = new Buffer(that.responses[i].body, 'base64');
173
+ }
174
+ }
175
+ if (that.log) {
176
+ console.log(that.responses);
177
+ }
178
+ res.writeHead(200, 'OK', { 'Content-Length': 0 });
179
+ }
180
+ res.end();
181
+ }
182
+ };
183
+
184
+ var receivedRequest = function(request, req, res) {
185
+ if (req.url.indexOf('/guzzle-server') === 0) {
186
+ controlRequest(request, req, res);
187
+ } else if (req.url.indexOf('/guzzle-server') == -1 && !that.responses.length) {
188
+ res.writeHead(500);
189
+ res.end('No responses in queue');
190
+ } else {
191
+ if (that.log) {
192
+ console.log('Returning response from queue and adding request');
193
+ }
194
+ that.requests.push(request);
195
+ var response = that.responses.shift();
196
+ res.writeHead(response.status, response.reason, response.headers);
197
+ res.end(response.body);
198
+ }
199
+ };
200
+
201
+ this.start = function() {
202
+
203
+ that.server = http.createServer(function(req, res) {
204
+
205
+ var parts = url.parse(req.url, false);
206
+ var request = {
207
+ http_method: req.method,
208
+ scheme: parts.scheme,
209
+ uri: parts.pathname,
210
+ query_string: parts.query,
211
+ headers: req.headers,
212
+ version: req.httpVersion,
213
+ body: ''
214
+ };
215
+
216
+ // Receive each chunk of the request body
217
+ req.addListener('data', function(chunk) {
218
+ request.body += chunk;
219
+ });
220
+
221
+ // Called when the request completes
222
+ req.addListener('end', function() {
223
+ firewallRequest(request, req, res, receivedRequest);
224
+ });
225
+ });
226
+
227
+ that.server.listen(this.port, '127.0.0.1');
228
+
229
+ if (this.log) {
230
+ console.log('Server running at http://127.0.0.1:8125/');
231
+ }
232
+ };
233
+ };
234
+
235
+ // Get the port from the arguments
236
+ port = process.argv.length >= 3 ? process.argv[2] : 8125;
237
+ log = process.argv.length >= 4 ? process.argv[3] : false;
238
+
239
+ // Start the server
240
+ server = new GuzzleServer(port, log);
241
+ server.start();
vendor/guzzlehttp/ringphp/tests/CoreTest.php ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring;
3
+
4
+ use GuzzleHttp\Ring\Core;
5
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
6
+ use GuzzleHttp\Ring\Future\FutureArray;
7
+ use GuzzleHttp\Stream\Stream;
8
+ use React\Promise\Deferred;
9
+
10
+ class CoreTest extends \PHPUnit_Framework_TestCase
11
+ {
12
+ public function testReturnsNullNoHeadersAreSet()
13
+ {
14
+ $this->assertNull(Core::header([], 'Foo'));
15
+ $this->assertNull(Core::firstHeader([], 'Foo'));
16
+ }
17
+
18
+ public function testChecksIfHasHeader()
19
+ {
20
+ $message = [
21
+ 'headers' => [
22
+ 'Foo' => ['Bar', 'Baz'],
23
+ 'foo' => ['hello'],
24
+ 'bar' => ['1']
25
+ ]
26
+ ];
27
+ $this->assertTrue(Core::hasHeader($message, 'Foo'));
28
+ $this->assertTrue(Core::hasHeader($message, 'foo'));
29
+ $this->assertTrue(Core::hasHeader($message, 'FoO'));
30
+ $this->assertTrue(Core::hasHeader($message, 'bar'));
31
+ $this->assertFalse(Core::hasHeader($message, 'barr'));
32
+ }
33
+
34
+ public function testReturnsFirstHeaderWhenSimple()
35
+ {
36
+ $this->assertEquals('Bar', Core::firstHeader([
37
+ 'headers' => ['Foo' => ['Bar', 'Baz']],
38
+ ], 'Foo'));
39
+ }
40
+
41
+ public function testReturnsFirstHeaderWhenMultiplePerLine()
42
+ {
43
+ $this->assertEquals('Bar', Core::firstHeader([
44
+ 'headers' => ['Foo' => ['Bar, Baz']],
45
+ ], 'Foo'));
46
+ }
47
+
48
+ public function testExtractsCaseInsensitiveHeader()
49
+ {
50
+ $this->assertEquals(
51
+ 'hello',
52
+ Core::header(['headers' => ['foo' => ['hello']]], 'FoO')
53
+ );
54
+ }
55
+
56
+ public function testExtractsCaseInsensitiveHeaderLines()
57
+ {
58
+ $this->assertEquals(
59
+ ['a', 'b', 'c', 'd'],
60
+ Core::headerLines([
61
+ 'headers' => [
62
+ 'foo' => ['a', 'b'],
63
+ 'Foo' => ['c', 'd']
64
+ ]
65
+ ], 'foo')
66
+ );
67
+ }
68
+
69
+ public function testExtractsHeaderLines()
70
+ {
71
+ $this->assertEquals(
72
+ ['bar', 'baz'],
73
+ Core::headerLines([
74
+ 'headers' => [
75
+ 'Foo' => ['bar', 'baz'],
76
+ ],
77
+ ], 'Foo')
78
+ );
79
+ }
80
+
81
+ public function testExtractsHeaderAsString()
82
+ {
83
+ $this->assertEquals(
84
+ 'bar, baz',
85
+ Core::header([
86
+ 'headers' => [
87
+ 'Foo' => ['bar', 'baz'],
88
+ ],
89
+ ], 'Foo', true)
90
+ );
91
+ }
92
+
93
+ public function testReturnsNullWhenHeaderNotFound()
94
+ {
95
+ $this->assertNull(Core::header(['headers' => []], 'Foo'));
96
+ }
97
+
98
+ public function testRemovesHeaders()
99
+ {
100
+ $message = [
101
+ 'headers' => [
102
+ 'foo' => ['bar'],
103
+ 'Foo' => ['bam'],
104
+ 'baz' => ['123'],
105
+ ],
106
+ ];
107
+
108
+ $this->assertSame($message, Core::removeHeader($message, 'bam'));
109
+ $this->assertEquals([
110
+ 'headers' => ['baz' => ['123']],
111
+ ], Core::removeHeader($message, 'foo'));
112
+ }
113
+
114
+ public function testCreatesUrl()
115
+ {
116
+ $req = [
117
+ 'scheme' => 'http',
118
+ 'headers' => ['host' => ['foo.com']],
119
+ 'uri' => '/',
120
+ ];
121
+
122
+ $this->assertEquals('http://foo.com/', Core::url($req));
123
+ }
124
+
125
+ /**
126
+ * @expectedException \InvalidArgumentException
127
+ * @expectedExceptionMessage No Host header was provided
128
+ */
129
+ public function testEnsuresHostIsAvailableWhenCreatingUrls()
130
+ {
131
+ Core::url([]);
132
+ }
133
+
134
+ public function testCreatesUrlWithQueryString()
135
+ {
136
+ $req = [
137
+ 'scheme' => 'http',
138
+ 'headers' => ['host' => ['foo.com']],
139
+ 'uri' => '/',
140
+ 'query_string' => 'foo=baz',
141
+ ];
142
+
143
+ $this->assertEquals('http://foo.com/?foo=baz', Core::url($req));
144
+ }
145
+
146
+ public function testUsesUrlIfSet()
147
+ {
148
+ $req = ['url' => 'http://foo.com'];
149
+ $this->assertEquals('http://foo.com', Core::url($req));
150
+ }
151
+
152
+ public function testReturnsNullWhenNoBody()
153
+ {
154
+ $this->assertNull(Core::body([]));
155
+ }
156
+
157
+ public function testReturnsStreamAsString()
158
+ {
159
+ $this->assertEquals(
160
+ 'foo',
161
+ Core::body(['body' => Stream::factory('foo')])
162
+ );
163
+ }
164
+
165
+ public function testReturnsString()
166
+ {
167
+ $this->assertEquals('foo', Core::body(['body' => 'foo']));
168
+ }
169
+
170
+ public function testReturnsResourceContent()
171
+ {
172
+ $r = fopen('php://memory', 'w+');
173
+ fwrite($r, 'foo');
174
+ rewind($r);
175
+ $this->assertEquals('foo', Core::body(['body' => $r]));
176
+ fclose($r);
177
+ }
178
+
179
+ public function testReturnsIteratorContent()
180
+ {
181
+ $a = new \ArrayIterator(['a', 'b', 'cd', '']);
182
+ $this->assertEquals('abcd', Core::body(['body' => $a]));
183
+ }
184
+
185
+ public function testReturnsObjectToString()
186
+ {
187
+ $this->assertEquals('foo', Core::body(['body' => new StrClass]));
188
+ }
189
+
190
+ /**
191
+ * @expectedException \InvalidArgumentException
192
+ */
193
+ public function testEnsuresBodyIsValid()
194
+ {
195
+ Core::body(['body' => false]);
196
+ }
197
+
198
+ public function testParsesHeadersFromLines()
199
+ {
200
+ $lines = ['Foo: bar', 'Foo: baz', 'Abc: 123', 'Def: a, b'];
201
+ $this->assertEquals([
202
+ 'Foo' => ['bar', 'baz'],
203
+ 'Abc' => ['123'],
204
+ 'Def' => ['a, b'],
205
+ ], Core::headersFromLines($lines));
206
+ }
207
+
208
+ public function testParsesHeadersFromLinesWithMultipleLines()
209
+ {
210
+ $lines = ['Foo: bar', 'Foo: baz', 'Foo: 123'];
211
+ $this->assertEquals([
212
+ 'Foo' => ['bar', 'baz', '123'],
213
+ ], Core::headersFromLines($lines));
214
+ }
215
+
216
+ public function testCreatesArrayCallFunctions()
217
+ {
218
+ $called = [];
219
+ $a = function ($a, $b) use (&$called) {
220
+ $called['a'] = func_get_args();
221
+ };
222
+ $b = function ($a, $b) use (&$called) {
223
+ $called['b'] = func_get_args();
224
+ };
225
+ $c = Core::callArray([$a, $b]);
226
+ $c(1, 2);
227
+ $this->assertEquals([1, 2], $called['a']);
228
+ $this->assertEquals([1, 2], $called['b']);
229
+ }
230
+
231
+ public function testRewindsGuzzleStreams()
232
+ {
233
+ $str = Stream::factory('foo');
234
+ $this->assertTrue(Core::rewindBody(['body' => $str]));
235
+ }
236
+
237
+ public function testRewindsStreams()
238
+ {
239
+ $str = Stream::factory('foo')->detach();
240
+ $this->assertTrue(Core::rewindBody(['body' => $str]));
241
+ }
242
+
243
+ public function testRewindsIterators()
244
+ {
245
+ $iter = new \ArrayIterator(['foo']);
246
+ $this->assertTrue(Core::rewindBody(['body' => $iter]));
247
+ }
248
+
249
+ public function testRewindsStrings()
250
+ {
251
+ $this->assertTrue(Core::rewindBody(['body' => 'hi']));
252
+ }
253
+
254
+ public function testRewindsToStrings()
255
+ {
256
+ $this->assertTrue(Core::rewindBody(['body' => new StrClass()]));
257
+ }
258
+
259
+ public function typeProvider()
260
+ {
261
+ return [
262
+ ['foo', 'string(3) "foo"'],
263
+ [true, 'bool(true)'],
264
+ [false, 'bool(false)'],
265
+ [10, 'int(10)'],
266
+ [1.0, 'float(1)'],
267
+ [new StrClass(), 'object(GuzzleHttp\Tests\Ring\StrClass)'],
268
+ [['foo'], 'array(1)']
269
+ ];
270
+ }
271
+
272
+ /**
273
+ * @dataProvider typeProvider
274
+ */
275
+ public function testDescribesType($input, $output)
276
+ {
277
+ $this->assertEquals($output, Core::describeType($input));
278
+ }
279
+
280
+ public function testDoesSleep()
281
+ {
282
+ $t = microtime(true);
283
+ $expected = $t + (100 / 1000);
284
+ Core::doSleep(['client' => ['delay' => 100]]);
285
+ $this->assertGreaterThanOrEqual($expected, microtime(true));
286
+ }
287
+
288
+ public function testProxiesFuture()
289
+ {
290
+ $f = new CompletedFutureArray(['status' => 200]);
291
+ $res = null;
292
+ $proxied = Core::proxy($f, function ($value) use (&$res) {
293
+ $value['foo'] = 'bar';
294
+ $res = $value;
295
+ return $value;
296
+ });
297
+ $this->assertNotSame($f, $proxied);
298
+ $this->assertEquals(200, $f->wait()['status']);
299
+ $this->assertArrayNotHasKey('foo', $f->wait());
300
+ $this->assertEquals('bar', $proxied->wait()['foo']);
301
+ $this->assertEquals(200, $proxied->wait()['status']);
302
+ }
303
+
304
+ public function testProxiesDeferredFuture()
305
+ {
306
+ $d = new Deferred();
307
+ $f = new FutureArray($d->promise());
308
+ $f2 = Core::proxy($f);
309
+ $d->resolve(['foo' => 'bar']);
310
+ $this->assertEquals('bar', $f['foo']);
311
+ $this->assertEquals('bar', $f2['foo']);
312
+ }
313
+
314
+ public function testProxiesDeferredFutureFailure()
315
+ {
316
+ $d = new Deferred();
317
+ $f = new FutureArray($d->promise());
318
+ $f2 = Core::proxy($f);
319
+ $d->reject(new \Exception('foo'));
320
+ try {
321
+ $f2['hello?'];
322
+ $this->fail('did not throw');
323
+ } catch (\Exception $e) {
324
+ $this->assertEquals('foo', $e->getMessage());
325
+ }
326
+
327
+ }
328
+ }
329
+
330
+ final class StrClass
331
+ {
332
+ public function __toString()
333
+ {
334
+ return 'foo';
335
+ }
336
+ }
vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Future;
3
+
4
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
5
+
6
+ class CompletedFutureArrayTest extends \PHPUnit_Framework_TestCase
7
+ {
8
+ public function testReturnsAsArray()
9
+ {
10
+ $f = new CompletedFutureArray(['foo' => 'bar']);
11
+ $this->assertEquals('bar', $f['foo']);
12
+ $this->assertFalse(isset($f['baz']));
13
+ $f['abc'] = '123';
14
+ $this->assertTrue(isset($f['abc']));
15
+ $this->assertEquals(['foo' => 'bar', 'abc' => '123'], iterator_to_array($f));
16
+ $this->assertEquals(2, count($f));
17
+ unset($f['abc']);
18
+ $this->assertEquals(1, count($f));
19
+ $this->assertEquals(['foo' => 'bar'], iterator_to_array($f));
20
+ }
21
+ }
vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Future;
3
+
4
+ use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
5
+ use GuzzleHttp\Ring\Future\CompletedFutureValue;
6
+
7
+ class CompletedFutureValueTest extends \PHPUnit_Framework_TestCase
8
+ {
9
+ public function testReturnsValue()
10
+ {
11
+ $f = new CompletedFutureValue('hi');
12
+ $this->assertEquals('hi', $f->wait());
13
+ $f->cancel();
14
+
15
+ $a = null;
16
+ $f->then(function ($v) use (&$a) {
17
+ $a = $v;
18
+ });
19
+ $this->assertSame('hi', $a);
20
+ }
21
+
22
+ public function testThrows()
23
+ {
24
+ $ex = new \Exception('foo');
25
+ $f = new CompletedFutureValue(null, $ex);
26
+ $f->cancel();
27
+ try {
28
+ $f->wait();
29
+ $this->fail('did not throw');
30
+ } catch (\Exception $e) {
31
+ $this->assertSame($e, $ex);
32
+ }
33
+ }
34
+
35
+ public function testMarksAsCancelled()
36
+ {
37
+ $ex = new CancelledFutureAccessException();
38
+ $f = new CompletedFutureValue(null, $ex);
39
+ try {
40
+ $f->wait();
41
+ $this->fail('did not throw');
42
+ } catch (\Exception $e) {
43
+ $this->assertSame($e, $ex);
44
+ }
45
+ }
46
+ }
vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Future;
3
+
4
+ use GuzzleHttp\Ring\Future\FutureArray;
5
+ use React\Promise\Deferred;
6
+
7
+ class FutureArrayTest extends \PHPUnit_Framework_TestCase
8
+ {
9
+ public function testLazilyCallsDeref()
10
+ {
11
+ $c = false;
12
+ $deferred = new Deferred();
13
+ $f = new FutureArray(
14
+ $deferred->promise(),
15
+ function () use (&$c, $deferred) {
16
+ $c = true;
17
+ $deferred->resolve(['status' => 200]);
18
+ }
19
+ );
20
+ $this->assertFalse($c);
21
+ $this->assertFalse($this->readAttribute($f, 'isRealized'));
22
+ $this->assertEquals(200, $f['status']);
23
+ $this->assertTrue($c);
24
+ }
25
+
26
+ public function testActsLikeArray()
27
+ {
28
+ $deferred = new Deferred();
29
+ $f = new FutureArray(
30
+ $deferred->promise(),
31
+ function () use (&$c, $deferred) {
32
+ $deferred->resolve(['status' => 200]);
33
+ }
34
+ );
35
+
36
+ $this->assertTrue(isset($f['status']));
37
+ $this->assertEquals(200, $f['status']);
38
+ $this->assertEquals(['status' => 200], $f->wait());
39
+ $this->assertEquals(1, count($f));
40
+ $f['baz'] = 10;
41
+ $this->assertEquals(10, $f['baz']);
42
+ unset($f['baz']);
43
+ $this->assertFalse(isset($f['baz']));
44
+ $this->assertEquals(['status' => 200], iterator_to_array($f));
45
+ }
46
+
47
+ /**
48
+ * @expectedException \RuntimeException
49
+ */
50
+ public function testThrowsWhenAccessingInvalidProperty()
51
+ {
52
+ $deferred = new Deferred();
53
+ $f = new FutureArray($deferred->promise(), function () {});
54
+ $f->foo;
55
+ }
56
+ }
vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Ring\Future;
3
+
4
+ use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
5
+ use GuzzleHttp\Ring\Future\FutureValue;
6
+ use React\Promise\Deferred;
7
+
8
+ class FutureValueTest extends \PHPUnit_Framework_TestCase
9
+ {
10
+ public function testDerefReturnsValue()
11
+ {
12
+ $called = 0;
13
+ $deferred = new Deferred();
14
+
15
+ $f = new FutureValue(
16
+ $deferred->promise(),
17
+ function () use ($deferred, &$called) {
18
+ $called++;
19
+ $deferred->resolve('foo');
20
+ }
21
+ );
22
+
23
+ $this->assertEquals('foo', $f->wait());
24
+ $this->assertEquals(1, $called);
25
+ $this->assertEquals('foo', $f->wait());
26
+ $this->assertEquals(1, $called);
27
+ $f->cancel();
28
+ $this->assertTrue($this->readAttribute($f, 'isRealized'));
29
+ }
30
+
31
+ /**
32
+ * @expectedException \GuzzleHttp\Ring\Exception\CancelledFutureAccessException
33
+ */
34
+ public function testThrowsWhenAccessingCancelled()
35
+ {
36
+ $f = new FutureValue(
37
+ (new Deferred())->promise(),
38
+ function () {},
39
+ function () { return true; }
40
+ );
41
+ $f->cancel();
42
+ $f->wait();
43
+ }
44
+
45
+ /**
46
+ * @expectedException \OutOfBoundsException
47
+ */
48
+ public function testThrowsWhenDerefFailure()
49
+ {
50
+ $called = false;
51
+ $deferred = new Deferred();
52
+ $f = new FutureValue(
53
+ $deferred->promise(),
54
+ function () use(&$called) {
55
+ $called = true;
56
+ }
57
+ );
58
+ $deferred->reject(new \OutOfBoundsException());
59
+ $f->wait();
60
+ $this->assertFalse($called);
61
+ }
62
+
63
+ /**
64
+ * @expectedException \GuzzleHttp\Ring\Exception\RingException
65
+ * @expectedExceptionMessage Waiting did not resolve future
66
+ */
67
+ public function testThrowsWhenDerefDoesNotResolve()
68
+ {
69
+ $deferred = new Deferred();
70
+ $f = new FutureValue(
71
+ $deferred->promise(),
72
+ function () use(&$called) {
73
+ $called = true;
74
+ }
75
+ );
76
+ $f->wait();
77
+ }
78
+
79
+ public function testThrowingCancelledFutureAccessExceptionCancels()
80
+ {
81
+ $deferred = new Deferred();
82
+ $f = new FutureValue(
83
+ $deferred->promise(),
84
+ function () use ($deferred) {
85
+ throw new CancelledFutureAccessException();
86
+ }
87
+ );
88
+ try {
89
+ $f->wait();
90
+ $this->fail('did not throw');
91
+ } catch (CancelledFutureAccessException $e) {}
92
+ }
93
+
94
+ /**
95
+ * @expectedException \Exception
96
+ * @expectedExceptionMessage foo
97
+ */
98
+ public function testThrowingExceptionInDerefMarksAsFailed()
99
+ {
100
+ $deferred = new Deferred();
101
+ $f = new FutureValue(
102
+ $deferred->promise(),
103
+ function () {
104
+ throw new \Exception('foo');
105
+ }
106
+ );
107
+ $f->wait();
108
+ }
109
+ }
vendor/guzzlehttp/ringphp/tests/bootstrap.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require __DIR__ . '/../vendor/autoload.php';
3
+ require __DIR__ . '/Client/Server.php';
4
+
5
+ use GuzzleHttp\Tests\Ring\Client\Server;
6
+
7
+ Server::start();
8
+
9
+ register_shutdown_function(function () {
10
+ Server::stop();
11
+ });
vendor/guzzlehttp/streams/.travis.yml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+
3
+ php:
4
+ - 5.4
5
+ - 5.5
6
+ - 5.6
7
+ - hhvm
8
+
9
+ before_script:
10
+ - composer self-update
11
+ - composer install --no-interaction --prefer-source --dev
12
+
13
+ script: vendor/bin/phpunit
14
+
15
+ matrix:
16
+ allow_failures:
17
+ - php: hhvm
vendor/guzzlehttp/streams/CHANGELOG.rst ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =========
2
+ Changelog
3
+ =========
4
+
5
+ 3.0.0 (2014-10-12)
6
+ ------------------
7
+
8
+ * Now supports creating streams from functions and iterators.
9
+ * Supports creating buffered streams and asynchronous streams.
10
+ * Removed ``functions.php``. Use the corresponding functions provided by
11
+ ``GuzzleHttp\Streams\Utils`` instead.
12
+ * Moved ``GuzzleHttp\Stream\MetadataStreamInterface::getMetadata`` to
13
+ ``GuzzleHttp\Stream\StreamInterface``. MetadataStreamInterface is no longer
14
+ used and is marked as deprecated.
15
+ * Added ``attach()`` to ``GuzzleHttp\Stream\StreamInterface`` for PSR-7
16
+ compatibility.
17
+ * Removed ``flush()`` from StreamInterface.
18
+ * Removed the ``$maxLength`` parameter from
19
+ ``GuzzleHttp\Stream\StreamInterface::getContents()``. This function now
20
+ returns the entire remainder of the stream. If you want to limit the maximum
21
+ amount of data read from the stream, use the
22
+ ``GuzzleHttp\Stream\Utils::copyToString()`` function.
23
+ * Streams that return an empty string, ``''``, are no longer considered a
24
+ failure. You MUST return ``false`` to mark the read as a failure, and ensure
25
+ that any decorators you create properly return ``true`` in response to the
26
+ ``eof()`` method when the stream is consumed.
27
+ * ``GuzzleHttp\Stream\Stream::__construct``,
28
+ ``GuzzleHttp\Stream\Stream::factory``, and
29
+ ``GuzzleHttp\Stream\Utils::create`` no longer accept a size in the second
30
+ argument. They now accept an associative array of options, including the
31
+ "size" key and "metadata" key which can be used to provide custom metadata.
32
+ * Added ``GuzzleHttp\Stream\BufferStream`` to add support for buffering data,
33
+ and when read, shifting data off of the buffer.
34
+ * Added ``GuzzleHttp\Stream\NullBuffer`` which can be used as a buffer that
35
+ does not actually store any data.
36
+ * Added ``GuzzleHttp\Stream\AsyncStream`` to provide support for non-blocking
37
+ streams that can be filled by a remote source (e.g., an event-loop). If a
38
+ ``drain`` option is provided, the stream can also act as if it is a blocking
39
+ stream.
40
+
41
+ 2.1.0 (2014-08-17)
42
+ ------------------
43
+
44
+ * Added an InflateStream to inflate gzipped or deflated content.
45
+ * Added ``flush`` to stream wrapper.
46
+ * Added the ability to easily register the GuzzleStreamWrapper if needed.
47
+
48
+ 2.0.0 (2014-08-16)
49
+ ------------------
50
+
51
+ * Deprecated functions.php and moved all of those methods to
52
+ ``GuzzleHttp\Streams\Utils``. Use ``GuzzleHttp\Stream\Stream::factory()``
53
+ instead of ``GuzzleHttp\Stream\create()`` to create new streams.
54
+ * Added ``flush()`` to ``StreamInterface``. This method is used to flush any
55
+ underlying stream write buffers.
56
+ * Added ``FnStream`` to easily decorate stream behavior with callables.
57
+ * ``Utils::hash`` now throws an exception when the stream cannot seek to 0.
58
+
59
+ 1.5.1 (2014-09-10)
60
+ ------------------
61
+
62
+ * Stream metadata is grabbed from the underlying stream each time
63
+ ``getMetadata`` is called rather than returning a value from a cache.
64
+ * Properly closing all underlying streams when AppendStream is closed.
65
+ * Seek functions no longer throw exceptions.
66
+ * LazyOpenStream now correctly returns the underlying stream resource when
67
+ detached.
68
+
69
+ 1.5.0 (2014-08-07)
70
+ ------------------
71
+
72
+ * Added ``Stream\safe_open`` to open stream resources and throw exceptions
73
+ instead of raising errors.
74
+
75
+ 1.4.0 (2014-07-19)
76
+ ------------------
77
+
78
+ * Added a LazyOpenStream
79
+
80
+ 1.3.0 (2014-07-15)
81
+ ------------------
82
+
83
+ * Added an AppendStream to stream over multiple stream one after the other.
84
+
85
+ 1.2.0 (2014-07-15)
86
+ ------------------
87
+
88
+ * Updated the ``detach()`` method to return the underlying stream resource or
89
+ ``null`` if it does not wrap a resource.
90
+ * Multiple fixes for how streams behave when the underlying resource is
91
+ detached
92
+ * Do not clear statcache when a stream does not have a 'uri'
93
+ * Added a fix to LimitStream
94
+ * Added a condition to ensure that functions.php can be required multiple times
vendor/guzzlehttp/streams/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/streams/Makefile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ all: clean coverage
2
+
3
+ release: tag
4
+ git push origin --tags
5
+
6
+ tag:
7
+ chag tag --sign --debug CHANGELOG.rst
8
+
9
+ test:
10
+ vendor/bin/phpunit
11
+
12
+ coverage:
13
+ vendor/bin/phpunit --coverage-html=artifacts/coverage
14
+
15
+ view-coverage:
16
+ open artifacts/coverage/index.html
17
+
18
+ clean:
19
+ rm -rf artifacts/*
vendor/guzzlehttp/streams/README.rst ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ==============
2
+ Guzzle Streams
3
+ ==============
4
+
5
+ Provides a simple abstraction over streams of data.
6
+
7
+ This library is used in `Guzzle 5 <https://github.com/guzzle/guzzle>`_, and is
8
+ (currently) compatible with the WIP PSR-7.
9
+
10
+ Installation
11
+ ============
12
+
13
+ This package can be installed easily using `Composer <http://getcomposer.org>`_.
14
+ Simply add the following to the composer.json file at the root of your project:
15
+
16
+ .. code-block:: javascript
17
+
18
+ {
19
+ "require": {
20
+ "guzzlehttp/streams": "~3.0"
21
+ }
22
+ }
23
+
24
+ Then install your dependencies using ``composer.phar install``.
25
+
26
+ Documentation
27
+ =============
28
+
29
+ The documentation for this package can be found on the main Guzzle website at
30
+ http://docs.guzzlephp.org/en/guzzle4/streams.html.
31
+
32
+ Testing
33
+ =======
34
+
35
+ This library is tested using PHPUnit. You'll need to install the dependencies
36
+ using `Composer <http://getcomposer.org>`_ then run ``make test``.
vendor/guzzlehttp/streams/composer.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "guzzlehttp/streams",
3
+ "description": "Provides a simple abstraction over streams of data",
4
+ "homepage": "http://guzzlephp.org/",
5
+ "keywords": ["stream", "guzzle"],
6
+ "license": "MIT",
7
+ "authors": [
8
+ {
9
+ "name": "Michael Dowling",
10
+ "email": "mtdowling@gmail.com",
11
+ "homepage": "https://github.com/mtdowling"
12
+ }
13
+ ],
14
+ "require": {
15
+ "php": ">=5.4.0"
16
+ },
17
+ "require-dev": {
18
+ "phpunit/phpunit": "~4.0"
19
+ },
20
+ "autoload": {
21
+ "psr-4": { "GuzzleHttp\\Stream\\": "src/" }
22
+ },
23
+ "extra": {
24
+ "branch-alias": {
25
+ "dev-master": "3.0-dev"
26
+ }
27
+ }
28
+ }
vendor/guzzlehttp/streams/phpunit.xml.dist ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <phpunit bootstrap="./vendor/autoload.php"
3
+ colors="true">
4
+ <testsuites>
5
+ <testsuite>
6
+ <directory>tests</directory>
7
+ </testsuite>
8
+ </testsuites>
9
+ <filter>
10
+ <whitelist>
11
+ <directory suffix=".php">src</directory>
12
+ <exclude>
13
+ <file>src/functions.php</file>
14
+ </exclude>
15
+ </whitelist>
16
+ </filter>
17
+ </phpunit>
vendor/guzzlehttp/streams/src/AppendStream.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ use GuzzleHttp\Stream\Exception\CannotAttachException;
5
+
6
+ /**
7
+ * Reads from multiple streams, one after the other.
8
+ *
9
+ * This is a read-only stream decorator.
10
+ */
11
+ class AppendStream implements StreamInterface
12
+ {
13
+ /** @var StreamInterface[] Streams being decorated */
14
+ private $streams = [];
15
+
16
+ private $seekable = true;
17
+ private $current = 0;
18
+ private $pos = 0;
19
+ private $detached = false;
20
+
21
+ /**
22
+ * @param StreamInterface[] $streams Streams to decorate. Each stream must
23
+ * be readable.
24
+ */
25
+ public function __construct(array $streams = [])
26
+ {
27
+ foreach ($streams as $stream) {
28
+ $this->addStream($stream);
29
+ }
30
+ }
31
+
32
+ public function __toString()
33
+ {
34
+ try {
35
+ $this->seek(0);
36
+ return $this->getContents();
37
+ } catch (\Exception $e) {
38
+ return '';
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Add a stream to the AppendStream
44
+ *
45
+ * @param StreamInterface $stream Stream to append. Must be readable.
46
+ *
47
+ * @throws \InvalidArgumentException if the stream is not readable
48
+ */
49
+ public function addStream(StreamInterface $stream)
50
+ {
51
+ if (!$stream->isReadable()) {
52
+ throw new \InvalidArgumentException('Each stream must be readable');
53
+ }
54
+
55
+ // The stream is only seekable if all streams are seekable
56
+ if (!$stream->isSeekable()) {
57
+ $this->seekable = false;
58
+ }
59
+
60
+ $this->streams[] = $stream;
61
+ }
62
+
63
+ public function getContents()
64
+ {
65
+ return Utils::copyToString($this);
66
+ }
67
+
68
+ /**
69
+ * Closes each attached stream.
70
+ *
71
+ * {@inheritdoc}
72
+ */
73
+ public function close()
74
+ {
75
+ $this->pos = $this->current = 0;
76
+
77
+ foreach ($this->streams as $stream) {
78
+ $stream->close();
79
+ }
80
+
81
+ $this->streams = [];
82
+ }
83
+
84
+ /**
85
+ * Detaches each attached stream
86
+ *
87
+ * {@inheritdoc}
88
+ */
89
+ public function detach()
90
+ {
91
+ $this->close();
92
+ $this->detached = true;
93
+ }
94
+
95
+ public function attach($stream)
96
+ {
97
+ throw new CannotAttachException();
98
+ }
99
+
100
+ public function tell()
101
+ {
102
+ return $this->pos;
103
+ }
104
+
105
+ /**
106
+ * Tries to calculate the size by adding the size of each stream.
107
+ *
108
+ * If any of the streams do not return a valid number, then the size of the
109
+ * append stream cannot be determined and null is returned.
110
+ *
111
+ * {@inheritdoc}
112
+ */
113
+ public function getSize()
114
+ {
115
+ $size = 0;
116
+
117
+ foreach ($this->streams as $stream) {
118
+ $s = $stream->getSize();
119
+ if ($s === null) {
120
+ return null;
121
+ }
122
+ $size += $s;
123
+ }
124
+
125
+ return $size;
126
+ }
127
+
128
+ public function eof()
129
+ {
130
+ return !$this->streams ||
131
+ ($this->current >= count($this->streams) - 1 &&
132
+ $this->streams[$this->current]->eof());
133
+ }
134
+
135
+ /**
136
+ * Attempts to seek to the given position. Only supports SEEK_SET.
137
+ *
138
+ * {@inheritdoc}
139
+ */
140
+ public function seek($offset, $whence = SEEK_SET)
141
+ {
142
+ if (!$this->seekable || $whence !== SEEK_SET) {
143
+ return false;
144
+ }
145
+
146
+ $success = true;
147
+ $this->pos = $this->current = 0;
148
+
149
+ // Rewind each stream
150
+ foreach ($this->streams as $stream) {
151
+ if (!$stream->seek(0)) {
152
+ $success = false;
153
+ }
154
+ }
155
+
156
+ if (!$success) {
157
+ return false;
158
+ }
159
+
160
+ // Seek to the actual position by reading from each stream
161
+ while ($this->pos < $offset && !$this->eof()) {
162
+ $this->read(min(8096, $offset - $this->pos));
163
+ }
164
+
165
+ return $this->pos == $offset;
166
+ }
167
+
168
+ /**
169
+ * Reads from all of the appended streams until the length is met or EOF.
170
+ *
171
+ * {@inheritdoc}
172
+ */
173
+ public function read($length)
174
+ {
175
+ $buffer = '';
176
+ $total = count($this->streams) - 1;
177
+ $remaining = $length;
178
+
179
+ while ($remaining > 0) {
180
+ // Progress to the next stream if needed.
181
+ if ($this->streams[$this->current]->eof()) {
182
+ if ($this->current == $total) {
183
+ break;
184
+ }
185
+ $this->current++;
186
+ }
187
+ $buffer .= $this->streams[$this->current]->read($remaining);
188
+ $remaining = $length - strlen($buffer);
189
+ }
190
+
191
+ $this->pos += strlen($buffer);
192
+
193
+ return $buffer;
194
+ }
195
+
196
+ public function isReadable()
197
+ {
198
+ return true;
199
+ }
200
+
201
+ public function isWritable()
202
+ {
203
+ return false;
204
+ }
205
+
206
+ public function isSeekable()
207
+ {
208
+ return $this->seekable;
209
+ }
210
+
211
+ public function write($string)
212
+ {
213
+ return false;
214
+ }
215
+
216
+ public function getMetadata($key = null)
217
+ {
218
+ return $key ? null : [];
219
+ }
220
+ }
vendor/guzzlehttp/streams/src/AsyncReadStream.php ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Represents an asynchronous read-only stream that supports a drain event and
6
+ * pumping data from a source stream.
7
+ *
8
+ * The AsyncReadStream can be used as a completely asynchronous stream, meaning
9
+ * the data you can read from the stream will immediately return only
10
+ * the data that is currently buffered.
11
+ *
12
+ * AsyncReadStream can also be used in a "blocking" manner if a "pump" function
13
+ * is provided. When a caller requests more bytes than are available in the
14
+ * buffer, then the pump function is used to block until the requested number
15
+ * of bytes are available or the remote source stream has errored, closed, or
16
+ * timed-out. This behavior isn't strictly "blocking" because the pump function
17
+ * can send other transfers while waiting on the desired buffer size to be
18
+ * ready for reading (e.g., continue to tick an event loop).
19
+ *
20
+ * @unstable This class is subject to change.
21
+ */
22
+ class AsyncReadStream implements StreamInterface
23
+ {
24
+ use StreamDecoratorTrait;
25
+
26
+ /** @var callable|null Fn used to notify writers the buffer has drained */
27
+ private $drain;
28
+
29
+ /** @var callable|null Fn used to block for more data */
30
+ private $pump;
31
+
32
+ /** @var int|null Highwater mark of the underlying buffer */
33
+ private $hwm;
34
+
35
+ /** @var bool Whether or not drain needs to be called at some point */
36
+ private $needsDrain;
37
+
38
+ /** @var int The expected size of the remote source */
39
+ private $size;
40
+
41
+ /**
42
+ * In order to utilize high water marks to tell writers to slow down, the
43
+ * provided stream must answer to the "hwm" stream metadata variable,
44
+ * providing the high water mark. If no "hwm" metadata value is available,
45
+ * then the "drain" functionality is not utilized.
46
+ *
47
+ * This class accepts an associative array of configuration options.
48
+ *
49
+ * - drain: (callable) Function to invoke when the stream has drained,
50
+ * meaning the buffer is now writable again because the size of the
51
+ * buffer is at an acceptable level (e.g., below the high water mark).
52
+ * The function accepts a single argument, the buffer stream object that
53
+ * has drained.
54
+ * - pump: (callable) A function that accepts the number of bytes to read
55
+ * from the source stream. This function will block until all of the data
56
+ * that was requested has been read, EOF of the source stream, or the
57
+ * source stream is closed.
58
+ * - size: (int) The expected size in bytes of the data that will be read
59
+ * (if known up-front).
60
+ *
61
+ * @param StreamInterface $buffer Buffer that contains the data that has
62
+ * been read by the event loop.
63
+ * @param array $config Associative array of options.
64
+ *
65
+ * @throws \InvalidArgumentException if the buffer is not readable and
66
+ * writable.
67
+ */
68
+ public function __construct(
69
+ StreamInterface $buffer,
70
+ array $config = []
71
+ ) {
72
+ if (!$buffer->isReadable() || !$buffer->isWritable()) {
73
+ throw new \InvalidArgumentException(
74
+ 'Buffer must be readable and writable'
75
+ );
76
+ }
77
+
78
+ if (isset($config['size'])) {
79
+ $this->size = $config['size'];
80
+ }
81
+
82
+ static $callables = ['pump', 'drain'];
83
+ foreach ($callables as $check) {
84
+ if (isset($config[$check])) {
85
+ if (!is_callable($config[$check])) {
86
+ throw new \InvalidArgumentException(
87
+ $check . ' must be callable'
88
+ );
89
+ }
90
+ $this->{$check} = $config[$check];
91
+ }
92
+ }
93
+
94
+ $this->hwm = $buffer->getMetadata('hwm');
95
+
96
+ // Cannot drain when there's no high water mark.
97
+ if ($this->hwm === null) {
98
+ $this->drain = null;
99
+ }
100
+
101
+ $this->stream = $buffer;
102
+ }
103
+
104
+ /**
105
+ * Factory method used to create new async stream and an underlying buffer
106
+ * if no buffer is provided.
107
+ *
108
+ * This function accepts the same options as AsyncReadStream::__construct,
109
+ * but added the following key value pairs:
110
+ *
111
+ * - buffer: (StreamInterface) Buffer used to buffer data. If none is
112
+ * provided, a default buffer is created.
113
+ * - hwm: (int) High water mark to use if a buffer is created on your
114
+ * behalf.
115
+ * - max_buffer: (int) If provided, wraps the utilized buffer in a
116
+ * DroppingStream decorator to ensure that buffer does not exceed a given
117
+ * length. When exceeded, the stream will begin dropping data. Set the
118
+ * max_buffer to 0, to use a NullStream which does not store data.
119
+ * - write: (callable) A function that is invoked when data is written
120
+ * to the underlying buffer. The function accepts the buffer as the first
121
+ * argument, and the data being written as the second. The function MUST
122
+ * return the number of bytes that were written or false to let writers
123
+ * know to slow down.
124
+ * - drain: (callable) See constructor documentation.
125
+ * - pump: (callable) See constructor documentation.
126
+ *
127
+ * @param array $options Associative array of options.
128
+ *
129
+ * @return array Returns an array containing the buffer used to buffer
130
+ * data, followed by the ready to use AsyncReadStream object.
131
+ */
132
+ public static function create(array $options = [])
133
+ {
134
+ $maxBuffer = isset($options['max_buffer'])
135
+ ? $options['max_buffer']
136
+ : null;
137
+
138
+ if ($maxBuffer === 0) {
139
+ $buffer = new NullStream();
140
+ } elseif (isset($options['buffer'])) {
141
+ $buffer = $options['buffer'];
142
+ } else {
143
+ $hwm = isset($options['hwm']) ? $options['hwm'] : 16384;
144
+ $buffer = new BufferStream($hwm);
145
+ }
146
+
147
+ if ($maxBuffer > 0) {
148
+ $buffer = new DroppingStream($buffer, $options['max_buffer']);
149
+ }
150
+
151
+ // Call the on_write callback if an on_write function was provided.
152
+ if (isset($options['write'])) {
153
+ $onWrite = $options['write'];
154
+ $buffer = FnStream::decorate($buffer, [
155
+ 'write' => function ($string) use ($buffer, $onWrite) {
156
+ $result = $buffer->write($string);
157
+ $onWrite($buffer, $string);
158
+ return $result;
159
+ }
160
+ ]);
161
+ }
162
+
163
+ return [$buffer, new self($buffer, $options)];
164
+ }
165
+
166
+ public function getSize()
167
+ {
168
+ return $this->size;
169
+ }
170
+
171
+ public function isWritable()
172
+ {
173
+ return false;
174
+ }
175
+
176
+ public function write($string)
177
+ {
178
+ return false;
179
+ }
180
+
181
+ public function read($length)
182
+ {
183
+ if (!$this->needsDrain && $this->drain) {
184
+ $this->needsDrain = $this->stream->getSize() >= $this->hwm;
185
+ }
186
+
187
+ $result = $this->stream->read($length);
188
+
189
+ // If we need to drain, then drain when the buffer is empty.
190
+ if ($this->needsDrain && $this->stream->getSize() === 0) {
191
+ $this->needsDrain = false;
192
+ $drainFn = $this->drain;
193
+ $drainFn($this->stream);
194
+ }
195
+
196
+ $resultLen = strlen($result);
197
+
198
+ // If a pump was provided, the buffer is still open, and not enough
199
+ // data was given, then block until the data is provided.
200
+ if ($this->pump && $resultLen < $length) {
201
+ $pumpFn = $this->pump;
202
+ $result .= $pumpFn($length - $resultLen);
203
+ }
204
+
205
+ return $result;
206
+ }
207
+ }
vendor/guzzlehttp/streams/src/BufferStream.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ use GuzzleHttp\Stream\Exception\CannotAttachException;
5
+
6
+ /**
7
+ * Provides a buffer stream that can be written to to fill a buffer, and read
8
+ * from to remove bytes from the buffer.
9
+ *
10
+ * This stream returns a "hwm" metadata value that tells upstream consumers
11
+ * what the configured high water mark of the stream is, or the maximum
12
+ * preferred size of the buffer.
13
+ *
14
+ * @package GuzzleHttp\Stream
15
+ */
16
+ class BufferStream implements StreamInterface
17
+ {
18
+ private $hwm;
19
+ private $buffer = '';
20
+
21
+ /**
22
+ * @param int $hwm High water mark, representing the preferred maximum
23
+ * buffer size. If the size of the buffer exceeds the high
24
+ * water mark, then calls to write will continue to succeed
25
+ * but will return false to inform writers to slow down
26
+ * until the buffer has been drained by reading from it.
27
+ */
28
+ public function __construct($hwm = 16384)
29
+ {
30
+ $this->hwm = $hwm;
31
+ }
32
+
33
+ public function __toString()
34
+ {
35
+ return $this->getContents();
36
+ }
37
+
38
+ public function getContents()
39
+ {
40
+ $buffer = $this->buffer;
41
+ $this->buffer = '';
42
+
43
+ return $buffer;
44
+ }
45
+
46
+ public function close()
47
+ {
48
+ $this->buffer = '';
49
+ }
50
+
51
+ public function detach()
52
+ {
53
+ $this->close();
54
+ }
55
+
56
+ public function attach($stream)
57
+ {
58
+ throw new CannotAttachException();
59
+ }
60
+
61
+ public function getSize()
62
+ {
63
+ return strlen($this->buffer);
64
+ }
65
+
66
+ public function isReadable()
67
+ {
68
+ return true;
69
+ }
70
+
71
+ public function isWritable()
72
+ {
73
+ return true;
74
+ }
75
+
76
+ public function isSeekable()
77
+ {
78
+ return false;
79
+ }
80
+
81
+ public function seek($offset, $whence = SEEK_SET)
82
+ {
83
+ return false;
84
+ }
85
+
86
+ public function eof()
87
+ {
88
+ return strlen($this->buffer) === 0;
89
+ }
90
+
91
+ public function tell()
92
+ {
93
+ return false;
94
+ }
95
+
96
+ /**
97
+ * Reads data from the buffer.
98
+ */
99
+ public function read($length)
100
+ {
101
+ $currentLength = strlen($this->buffer);
102
+
103
+ if ($length >= $currentLength) {
104
+ // No need to slice the buffer because we don't have enough data.
105
+ $result = $this->buffer;
106
+ $this->buffer = '';
107
+ } else {
108
+ // Slice up the result to provide a subset of the buffer.
109
+ $result = substr($this->buffer, 0, $length);
110
+ $this->buffer = substr($this->buffer, $length);
111
+ }
112
+
113
+ return $result;
114
+ }
115
+
116
+ /**
117
+ * Writes data to the buffer.
118
+ */
119
+ public function write($string)
120
+ {
121
+ $this->buffer .= $string;
122
+
123
+ if (strlen($this->buffer) >= $this->hwm) {
124
+ return false;
125
+ }
126
+
127
+ return strlen($string);
128
+ }
129
+
130
+ public function getMetadata($key = null)
131
+ {
132
+ if ($key == 'hwm') {
133
+ return $this->hwm;
134
+ }
135
+
136
+ return $key ? null : [];
137
+ }
138
+ }
vendor/guzzlehttp/streams/src/CachingStream.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ use GuzzleHttp\Stream\Exception\SeekException;
5
+
6
+ /**
7
+ * Stream decorator that can cache previously read bytes from a sequentially
8
+ * read stream.
9
+ */
10
+ class CachingStream implements StreamInterface
11
+ {
12
+ use StreamDecoratorTrait;
13
+
14
+ /** @var StreamInterface Stream being wrapped */
15
+ private $remoteStream;
16
+
17
+ /** @var int Number of bytes to skip reading due to a write on the buffer */
18
+ private $skipReadBytes = 0;
19
+
20
+ /**
21
+ * We will treat the buffer object as the body of the stream
22
+ *
23
+ * @param StreamInterface $stream Stream to cache
24
+ * @param StreamInterface $target Optionally specify where data is cached
25
+ */
26
+ public function __construct(
27
+ StreamInterface $stream,
28
+ StreamInterface $target = null
29
+ ) {
30
+ $this->remoteStream = $stream;
31
+ $this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
32
+ }
33
+
34
+ public function getSize()
35
+ {
36
+ return max($this->stream->getSize(), $this->remoteStream->getSize());
37
+ }
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ * @throws SeekException When seeking with SEEK_END or when seeking
42
+ * past the total size of the buffer stream
43
+ */
44
+ public function seek($offset, $whence = SEEK_SET)
45
+ {
46
+ if ($whence == SEEK_SET) {
47
+ $byte = $offset;
48
+ } elseif ($whence == SEEK_CUR) {
49
+ $byte = $offset + $this->tell();
50
+ } else {
51
+ return false;
52
+ }
53
+
54
+ // You cannot skip ahead past where you've read from the remote stream
55
+ if ($byte > $this->stream->getSize()) {
56
+ throw new SeekException(
57
+ $this,
58
+ $byte,
59
+ sprintf('Cannot seek to byte %d when the buffered stream only'
60
+ . ' contains %d bytes', $byte, $this->stream->getSize())
61
+ );
62
+ }
63
+
64
+ return $this->stream->seek($byte);
65
+ }
66
+
67
+ public function read($length)
68
+ {
69
+ // Perform a regular read on any previously read data from the buffer
70
+ $data = $this->stream->read($length);
71
+ $remaining = $length - strlen($data);
72
+
73
+ // More data was requested so read from the remote stream
74
+ if ($remaining) {
75
+ // If data was written to the buffer in a position that would have
76
+ // been filled from the remote stream, then we must skip bytes on
77
+ // the remote stream to emulate overwriting bytes from that
78
+ // position. This mimics the behavior of other PHP stream wrappers.
79
+ $remoteData = $this->remoteStream->read(
80
+ $remaining + $this->skipReadBytes
81
+ );
82
+
83
+ if ($this->skipReadBytes) {
84
+ $len = strlen($remoteData);
85
+ $remoteData = substr($remoteData, $this->skipReadBytes);
86
+ $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
87
+ }
88
+
89
+ $data .= $remoteData;
90
+ $this->stream->write($remoteData);
91
+ }
92
+
93
+ return $data;
94
+ }
95
+
96
+ public function write($string)
97
+ {
98
+ // When appending to the end of the currently read stream, you'll want
99
+ // to skip bytes from being read from the remote stream to emulate
100
+ // other stream wrappers. Basically replacing bytes of data of a fixed
101
+ // length.
102
+ $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
103
+ if ($overflow > 0) {
104
+ $this->skipReadBytes += $overflow;
105
+ }
106
+
107
+ return $this->stream->write($string);
108
+ }
109
+
110
+ public function eof()
111
+ {
112
+ return $this->stream->eof() && $this->remoteStream->eof();
113
+ }
114
+
115
+ /**
116
+ * Close both the remote stream and buffer stream
117
+ */
118
+ public function close()
119
+ {
120
+ $this->remoteStream->close() && $this->stream->close();
121
+ }
122
+ }
vendor/guzzlehttp/streams/src/DroppingStream.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Stream decorator that begins dropping data once the size of the underlying
6
+ * stream becomes too full.
7
+ */
8
+ class DroppingStream implements StreamInterface
9
+ {
10
+ use StreamDecoratorTrait;
11
+
12
+ private $maxLength;
13
+
14
+ /**
15
+ * @param StreamInterface $stream Underlying stream to decorate.
16
+ * @param int $maxLength Maximum size before dropping data.
17
+ */
18
+ public function __construct(StreamInterface $stream, $maxLength)
19
+ {
20
+ $this->stream = $stream;
21
+ $this->maxLength = $maxLength;
22
+ }
23
+
24
+ public function write($string)
25
+ {
26
+ $diff = $this->maxLength - $this->stream->getSize();
27
+
28
+ // Begin returning false when the underlying stream is too large.
29
+ if ($diff <= 0) {
30
+ return false;
31
+ }
32
+
33
+ // Write the stream or a subset of the stream if needed.
34
+ if (strlen($string) < $diff) {
35
+ return $this->stream->write($string);
36
+ }
37
+
38
+ $this->stream->write(substr($string, 0, $diff));
39
+
40
+ return false;
41
+ }
42
+ }
vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream\Exception;
3
+
4
+ class CannotAttachException extends \RuntimeException {}
vendor/guzzlehttp/streams/src/Exception/SeekException.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream\Exception;
3
+
4
+ use GuzzleHttp\Stream\StreamInterface;
5
+
6
+ /**
7
+ * Exception thrown when a seek fails on a stream.
8
+ */
9
+ class SeekException extends \RuntimeException
10
+ {
11
+ private $stream;
12
+
13
+ public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
14
+ {
15
+ $this->stream = $stream;
16
+ $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
17
+ parent::__construct($msg);
18
+ }
19
+
20
+ /**
21
+ * @return StreamInterface
22
+ */
23
+ public function getStream()
24
+ {
25
+ return $this->stream;
26
+ }
27
+ }
vendor/guzzlehttp/streams/src/FnStream.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Compose stream implementations based on a hash of functions.
6
+ *
7
+ * Allows for easy testing and extension of a provided stream without needing
8
+ * to create a concrete class for a simple extension point.
9
+ */
10
+ class FnStream implements StreamInterface
11
+ {
12
+ /** @var array */
13
+ private $methods;
14
+
15
+ /** @var array Methods that must be implemented in the given array */
16
+ private static $slots = ['__toString', 'close', 'detach', 'attach',
17
+ 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
18
+ 'isReadable', 'read', 'getContents', 'getMetadata'];
19
+
20
+ /**
21
+ * @param array $methods Hash of method name to a callable.
22
+ */
23
+ public function __construct(array $methods)
24
+ {
25
+ $this->methods = $methods;
26
+
27
+ // Create the functions on the class
28
+ foreach ($methods as $name => $fn) {
29
+ $this->{'_fn_' . $name} = $fn;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Lazily determine which methods are not implemented.
35
+ * @throws \BadMethodCallException
36
+ */
37
+ public function __get($name)
38
+ {
39
+ throw new \BadMethodCallException(str_replace('_fn_', '', $name)
40
+ . '() is not implemented in the FnStream');
41
+ }
42
+
43
+ /**
44
+ * The close method is called on the underlying stream only if possible.
45
+ */
46
+ public function __destruct()
47
+ {
48
+ if (isset($this->_fn_close)) {
49
+ call_user_func($this->_fn_close);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Adds custom functionality to an underlying stream by intercepting
55
+ * specific method calls.
56
+ *
57
+ * @param StreamInterface $stream Stream to decorate
58
+ * @param array $methods Hash of method name to a closure
59
+ *
60
+ * @return FnStream
61
+ */
62
+ public static function decorate(StreamInterface $stream, array $methods)
63
+ {
64
+ // If any of the required methods were not provided, then simply
65
+ // proxy to the decorated stream.
66
+ foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
67
+ $methods[$diff] = [$stream, $diff];
68
+ }
69
+
70
+ return new self($methods);
71
+ }
72
+
73
+ public function __toString()
74
+ {
75
+ return call_user_func($this->_fn___toString);
76
+ }
77
+
78
+ public function close()
79
+ {
80
+ return call_user_func($this->_fn_close);
81
+ }
82
+
83
+ public function detach()
84
+ {
85
+ return call_user_func($this->_fn_detach);
86
+ }
87
+
88
+ public function attach($stream)
89
+ {
90
+ return call_user_func($this->_fn_attach, $stream);
91
+ }
92
+
93
+ public function getSize()
94
+ {
95
+ return call_user_func($this->_fn_getSize);
96
+ }
97
+
98
+ public function tell()
99
+ {
100
+ return call_user_func($this->_fn_tell);
101
+ }
102
+
103
+ public function eof()
104
+ {
105
+ return call_user_func($this->_fn_eof);
106
+ }
107
+
108
+ public function isSeekable()
109
+ {
110
+ return call_user_func($this->_fn_isSeekable);
111
+ }
112
+
113
+ public function seek($offset, $whence = SEEK_SET)
114
+ {
115
+ return call_user_func($this->_fn_seek, $offset, $whence);
116
+ }
117
+
118
+ public function isWritable()
119
+ {
120
+ return call_user_func($this->_fn_isWritable);
121
+ }
122
+
123
+ public function write($string)
124
+ {
125
+ return call_user_func($this->_fn_write, $string);
126
+ }
127
+
128
+ public function isReadable()
129
+ {
130
+ return call_user_func($this->_fn_isReadable);
131
+ }
132
+
133
+ public function read($length)
134
+ {
135
+ return call_user_func($this->_fn_read, $length);
136
+ }
137
+
138
+ public function getContents()
139
+ {
140
+ return call_user_func($this->_fn_getContents);
141
+ }
142
+
143
+ public function getMetadata($key = null)
144
+ {
145
+ return call_user_func($this->_fn_getMetadata, $key);
146
+ }
147
+ }
vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Converts Guzzle streams into PHP stream resources.
6
+ */
7
+ class GuzzleStreamWrapper
8
+ {
9
+ /** @var resource */
10
+ public $context;
11
+
12
+ /** @var StreamInterface */
13
+ private $stream;
14
+
15
+ /** @var string r, r+, or w */
16
+ private $mode;
17
+
18
+ /**
19
+ * Returns a resource representing the stream.
20
+ *
21
+ * @param StreamInterface $stream The stream to get a resource for
22
+ *
23
+ * @return resource
24
+ * @throws \InvalidArgumentException if stream is not readable or writable
25
+ */
26
+ public static function getResource(StreamInterface $stream)
27
+ {
28
+ self::register();
29
+
30
+ if ($stream->isReadable()) {
31
+ $mode = $stream->isWritable() ? 'r+' : 'r';
32
+ } elseif ($stream->isWritable()) {
33
+ $mode = 'w';
34
+ } else {
35
+ throw new \InvalidArgumentException('The stream must be readable, '
36
+ . 'writable, or both.');
37
+ }
38
+
39
+ return fopen('guzzle://stream', $mode, null, stream_context_create([
40
+ 'guzzle' => ['stream' => $stream]
41
+ ]));
42
+ }
43
+
44
+ /**
45
+ * Registers the stream wrapper if needed
46
+ */
47
+ public static function register()
48
+ {
49
+ if (!in_array('guzzle', stream_get_wrappers())) {
50
+ stream_wrapper_register('guzzle', __CLASS__);
51
+ }
52
+ }
53
+
54
+ public function stream_open($path, $mode, $options, &$opened_path)
55
+ {
56
+ $options = stream_context_get_options($this->context);
57
+
58
+ if (!isset($options['guzzle']['stream'])) {
59
+ return false;
60
+ }
61
+
62
+ $this->mode = $mode;
63
+ $this->stream = $options['guzzle']['stream'];
64
+
65
+ return true;
66
+ }
67
+
68
+ public function stream_read($count)
69
+ {
70
+ return $this->stream->read($count);
71
+ }
72
+
73
+ public function stream_write($data)
74
+ {
75
+ return (int) $this->stream->write($data);
76
+ }
77
+
78
+ public function stream_tell()
79
+ {
80
+ return $this->stream->tell();
81
+ }
82
+
83
+ public function stream_eof()
84
+ {
85
+ return $this->stream->eof();
86
+ }
87
+
88
+ public function stream_seek($offset, $whence)
89
+ {
90
+ return $this->stream->seek($offset, $whence);
91
+ }
92
+
93
+ public function stream_stat()
94
+ {
95
+ static $modeMap = [
96
+ 'r' => 33060,
97
+ 'r+' => 33206,
98
+ 'w' => 33188
99
+ ];
100
+
101
+ return [
102
+ 'dev' => 0,
103
+ 'ino' => 0,
104
+ 'mode' => $modeMap[$this->mode],
105
+ 'nlink' => 0,
106
+ 'uid' => 0,
107
+ 'gid' => 0,
108
+ 'rdev' => 0,
109
+ 'size' => $this->stream->getSize() ?: 0,
110
+ 'atime' => 0,
111
+ 'mtime' => 0,
112
+ 'ctime' => 0,
113
+ 'blksize' => 0,
114
+ 'blocks' => 0
115
+ ];
116
+ }
117
+ }
vendor/guzzlehttp/streams/src/InflateStream.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
6
+ *
7
+ * This stream decorator skips the first 10 bytes of the given stream to remove
8
+ * the gzip header, converts the provided stream to a PHP stream resource,
9
+ * then appends the zlib.inflate filter. The stream is then converted back
10
+ * to a Guzzle stream resource to be used as a Guzzle stream.
11
+ *
12
+ * @link http://tools.ietf.org/html/rfc1952
13
+ * @link http://php.net/manual/en/filters.compression.php
14
+ */
15
+ class InflateStream implements StreamInterface
16
+ {
17
+ use StreamDecoratorTrait;
18
+
19
+ public function __construct(StreamInterface $stream)
20
+ {
21
+ // Skip the first 10 bytes
22
+ $stream = new LimitStream($stream, -1, 10);
23
+ $resource = GuzzleStreamWrapper::getResource($stream);
24
+ stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
25
+ $this->stream = new Stream($resource);
26
+ }
27
+ }
vendor/guzzlehttp/streams/src/LazyOpenStream.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Lazily reads or writes to a file that is opened only after an IO operation
6
+ * take place on the stream.
7
+ */
8
+ class LazyOpenStream implements StreamInterface
9
+ {
10
+ use StreamDecoratorTrait;
11
+
12
+ /** @var string File to open */
13
+ private $filename;
14
+
15
+ /** @var string $mode */
16
+ private $mode;
17
+
18
+ /**
19
+ * @param string $filename File to lazily open
20
+ * @param string $mode fopen mode to use when opening the stream
21
+ */
22
+ public function __construct($filename, $mode)
23
+ {
24
+ $this->filename = $filename;
25
+ $this->mode = $mode;
26
+ }
27
+
28
+ /**
29
+ * Creates the underlying stream lazily when required.
30
+ *
31
+ * @return StreamInterface
32
+ */
33
+ protected function createStream()
34
+ {
35
+ return Stream::factory(Utils::open($this->filename, $this->mode));
36
+ }
37
+ }
vendor/guzzlehttp/streams/src/LimitStream.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ use GuzzleHttp\Stream\Exception\SeekException;
5
+
6
+ /**
7
+ * Decorator used to return only a subset of a stream
8
+ */
9
+ class LimitStream implements StreamInterface
10
+ {
11
+ use StreamDecoratorTrait;
12
+
13
+ /** @var int Offset to start reading from */
14
+ private $offset;
15
+
16
+ /** @var int Limit the number of bytes that can be read */
17
+ private $limit;
18
+
19
+ /**
20
+ * @param StreamInterface $stream Stream to wrap
21
+ * @param int $limit Total number of bytes to allow to be read
22
+ * from the stream. Pass -1 for no limit.
23
+ * @param int|null $offset Position to seek to before reading (only
24
+ * works on seekable streams).
25
+ */
26
+ public function __construct(
27
+ StreamInterface $stream,
28
+ $limit = -1,
29
+ $offset = 0
30
+ ) {
31
+ $this->stream = $stream;
32
+ $this->setLimit($limit);
33
+ $this->setOffset($offset);
34
+ }
35
+
36
+ public function eof()
37
+ {
38
+ // Always return true if the underlying stream is EOF
39
+ if ($this->stream->eof()) {
40
+ return true;
41
+ }
42
+
43
+ // No limit and the underlying stream is not at EOF
44
+ if ($this->limit == -1) {
45
+ return false;
46
+ }
47
+
48
+ $tell = $this->stream->tell();
49
+ if ($tell === false) {
50
+ return false;
51
+ }
52
+
53
+ return $tell >= $this->offset + $this->limit;
54
+ }
55
+
56
+ /**
57
+ * Returns the size of the limited subset of data
58
+ * {@inheritdoc}
59
+ */
60
+ public function getSize()
61
+ {
62
+ if (null === ($length = $this->stream->getSize())) {
63
+ return null;
64
+ } elseif ($this->limit == -1) {
65
+ return $length - $this->offset;
66
+ } else {
67
+ return min($this->limit, $length - $this->offset);
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Allow for a bounded seek on the read limited stream
73
+ * {@inheritdoc}
74
+ */
75
+ public function seek($offset, $whence = SEEK_SET)
76
+ {
77
+ if ($whence !== SEEK_SET || $offset < 0) {
78
+ return false;
79
+ }
80
+
81
+ $offset += $this->offset;
82
+
83
+ if ($this->limit !== -1) {
84
+ if ($offset > $this->offset + $this->limit) {
85
+ $offset = $this->offset + $this->limit;
86
+ }
87
+ }
88
+
89
+ return $this->stream->seek($offset);
90
+ }
91
+
92
+ /**
93
+ * Give a relative tell()
94
+ * {@inheritdoc}
95
+ */
96
+ public function tell()
97
+ {
98
+ return $this->stream->tell() - $this->offset;
99
+ }
100
+
101
+ /**
102
+ * Set the offset to start limiting from
103
+ *
104
+ * @param int $offset Offset to seek to and begin byte limiting from
105
+ *
106
+ * @return self
107
+ * @throws SeekException
108
+ */
109
+ public function setOffset($offset)
110
+ {
111
+ $current = $this->stream->tell();
112
+
113
+ if ($current !== $offset) {
114
+ // If the stream cannot seek to the offset position, then read to it
115
+ if (!$this->stream->seek($offset)) {
116
+ if ($current > $offset) {
117
+ throw new SeekException($this, $offset);
118
+ } else {
119
+ $this->stream->read($offset - $current);
120
+ }
121
+ }
122
+ }
123
+
124
+ $this->offset = $offset;
125
+
126
+ return $this;
127
+ }
128
+
129
+ /**
130
+ * Set the limit of bytes that the decorator allows to be read from the
131
+ * stream.
132
+ *
133
+ * @param int $limit Number of bytes to allow to be read from the stream.
134
+ * Use -1 for no limit.
135
+ * @return self
136
+ */
137
+ public function setLimit($limit)
138
+ {
139
+ $this->limit = $limit;
140
+
141
+ return $this;
142
+ }
143
+
144
+ public function read($length)
145
+ {
146
+ if ($this->limit == -1) {
147
+ return $this->stream->read($length);
148
+ }
149
+
150
+ // Check if the current position is less than the total allowed
151
+ // bytes + original offset
152
+ $remaining = ($this->offset + $this->limit) - $this->stream->tell();
153
+ if ($remaining > 0) {
154
+ // Only return the amount of requested data, ensuring that the byte
155
+ // limit is not exceeded
156
+ return $this->stream->read(min($remaining, $length));
157
+ } else {
158
+ return false;
159
+ }
160
+ }
161
+ }
vendor/guzzlehttp/streams/src/MetadataStreamInterface.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * This interface is deprecated and should no longer be used. Just use
6
+ * StreamInterface now that the getMetadata method has been added to
7
+ * StreamInterface.
8
+ *
9
+ * @deprecated
10
+ */
11
+ interface MetadataStreamInterface extends StreamInterface {}
vendor/guzzlehttp/streams/src/NoSeekStream.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Stream decorator that prevents a stream from being seeked
6
+ */
7
+ class NoSeekStream implements StreamInterface
8
+ {
9
+ use StreamDecoratorTrait;
10
+
11
+ public function seek($offset, $whence = SEEK_SET)
12
+ {
13
+ return false;
14
+ }
15
+
16
+ public function isSeekable()
17
+ {
18
+ return false;
19
+ }
20
+
21
+ public function attach($stream)
22
+ {
23
+ $this->stream->attach($stream);
24
+ }
25
+ }
vendor/guzzlehttp/streams/src/NullStream.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+ use GuzzleHttp\Stream\Exception\CannotAttachException;
4
+
5
+ /**
6
+ * Does not store any data written to it.
7
+ */
8
+ class NullStream implements StreamInterface
9
+ {
10
+ public function __toString()
11
+ {
12
+ return '';
13
+ }
14
+
15
+ public function getContents()
16
+ {
17
+ return '';
18
+ }
19
+
20
+ public function close() {}
21
+
22
+ public function detach() {}
23
+
24
+ public function attach($stream)
25
+ {
26
+ throw new CannotAttachException();
27
+ }
28
+
29
+ public function getSize()
30
+ {
31
+ return 0;
32
+ }
33
+
34
+ public function isReadable()
35
+ {
36
+ return true;
37
+ }
38
+
39
+ public function isWritable()
40
+ {
41
+ return true;
42
+ }
43
+
44
+ public function isSeekable()
45
+ {
46
+ return true;
47
+ }
48
+
49
+ public function eof()
50
+ {
51
+ return true;
52
+ }
53
+
54
+ public function tell()
55
+ {
56
+ return 0;
57
+ }
58
+
59
+ public function seek($offset, $whence = SEEK_SET)
60
+ {
61
+ return false;
62
+ }
63
+
64
+ public function read($length)
65
+ {
66
+ return false;
67
+ }
68
+
69
+ public function write($string)
70
+ {
71
+ return strlen($string);
72
+ }
73
+
74
+ public function getMetadata($key = null)
75
+ {
76
+ return $key ? null : [];
77
+ }
78
+ }
vendor/guzzlehttp/streams/src/PumpStream.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ use GuzzleHttp\Stream\Exception\CannotAttachException;
5
+
6
+ /**
7
+ * Provides a read only stream that pumps data from a PHP callable.
8
+ *
9
+ * When invoking the provided callable, the PumpStream will pass the amount of
10
+ * data requested to read to the callable. The callable can choose to ignore
11
+ * this value and return fewer or more bytes than requested. Any extra data
12
+ * returned by the provided callable is buffered internally until drained using
13
+ * the read() function of the PumpStream. The provided callable MUST return
14
+ * false when there is no more data to read.
15
+ */
16
+ class PumpStream implements StreamInterface
17
+ {
18
+ /** @var callable */
19
+ private $source;
20
+
21
+ /** @var int */
22
+ private $size;
23
+
24
+ /** @var int */
25
+ private $tellPos = 0;
26
+
27
+ /** @var array */
28
+ private $metadata;
29
+
30
+ /** @var BufferStream */
31
+ private $buffer;
32
+
33
+ /**
34
+ * @param callable $source Source of the stream data. The callable MAY
35
+ * accept an integer argument used to control the
36
+ * amount of data to return. The callable MUST
37
+ * return a string when called, or false on error
38
+ * or EOF.
39
+ * @param array $options Stream options:
40
+ * - metadata: Hash of metadata to use with stream.
41
+ * - size: Size of the stream, if known.
42
+ */
43
+ public function __construct(callable $source, array $options = [])
44
+ {
45
+ $this->source = $source;
46
+ $this->size = isset($options['size']) ? $options['size'] : null;
47
+ $this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
48
+ $this->buffer = new BufferStream();
49
+ }
50
+
51
+ public function __toString()
52
+ {
53
+ return Utils::copyToString($this);
54
+ }
55
+
56
+ public function close()
57
+ {
58
+ $this->detach();
59
+ }
60
+
61
+ public function detach()
62
+ {
63
+ $this->tellPos = false;
64
+ $this->source = null;
65
+ }
66
+
67
+ public function attach($stream)
68
+ {
69
+ throw new CannotAttachException();
70
+ }
71
+
72
+ public function getSize()
73
+ {
74
+ return $this->size;
75
+ }
76
+
77
+ public function tell()
78
+ {
79
+ return $this->tellPos;
80
+ }
81
+
82
+ public function eof()
83
+ {
84
+ return !$this->source;
85
+ }
86
+
87
+ public function isSeekable()
88
+ {
89
+ return false;
90
+ }
91
+
92
+ public function seek($offset, $whence = SEEK_SET)
93
+ {
94
+ return false;
95
+ }
96
+
97
+ public function isWritable()
98
+ {
99
+ return false;
100
+ }
101
+
102
+ public function write($string)
103
+ {
104
+ return false;
105
+ }
106
+
107
+ public function isReadable()
108
+ {
109
+ return true;
110
+ }
111
+
112
+ public function read($length)
113
+ {
114
+ $data = $this->buffer->read($length);
115
+ $readLen = strlen($data);
116
+ $this->tellPos += $readLen;
117
+ $remaining = $length - $readLen;
118
+
119
+ if ($remaining) {
120
+ $this->pump($remaining);
121
+ $data .= $this->buffer->read($remaining);
122
+ $this->tellPos += strlen($data) - $readLen;
123
+ }
124
+
125
+ return $data;
126
+ }
127
+
128
+ public function getContents()
129
+ {
130
+ $result = '';
131
+ while (!$this->eof()) {
132
+ $result .= $this->read(1000000);
133
+ }
134
+
135
+ return $result;
136
+ }
137
+
138
+ public function getMetadata($key = null)
139
+ {
140
+ if (!$key) {
141
+ return $this->metadata;
142
+ }
143
+
144
+ return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
145
+ }
146
+
147
+ private function pump($length)
148
+ {
149
+ if ($this->source) {
150
+ do {
151
+ $data = call_user_func($this->source, $length);
152
+ if ($data === false || $data === null) {
153
+ $this->source = null;
154
+ return;
155
+ }
156
+ $this->buffer->write($data);
157
+ $length -= strlen($data);
158
+ } while ($length > 0);
159
+ }
160
+ }
161
+ }
vendor/guzzlehttp/streams/src/Stream.php ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * PHP stream implementation
6
+ */
7
+ class Stream implements StreamInterface
8
+ {
9
+ private $stream;
10
+ private $size;
11
+ private $seekable;
12
+ private $readable;
13
+ private $writable;
14
+ private $uri;
15
+ private $customMetadata;
16
+
17
+ /** @var array Hash of readable and writable stream types */
18
+ private static $readWriteHash = [
19
+ 'read' => [
20
+ 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
21
+ 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
22
+ 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
23
+ 'x+t' => true, 'c+t' => true, 'a+' => true
24
+ ],
25
+ 'write' => [
26
+ 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
27
+ 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
28
+ 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
29
+ 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
30
+ ]
31
+ ];
32
+
33
+ /**
34
+ * Create a new stream based on the input type.
35
+ *
36
+ * This factory accepts the same associative array of options as described
37
+ * in the constructor.
38
+ *
39
+ * @param resource|string|StreamInterface $resource Entity body data
40
+ * @param array $options Additional options
41
+ *
42
+ * @return Stream
43
+ * @throws \InvalidArgumentException if the $resource arg is not valid.
44
+ */
45
+ public static function factory($resource = '', array $options = [])
46
+ {
47
+ $type = gettype($resource);
48
+
49
+ if ($type == 'string') {
50
+ $stream = fopen('php://temp', 'r+');
51
+ if ($resource !== '') {
52
+ fwrite($stream, $resource);
53
+ fseek($stream, 0);
54
+ }
55
+ return new self($stream, $options);
56
+ }
57
+
58
+ if ($type == 'resource') {
59
+ return new self($resource, $options);
60
+ }
61
+
62
+ if ($resource instanceof StreamInterface) {
63
+ return $resource;
64
+ }
65
+
66
+ if ($type == 'object' && method_exists($resource, '__toString')) {
67
+ return self::factory((string) $resource, $options);
68
+ }
69
+
70
+ if (is_callable($resource)) {
71
+ return new PumpStream($resource, $options);
72
+ }
73
+
74
+ if ($resource instanceof \Iterator) {
75
+ return new PumpStream(function () use ($resource) {
76
+ if (!$resource->valid()) {
77
+ return false;
78
+ }
79
+ $result = $resource->current();
80
+ $resource->next();
81
+ return $result;
82
+ }, $options);
83
+ }
84
+
85
+ throw new \InvalidArgumentException('Invalid resource type: ' . $type);
86
+ }
87
+
88
+ /**
89
+ * This constructor accepts an associative array of options.
90
+ *
91
+ * - size: (int) If a read stream would otherwise have an indeterminate
92
+ * size, but the size is known due to foreknownledge, then you can
93
+ * provide that size, in bytes.
94
+ * - metadata: (array) Any additional metadata to return when the metadata
95
+ * of the stream is accessed.
96
+ *
97
+ * @param resource $stream Stream resource to wrap.
98
+ * @param array $options Associative array of options.
99
+ *
100
+ * @throws \InvalidArgumentException if the stream is not a stream resource
101
+ */
102
+ public function __construct($stream, $options = [])
103
+ {
104
+ if (!is_resource($stream)) {
105
+ throw new \InvalidArgumentException('Stream must be a resource');
106
+ }
107
+
108
+ if (isset($options['size'])) {
109
+ $this->size = $options['size'];
110
+ }
111
+
112
+ $this->customMetadata = isset($options['metadata'])
113
+ ? $options['metadata']
114
+ : [];
115
+
116
+ $this->attach($stream);
117
+ }
118
+
119
+ /**
120
+ * Closes the stream when the destructed
121
+ */
122
+ public function __destruct()
123
+ {
124
+ $this->close();
125
+ }
126
+
127
+ public function __toString()
128
+ {
129
+ if (!$this->stream) {
130
+ return '';
131
+ }
132
+
133
+ $this->seek(0);
134
+
135
+ return (string) stream_get_contents($this->stream);
136
+ }
137
+
138
+ public function getContents()
139
+ {
140
+ return $this->stream ? stream_get_contents($this->stream) : '';
141
+ }
142
+
143
+ public function close()
144
+ {
145
+ if (is_resource($this->stream)) {
146
+ fclose($this->stream);
147
+ }
148
+
149
+ $this->detach();
150
+ }
151
+
152
+ public function detach()
153
+ {
154
+ $result = $this->stream;
155
+ $this->stream = $this->size = $this->uri = null;
156
+ $this->readable = $this->writable = $this->seekable = false;
157
+
158
+ return $result;
159
+ }
160
+
161
+ public function attach($stream)
162
+ {
163
+ $this->stream = $stream;
164
+ $meta = stream_get_meta_data($this->stream);
165
+ $this->seekable = $meta['seekable'];
166
+ $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
167
+ $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
168
+ $this->uri = $this->getMetadata('uri');
169
+ }
170
+
171
+ public function getSize()
172
+ {
173
+ if ($this->size !== null) {
174
+ return $this->size;
175
+ }
176
+
177
+ if (!$this->stream) {
178
+ return null;
179
+ }
180
+
181
+ // Clear the stat cache if the stream has a URI
182
+ if ($this->uri) {
183
+ clearstatcache(true, $this->uri);
184
+ }
185
+
186
+ $stats = fstat($this->stream);
187
+ if (isset($stats['size'])) {
188
+ $this->size = $stats['size'];
189
+ return $this->size;
190
+ }
191
+
192
+ return null;
193
+ }
194
+
195
+ public function isReadable()
196
+ {
197
+ return $this->readable;
198
+ }
199
+
200
+ public function isWritable()
201
+ {
202
+ return $this->writable;
203
+ }
204
+
205
+ public function isSeekable()
206
+ {
207
+ return $this->seekable;
208
+ }
209
+
210
+ public function eof()
211
+ {
212
+ return !$this->stream || feof($this->stream);
213
+ }
214
+
215
+ public function tell()
216
+ {
217
+ return $this->stream ? ftell($this->stream) : false;
218
+ }
219
+
220
+ public function setSize($size)
221
+ {
222
+ $this->size = $size;
223
+
224
+ return $this;
225
+ }
226
+
227
+ public function seek($offset, $whence = SEEK_SET)
228
+ {
229
+ return $this->seekable
230
+ ? fseek($this->stream, $offset, $whence) === 0
231
+ : false;
232
+ }
233
+
234
+ public function read($length)
235
+ {
236
+ return $this->readable ? fread($this->stream, $length) : false;
237
+ }
238
+
239
+ public function write($string)
240
+ {
241
+ // We can't know the size after writing anything
242
+ $this->size = null;
243
+
244
+ return $this->writable ? fwrite($this->stream, $string) : false;
245
+ }
246
+
247
+ public function getMetadata($key = null)
248
+ {
249
+ if (!$this->stream) {
250
+ return $key ? null : [];
251
+ } elseif (!$key) {
252
+ return $this->customMetadata + stream_get_meta_data($this->stream);
253
+ } elseif (isset($this->customMetadata[$key])) {
254
+ return $this->customMetadata[$key];
255
+ }
256
+
257
+ $meta = stream_get_meta_data($this->stream);
258
+
259
+ return isset($meta[$key]) ? $meta[$key] : null;
260
+ }
261
+ }
vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+ use GuzzleHttp\Stream\Exception\CannotAttachException;
4
+
5
+ /**
6
+ * Stream decorator trait
7
+ * @property StreamInterface stream
8
+ */
9
+ trait StreamDecoratorTrait
10
+ {
11
+ /**
12
+ * @param StreamInterface $stream Stream to decorate
13
+ */
14
+ public function __construct(StreamInterface $stream)
15
+ {
16
+ $this->stream = $stream;
17
+ }
18
+
19
+ /**
20
+ * Magic method used to create a new stream if streams are not added in
21
+ * the constructor of a decorator (e.g., LazyOpenStream).
22
+ */
23
+ public function __get($name)
24
+ {
25
+ if ($name == 'stream') {
26
+ $this->stream = $this->createStream();
27
+ return $this->stream;
28
+ }
29
+
30
+ throw new \UnexpectedValueException("$name not found on class");
31
+ }
32
+
33
+ public function __toString()
34
+ {
35
+ try {
36
+ $this->seek(0);
37
+ return $this->getContents();
38
+ } catch (\Exception $e) {
39
+ // Really, PHP? https://bugs.php.net/bug.php?id=53648
40
+ trigger_error('StreamDecorator::__toString exception: '
41
+ . (string) $e, E_USER_ERROR);
42
+ return '';
43
+ }
44
+ }
45
+
46
+ public function getContents()
47
+ {
48
+ return Utils::copyToString($this);
49
+ }
50
+
51
+ /**
52
+ * Allow decorators to implement custom methods
53
+ *
54
+ * @param string $method Missing method name
55
+ * @param array $args Method arguments
56
+ *
57
+ * @return mixed
58
+ */
59
+ public function __call($method, array $args)
60
+ {
61
+ $result = call_user_func_array(array($this->stream, $method), $args);
62
+
63
+ // Always return the wrapped object if the result is a return $this
64
+ return $result === $this->stream ? $this : $result;
65
+ }
66
+
67
+ public function close()
68
+ {
69
+ $this->stream->close();
70
+ }
71
+
72
+ public function getMetadata($key = null)
73
+ {
74
+ return $this->stream->getMetadata($key);
75
+ }
76
+
77
+ public function detach()
78
+ {
79
+ return $this->stream->detach();
80
+ }
81
+
82
+ public function attach($stream)
83
+ {
84
+ throw new CannotAttachException();
85
+ }
86
+
87
+ public function getSize()
88
+ {
89
+ return $this->stream->getSize();
90
+ }
91
+
92
+ public function eof()
93
+ {
94
+ return $this->stream->eof();
95
+ }
96
+
97
+ public function tell()
98
+ {
99
+ return $this->stream->tell();
100
+ }
101
+
102
+ public function isReadable()
103
+ {
104
+ return $this->stream->isReadable();
105
+ }
106
+
107
+ public function isWritable()
108
+ {
109
+ return $this->stream->isWritable();
110
+ }
111
+
112
+ public function isSeekable()
113
+ {
114
+ return $this->stream->isSeekable();
115
+ }
116
+
117
+ public function seek($offset, $whence = SEEK_SET)
118
+ {
119
+ return $this->stream->seek($offset, $whence);
120
+ }
121
+
122
+ public function read($length)
123
+ {
124
+ return $this->stream->read($length);
125
+ }
126
+
127
+ public function write($string)
128
+ {
129
+ return $this->stream->write($string);
130
+ }
131
+
132
+ /**
133
+ * Implement in subclasses to dynamically create streams when requested.
134
+ *
135
+ * @return StreamInterface
136
+ * @throws \BadMethodCallException
137
+ */
138
+ protected function createStream()
139
+ {
140
+ throw new \BadMethodCallException('createStream() not implemented in '
141
+ . get_class($this));
142
+ }
143
+ }
vendor/guzzlehttp/streams/src/StreamInterface.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ /**
5
+ * Describes a stream instance.
6
+ */
7
+ interface StreamInterface
8
+ {
9
+ /**
10
+ * Attempts to seek to the beginning of the stream and reads all data into
11
+ * a string until the end of the stream is reached.
12
+ *
13
+ * Warning: This could attempt to load a large amount of data into memory.
14
+ *
15
+ * @return string
16
+ */
17
+ public function __toString();
18
+
19
+ /**
20
+ * Closes the stream and any underlying resources.
21
+ */
22
+ public function close();
23
+
24
+ /**
25
+ * Separates any underlying resources from the stream.
26
+ *
27
+ * After the underlying resource has been detached, the stream object is in
28
+ * an unusable state. If you wish to use a Stream object as a PHP stream
29
+ * but keep the Stream object in a consistent state, use
30
+ * {@see GuzzleHttp\Stream\GuzzleStreamWrapper::getResource}.
31
+ *
32
+ * @return resource|null Returns the underlying PHP stream resource or null
33
+ * if the Stream object did not utilize an underlying
34
+ * stream resource.
35
+ */
36
+ public function detach();
37
+
38
+ /**
39
+ * Replaces the underlying stream resource with the provided stream.
40
+ *
41
+ * Use this method to replace the underlying stream with another; as an
42
+ * example, in server-side code, if you decide to return a file, you
43
+ * would replace the original content-oriented stream with the file
44
+ * stream.
45
+ *
46
+ * Any internal state such as caching of cursor position should be reset
47
+ * when attach() is called, as the stream has changed.
48
+ *
49
+ * @param resource $stream
50
+ *
51
+ * @return void
52
+ */
53
+ public function attach($stream);
54
+
55
+ /**
56
+ * Get the size of the stream if known
57
+ *
58
+ * @return int|null Returns the size in bytes if known, or null if unknown
59
+ */
60
+ public function getSize();
61
+
62
+ /**
63
+ * Returns the current position of the file read/write pointer
64
+ *
65
+ * @return int|bool Returns the position of the file pointer or false on error
66
+ */
67
+ public function tell();
68
+
69
+ /**
70
+ * Returns true if the stream is at the end of the stream.
71
+ *
72
+ * @return bool
73
+ */
74
+ public function eof();
75
+
76
+ /**
77
+ * Returns whether or not the stream is seekable
78
+ *
79
+ * @return bool
80
+ */
81
+ public function isSeekable();
82
+
83
+ /**
84
+ * Seek to a position in the stream
85
+ *
86
+ * @param int $offset Stream offset
87
+ * @param int $whence Specifies how the cursor position will be calculated
88
+ * based on the seek offset. Valid values are identical
89
+ * to the built-in PHP $whence values for `fseek()`.
90
+ * SEEK_SET: Set position equal to offset bytes
91
+ * SEEK_CUR: Set position to current location plus offset
92
+ * SEEK_END: Set position to end-of-stream plus offset
93
+ *
94
+ * @return bool Returns true on success or false on failure
95
+ * @link http://www.php.net/manual/en/function.fseek.php
96
+ */
97
+ public function seek($offset, $whence = SEEK_SET);
98
+
99
+ /**
100
+ * Returns whether or not the stream is writable
101
+ *
102
+ * @return bool
103
+ */
104
+ public function isWritable();
105
+
106
+ /**
107
+ * Write data to the stream
108
+ *
109
+ * @param string $string The string that is to be written.
110
+ *
111
+ * @return int|bool Returns the number of bytes written to the stream on
112
+ * success returns false on failure (e.g., broken pipe,
113
+ * writer needs to slow down, buffer is full, etc.)
114
+ */
115
+ public function write($string);
116
+
117
+ /**
118
+ * Returns whether or not the stream is readable
119
+ *
120
+ * @return bool
121
+ */
122
+ public function isReadable();
123
+
124
+ /**
125
+ * Read data from the stream
126
+ *
127
+ * @param int $length Read up to $length bytes from the object and return
128
+ * them. Fewer than $length bytes may be returned if
129
+ * underlying stream call returns fewer bytes.
130
+ *
131
+ * @return string Returns the data read from the stream.
132
+ */
133
+ public function read($length);
134
+
135
+ /**
136
+ * Returns the remaining contents of the stream as a string.
137
+ *
138
+ * Note: this could potentially load a large amount of data into memory.
139
+ *
140
+ * @return string
141
+ */
142
+ public function getContents();
143
+
144
+ /**
145
+ * Get stream metadata as an associative array or retrieve a specific key.
146
+ *
147
+ * The keys returned are identical to the keys returned from PHP's
148
+ * stream_get_meta_data() function.
149
+ *
150
+ * @param string $key Specific metadata to retrieve.
151
+ *
152
+ * @return array|mixed|null Returns an associative array if no key is
153
+ * no key is provided. Returns a specific key
154
+ * value if a key is provided and the value is
155
+ * found, or null if the key is not found.
156
+ * @see http://php.net/manual/en/function.stream-get-meta-data.php
157
+ */
158
+ public function getMetadata($key = null);
159
+ }
vendor/guzzlehttp/streams/src/Utils.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Stream;
3
+
4
+ use GuzzleHttp\Stream\Exception\SeekException;
5
+
6
+ /**
7
+ * Static utility class because PHP's autoloaders don't support the concept
8
+ * of namespaced function autoloading.
9
+ */
10
+ class Utils
11
+ {
12
+ /**
13
+ * Safely opens a PHP stream resource using a filename.
14
+ *
15
+ * When fopen fails, PHP normally raises a warning. This function adds an
16
+ * error handler that checks for errors and throws an exception instead.
17
+ *
18
+ * @param string $filename File to open
19
+ * @param string $mode Mode used to open the file
20
+ *
21
+ * @return resource
22
+ * @throws \RuntimeException if the file cannot be opened
23
+ */
24
+ public static function open($filename, $mode)
25
+ {
26
+ $ex = null;
27
+ set_error_handler(function () use ($filename, $mode, &$ex) {
28
+ $ex = new \RuntimeException(sprintf(
29
+ 'Unable to open %s using mode %s: %s',
30
+ $filename,
31
+ $mode,
32
+ func_get_args()[1]
33
+ ));
34
+ });
35
+
36
+ $handle = fopen($filename, $mode);
37
+ restore_error_handler();
38
+
39
+ if ($ex) {
40
+ /** @var $ex \RuntimeException */
41
+ throw $ex;
42
+ }
43
+
44
+ return $handle;
45
+ }
46
+
47
+ /**
48
+ * Copy the contents of a stream into a string until the given number of
49
+ * bytes have been read.
50
+ *
51
+ * @param StreamInterface $stream Stream to read
52
+ * @param int $maxLen Maximum number of bytes to read. Pass -1
53
+ * to read the entire stream.
54
+ * @return string
55
+ */
56
+ public static function copyToString(StreamInterface $stream, $maxLen = -1)
57
+ {
58
+ $buffer = '';
59
+
60
+ if ($maxLen === -1) {
61
+ while (!$stream->eof()) {
62
+ $buf = $stream->read(1048576);
63
+ if ($buf === false) {
64
+ break;
65
+ }
66
+ $buffer .= $buf;
67
+ }
68
+ return $buffer;
69
+ }
70
+
71
+ $len = 0;
72
+ while (!$stream->eof() && $len < $maxLen) {
73
+ $buf = $stream->read($maxLen - $len);
74
+ if ($buf === false) {
75
+ break;
76
+ }
77
+ $buffer .= $buf;
78
+ $len = strlen($buffer);
79
+ }
80
+
81
+ return $buffer;
82
+ }
83
+
84
+ /**
85
+ * Copy the contents of a stream into another stream until the given number
86
+ * of bytes have been read.
87
+ *
88
+ * @param StreamInterface $source Stream to read from
89
+ * @param StreamInterface $dest Stream to write to
90
+ * @param int $maxLen Maximum number of bytes to read. Pass -1
91
+ * to read the entire stream.
92
+ */
93
+ public static function copyToStream(
94
+ StreamInterface $source,
95
+ StreamInterface $dest,
96
+ $maxLen = -1
97
+ ) {
98
+ if ($maxLen === -1) {
99
+ while (!$source->eof()) {
100
+ if (!$dest->write($source->read(1048576))) {
101
+ break;
102
+ }
103
+ }
104
+ return;
105
+ }
106
+
107
+ $bytes = 0;
108
+ while (!$source->eof()) {
109
+ $buf = $source->read($maxLen - $bytes);
110
+ if (!($len = strlen($buf))) {
111
+ break;
112
+ }
113
+ $bytes += $len;
114
+ $dest->write($buf);
115
+ if ($bytes == $maxLen) {
116
+ break;
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Calculate a hash of a Stream
123
+ *
124
+ * @param StreamInterface $stream Stream to calculate the hash for
125
+ * @param string $algo Hash algorithm (e.g. md5, crc32, etc)
126
+ * @param bool $rawOutput Whether or not to use raw output
127
+ *
128
+ * @return string Returns the hash of the stream
129
+ * @throws SeekException
130
+ */
131
+ public static function hash(
132
+ StreamInterface $stream,
133
+ $algo,
134
+ $rawOutput = false
135
+ ) {
136
+ $pos = $stream->tell();
137
+
138
+ if ($pos > 0 && !$stream->seek(0)) {
139
+ throw new SeekException($stream);
140
+ }
141
+
142
+ $ctx = hash_init($algo);
143
+ while (!$stream->eof()) {
144
+ hash_update($ctx, $stream->read(1048576));
145
+ }
146
+
147
+ $out = hash_final($ctx, (bool) $rawOutput);
148
+ $stream->seek($pos);
149
+
150
+ return $out;
151
+ }
152
+
153
+ /**
154
+ * Read a line from the stream up to the maximum allowed buffer length
155
+ *
156
+ * @param StreamInterface $stream Stream to read from
157
+ * @param int $maxLength Maximum buffer length
158
+ *
159
+ * @return string|bool
160
+ */
161
+ public static function readline(StreamInterface $stream, $maxLength = null)
162
+ {
163
+ $buffer = '';
164
+ $size = 0;
165
+
166
+ while (!$stream->eof()) {
167
+ if (false === ($byte = $stream->read(1))) {
168
+ return $buffer;
169
+ }
170
+ $buffer .= $byte;
171
+ // Break when a new line is found or the max length - 1 is reached
172
+ if ($byte == PHP_EOL || ++$size == $maxLength - 1) {
173
+ break;
174
+ }
175
+ }
176
+
177
+ return $buffer;
178
+ }
179
+
180
+ /**
181
+ * Alias of GuzzleHttp\Stream\Stream::factory.
182
+ *
183
+ * @param mixed $resource Resource to create
184
+ * @param array $options Associative array of stream options defined in
185
+ * {@see \GuzzleHttp\Stream\Stream::__construct}
186
+ *
187
+ * @return StreamInterface
188
+ *
189
+ * @see GuzzleHttp\Stream\Stream::factory
190
+ * @see GuzzleHttp\Stream\Stream::__construct
191
+ */
192
+ public static function create($resource, array $options = [])
193
+ {
194
+ return Stream::factory($resource, $options);
195
+ }
196
+ }
vendor/guzzlehttp/streams/tests/AppendStreamTest.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\AppendStream;
5
+ use GuzzleHttp\Stream\Stream;
6
+
7
+ class AppendStreamTest extends \PHPUnit_Framework_TestCase
8
+ {
9
+ /**
10
+ * @expectedException \InvalidArgumentException
11
+ * @expectedExceptionMessage Each stream must be readable
12
+ */
13
+ public function testValidatesStreamsAreReadable()
14
+ {
15
+ $a = new AppendStream();
16
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
17
+ ->setMethods(['isReadable'])
18
+ ->getMockForAbstractClass();
19
+ $s->expects($this->once())
20
+ ->method('isReadable')
21
+ ->will($this->returnValue(false));
22
+ $a->addStream($s);
23
+ }
24
+
25
+ public function testValidatesSeekType()
26
+ {
27
+ $a = new AppendStream();
28
+ $this->assertFalse($a->seek(100, SEEK_CUR));
29
+ }
30
+
31
+ public function testTriesToRewindOnSeek()
32
+ {
33
+ $a = new AppendStream();
34
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
35
+ ->setMethods(['isReadable', 'seek', 'isSeekable'])
36
+ ->getMockForAbstractClass();
37
+ $s->expects($this->once())
38
+ ->method('isReadable')
39
+ ->will($this->returnValue(true));
40
+ $s->expects($this->once())
41
+ ->method('isSeekable')
42
+ ->will($this->returnValue(true));
43
+ $s->expects($this->once())
44
+ ->method('seek')
45
+ ->will($this->returnValue(false));
46
+ $a->addStream($s);
47
+ $this->assertFalse($a->seek(10));
48
+ }
49
+
50
+ public function testSeeksToPositionByReading()
51
+ {
52
+ $a = new AppendStream([
53
+ Stream::factory('foo'),
54
+ Stream::factory('bar'),
55
+ Stream::factory('baz'),
56
+ ]);
57
+
58
+ $this->assertTrue($a->seek(3));
59
+ $this->assertEquals(3, $a->tell());
60
+ $this->assertEquals('bar', $a->read(3));
61
+ $a->seek(6);
62
+ $this->assertEquals(6, $a->tell());
63
+ $this->assertEquals('baz', $a->read(3));
64
+ }
65
+
66
+ public function testDetachesEachStream()
67
+ {
68
+ $s1 = Stream::factory('foo');
69
+ $s2 = Stream::factory('foo');
70
+ $a = new AppendStream([$s1, $s2]);
71
+ $this->assertSame('foofoo', (string) $a);
72
+ $a->detach();
73
+ $this->assertSame('', (string) $a);
74
+ $this->assertSame(0, $a->getSize());
75
+ }
76
+
77
+ public function testClosesEachStream()
78
+ {
79
+ $s1 = Stream::factory('foo');
80
+ $a = new AppendStream([$s1]);
81
+ $a->close();
82
+ $this->assertSame('', (string) $a);
83
+ }
84
+
85
+ public function testIsNotWritable()
86
+ {
87
+ $a = new AppendStream([Stream::factory('foo')]);
88
+ $this->assertFalse($a->isWritable());
89
+ $this->assertTrue($a->isSeekable());
90
+ $this->assertTrue($a->isReadable());
91
+ $this->assertFalse($a->write('foo'));
92
+ }
93
+
94
+ public function testDoesNotNeedStreams()
95
+ {
96
+ $a = new AppendStream();
97
+ $this->assertEquals('', (string) $a);
98
+ }
99
+
100
+ public function testCanReadFromMultipleStreams()
101
+ {
102
+ $a = new AppendStream([
103
+ Stream::factory('foo'),
104
+ Stream::factory('bar'),
105
+ Stream::factory('baz'),
106
+ ]);
107
+ $this->assertFalse($a->eof());
108
+ $this->assertSame(0, $a->tell());
109
+ $this->assertEquals('foo', $a->read(3));
110
+ $this->assertEquals('bar', $a->read(3));
111
+ $this->assertEquals('baz', $a->read(3));
112
+ $this->assertTrue($a->eof());
113
+ $this->assertSame(9, $a->tell());
114
+ $this->assertEquals('foobarbaz', (string) $a);
115
+ }
116
+
117
+ public function testCanDetermineSizeFromMultipleStreams()
118
+ {
119
+ $a = new AppendStream([
120
+ Stream::factory('foo'),
121
+ Stream::factory('bar')
122
+ ]);
123
+ $this->assertEquals(6, $a->getSize());
124
+
125
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
126
+ ->setMethods(['isSeekable', 'isReadable'])
127
+ ->getMockForAbstractClass();
128
+ $s->expects($this->once())
129
+ ->method('isSeekable')
130
+ ->will($this->returnValue(null));
131
+ $s->expects($this->once())
132
+ ->method('isReadable')
133
+ ->will($this->returnValue(true));
134
+ $a->addStream($s);
135
+ $this->assertNull($a->getSize());
136
+ }
137
+
138
+ public function testCatchesExceptionsWhenCastingToString()
139
+ {
140
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
141
+ ->setMethods(['read', 'isReadable', 'eof'])
142
+ ->getMockForAbstractClass();
143
+ $s->expects($this->once())
144
+ ->method('read')
145
+ ->will($this->throwException(new \RuntimeException('foo')));
146
+ $s->expects($this->once())
147
+ ->method('isReadable')
148
+ ->will($this->returnValue(true));
149
+ $s->expects($this->any())
150
+ ->method('eof')
151
+ ->will($this->returnValue(false));
152
+ $a = new AppendStream([$s]);
153
+ $this->assertFalse($a->eof());
154
+ $this->assertSame('', (string) $a);
155
+ }
156
+
157
+ public function testCanDetach()
158
+ {
159
+ $s = new AppendStream();
160
+ $s->detach();
161
+ }
162
+
163
+ public function testReturnsEmptyMetadata()
164
+ {
165
+ $s = new AppendStream();
166
+ $this->assertEquals([], $s->getMetadata());
167
+ $this->assertNull($s->getMetadata('foo'));
168
+ }
169
+
170
+ /**
171
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
172
+ */
173
+ public function testCannotAttach()
174
+ {
175
+ $p = new AppendStream();
176
+ $p->attach('a');
177
+ }
178
+ }
vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\AsyncReadStream;
5
+ use GuzzleHttp\Stream\BufferStream;
6
+ use GuzzleHttp\Stream\FnStream;
7
+ use GuzzleHttp\Stream\Stream;
8
+
9
+ class AsyncReadStreamTest extends \PHPUnit_Framework_TestCase
10
+ {
11
+ /**
12
+ * @expectedException \InvalidArgumentException
13
+ * @expectedExceptionMessage Buffer must be readable and writable
14
+ */
15
+ public function testValidatesReadableBuffer()
16
+ {
17
+ new AsyncReadStream(FnStream::decorate(
18
+ Stream::factory(),
19
+ ['isReadable' => function () { return false; }]
20
+ ));
21
+ }
22
+
23
+ /**
24
+ * @expectedException \InvalidArgumentException
25
+ * @expectedExceptionMessage Buffer must be readable and writable
26
+ */
27
+ public function testValidatesWritableBuffer()
28
+ {
29
+ new AsyncReadStream(FnStream::decorate(
30
+ Stream::factory(),
31
+ ['isWritable' => function () { return false; }]
32
+ ));
33
+ }
34
+
35
+ public function testValidatesHwmMetadata()
36
+ {
37
+ $a = new AsyncReadStream(Stream::factory(), [
38
+ 'drain' => function() {}
39
+ ]);
40
+ $this->assertNull($this->readAttribute($a, 'drain'));
41
+ }
42
+
43
+ /**
44
+ * @expectedException \InvalidArgumentException
45
+ * @expectedExceptionMessage pump must be callable
46
+ */
47
+ public function testValidatesPumpIsCallable()
48
+ {
49
+ new AsyncReadStream(new BufferStream(), ['pump' => true]);
50
+ }
51
+
52
+ /**
53
+ * @expectedException \InvalidArgumentException
54
+ * @expectedExceptionMessage drain must be callable
55
+ */
56
+ public function testValidatesDrainIsCallable()
57
+ {
58
+ new AsyncReadStream(new BufferStream(), ['drain' => true]);
59
+ }
60
+
61
+ public function testCanInitialize()
62
+ {
63
+ $buffer = new BufferStream();
64
+ $a = new AsyncReadStream($buffer, [
65
+ 'size' => 10,
66
+ 'drain' => function () {},
67
+ 'pump' => function () {},
68
+ ]);
69
+ $this->assertSame($buffer, $this->readAttribute($a, 'stream'));
70
+ $this->assertTrue(is_callable($this->readAttribute($a, 'drain')));
71
+ $this->assertTrue(is_callable($this->readAttribute($a, 'pump')));
72
+ $this->assertTrue($a->isReadable());
73
+ $this->assertFalse($a->isSeekable());
74
+ $this->assertFalse($a->isWritable());
75
+ $this->assertFalse($a->write('foo'));
76
+ $this->assertEquals(10, $a->getSize());
77
+ }
78
+
79
+ public function testReadsFromBufferWithNoDrainOrPump()
80
+ {
81
+ $buffer = new BufferStream();
82
+ $a = new AsyncReadStream($buffer);
83
+ $buffer->write('foo');
84
+ $this->assertNull($a->getSize());
85
+ $this->assertEquals('foo', $a->read(10));
86
+ $this->assertEquals('', $a->read(10));
87
+ }
88
+
89
+ public function testCallsPumpForMoreDataWhenRequested()
90
+ {
91
+ $called = 0;
92
+ $buffer = new BufferStream();
93
+ $a = new AsyncReadStream($buffer, [
94
+ 'pump' => function ($size) use (&$called) {
95
+ $called++;
96
+ return str_repeat('.', $size);
97
+ }
98
+ ]);
99
+ $buffer->write('foobar');
100
+ $this->assertEquals('foo', $a->read(3));
101
+ $this->assertEquals(0, $called);
102
+ $this->assertEquals('bar.....', $a->read(8));
103
+ $this->assertEquals(1, $called);
104
+ $this->assertEquals('..', $a->read(2));
105
+ $this->assertEquals(2, $called);
106
+ }
107
+
108
+ public function testCallsDrainWhenNeeded()
109
+ {
110
+ $called = 0;
111
+ $buffer = new BufferStream(5);
112
+ $a = new AsyncReadStream($buffer, [
113
+ 'drain' => function (BufferStream $b) use (&$called, $buffer) {
114
+ $this->assertSame($b, $buffer);
115
+ $called++;
116
+ }
117
+ ]);
118
+
119
+ $buffer->write('foobar');
120
+ $this->assertEquals(6, $buffer->getSize());
121
+ $this->assertEquals(0, $called);
122
+
123
+ $a->read(3);
124
+ $this->assertTrue($this->readAttribute($a, 'needsDrain'));
125
+ $this->assertEquals(3, $buffer->getSize());
126
+ $this->assertEquals(0, $called);
127
+
128
+ $a->read(3);
129
+ $this->assertEquals(0, $buffer->getSize());
130
+ $this->assertFalse($this->readAttribute($a, 'needsDrain'));
131
+ $this->assertEquals(1, $called);
132
+ }
133
+
134
+ public function testCreatesBufferWithNoConfig()
135
+ {
136
+ list($buffer, $async) = AsyncReadStream::create();
137
+ $this->assertInstanceOf('GuzzleHttp\Stream\BufferStream', $buffer);
138
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
139
+ }
140
+
141
+ public function testCreatesBufferWithSpecifiedBuffer()
142
+ {
143
+ $buf = new BufferStream();
144
+ list($buffer, $async) = AsyncReadStream::create(['buffer' => $buf]);
145
+ $this->assertSame($buf, $buffer);
146
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
147
+ }
148
+
149
+ public function testCreatesNullStream()
150
+ {
151
+ list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 0]);
152
+ $this->assertInstanceOf('GuzzleHttp\Stream\NullStream', $buffer);
153
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
154
+ }
155
+
156
+ public function testCreatesDroppingStream()
157
+ {
158
+ list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 5]);
159
+ $this->assertInstanceOf('GuzzleHttp\Stream\DroppingStream', $buffer);
160
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
161
+ $buffer->write('12345678910');
162
+ $this->assertEquals(5, $buffer->getSize());
163
+ }
164
+
165
+ public function testCreatesOnWriteStream()
166
+ {
167
+ $c = 0;
168
+ $b = new BufferStream();
169
+ list($buffer, $async) = AsyncReadStream::create([
170
+ 'buffer' => $b,
171
+ 'write' => function (BufferStream $buf, $data) use (&$c, $b) {
172
+ $this->assertSame($buf, $b);
173
+ $this->assertEquals('foo', $data);
174
+ $c++;
175
+ }
176
+ ]);
177
+ $this->assertInstanceOf('GuzzleHttp\Stream\FnStream', $buffer);
178
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
179
+ $this->assertEquals(0, $c);
180
+ $this->assertEquals(3, $buffer->write('foo'));
181
+ $this->assertEquals(1, $c);
182
+ $this->assertEquals(3, $buffer->write('foo'));
183
+ $this->assertEquals(2, $c);
184
+ $this->assertEquals('foofoo', (string) $buffer);
185
+ }
186
+ }
vendor/guzzlehttp/streams/tests/BufferStreamTest.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\BufferStream;
5
+
6
+ class BufferStreamTest extends \PHPUnit_Framework_TestCase
7
+ {
8
+ public function testHasMetadata()
9
+ {
10
+ $b = new BufferStream(10);
11
+ $this->assertTrue($b->isReadable());
12
+ $this->assertTrue($b->isWritable());
13
+ $this->assertFalse($b->isSeekable());
14
+ $this->assertEquals(null, $b->getMetadata('foo'));
15
+ $this->assertEquals(10, $b->getMetadata('hwm'));
16
+ $this->assertEquals([], $b->getMetadata());
17
+ }
18
+
19
+ public function testRemovesReadDataFromBuffer()
20
+ {
21
+ $b = new BufferStream();
22
+ $this->assertEquals(3, $b->write('foo'));
23
+ $this->assertEquals(3, $b->getSize());
24
+ $this->assertFalse($b->eof());
25
+ $this->assertEquals('foo', $b->read(10));
26
+ $this->assertTrue($b->eof());
27
+ $this->assertEquals('', $b->read(10));
28
+ }
29
+
30
+ public function testCanCastToStringOrGetContents()
31
+ {
32
+ $b = new BufferStream();
33
+ $b->write('foo');
34
+ $b->write('baz');
35
+ $this->assertEquals('foo', $b->read(3));
36
+ $b->write('bar');
37
+ $this->assertEquals('bazbar', (string) $b);
38
+ $this->assertFalse($b->tell());
39
+ }
40
+
41
+ public function testDetachClearsBuffer()
42
+ {
43
+ $b = new BufferStream();
44
+ $b->write('foo');
45
+ $b->detach();
46
+ $this->assertEquals(0, $b->tell());
47
+ $this->assertTrue($b->eof());
48
+ $this->assertEquals(3, $b->write('abc'));
49
+ $this->assertEquals('abc', $b->read(10));
50
+ }
51
+
52
+ public function testExceedingHighwaterMarkReturnsFalseButStillBuffers()
53
+ {
54
+ $b = new BufferStream(5);
55
+ $this->assertEquals(3, $b->write('hi '));
56
+ $this->assertFalse($b->write('hello'));
57
+ $this->assertEquals('hi hello', (string) $b);
58
+ $this->assertEquals(4, $b->write('test'));
59
+ }
60
+
61
+ /**
62
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
63
+ */
64
+ public function testCannotAttach()
65
+ {
66
+ $p = new BufferStream();
67
+ $p->attach('a');
68
+ }
69
+ }
vendor/guzzlehttp/streams/tests/CachingStreamTest.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\Stream;
5
+ use GuzzleHttp\Stream\CachingStream;
6
+ use GuzzleHttp\Stream\Utils;
7
+
8
+ /**
9
+ * @covers GuzzleHttp\Stream\CachingStream
10
+ */
11
+ class CachingStreamTest extends \PHPUnit_Framework_TestCase
12
+ {
13
+ /** @var CachingStream */
14
+ protected $body;
15
+
16
+ /** @var Stream */
17
+ protected $decorated;
18
+
19
+ public function setUp()
20
+ {
21
+ $this->decorated = Stream::factory('testing');
22
+ $this->body = new CachingStream($this->decorated);
23
+ }
24
+
25
+ public function tearDown()
26
+ {
27
+ $this->decorated->close();
28
+ $this->body->close();
29
+ }
30
+
31
+ public function testUsesRemoteSizeIfPossible()
32
+ {
33
+ $body = Stream::factory('test');
34
+ $caching = new CachingStream($body);
35
+ $this->assertEquals(4, $caching->getSize());
36
+ }
37
+
38
+ /**
39
+ * @expectedException \RuntimeException
40
+ * @expectedExceptionMessage Cannot seek to byte 10
41
+ */
42
+ public function testCannotSeekPastWhatHasBeenRead()
43
+ {
44
+ $this->body->seek(10);
45
+ }
46
+
47
+ public function testCannotUseSeekEnd()
48
+ {
49
+ $this->assertFalse($this->body->seek(2, SEEK_END));
50
+ }
51
+
52
+ public function testRewindUsesSeek()
53
+ {
54
+ $a = Stream::factory('foo');
55
+ $d = $this->getMockBuilder('GuzzleHttp\Stream\CachingStream')
56
+ ->setMethods(array('seek'))
57
+ ->setConstructorArgs(array($a))
58
+ ->getMock();
59
+ $d->expects($this->once())
60
+ ->method('seek')
61
+ ->with(0)
62
+ ->will($this->returnValue(true));
63
+ $d->seek(0);
64
+ }
65
+
66
+ public function testCanSeekToReadBytes()
67
+ {
68
+ $this->assertEquals('te', $this->body->read(2));
69
+ $this->body->seek(0);
70
+ $this->assertEquals('test', $this->body->read(4));
71
+ $this->assertEquals(4, $this->body->tell());
72
+ $this->body->seek(2);
73
+ $this->assertEquals(2, $this->body->tell());
74
+ $this->body->seek(2, SEEK_CUR);
75
+ $this->assertEquals(4, $this->body->tell());
76
+ $this->assertEquals('ing', $this->body->read(3));
77
+ }
78
+
79
+ public function testWritesToBufferStream()
80
+ {
81
+ $this->body->read(2);
82
+ $this->body->write('hi');
83
+ $this->body->seek(0);
84
+ $this->assertEquals('tehiing', (string) $this->body);
85
+ }
86
+
87
+ public function testSkipsOverwrittenBytes()
88
+ {
89
+ $decorated = Stream::factory(
90
+ implode("\n", array_map(function ($n) {
91
+ return str_pad($n, 4, '0', STR_PAD_LEFT);
92
+ }, range(0, 25)))
93
+ );
94
+
95
+ $body = new CachingStream($decorated);
96
+
97
+ $this->assertEquals("0000\n", Utils::readline($body));
98
+ $this->assertEquals("0001\n", Utils::readline($body));
99
+ // Write over part of the body yet to be read, so skip some bytes
100
+ $this->assertEquals(5, $body->write("TEST\n"));
101
+ $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
102
+ // Read, which skips bytes, then reads
103
+ $this->assertEquals("0003\n", Utils::readline($body));
104
+ $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
105
+ $this->assertEquals("0004\n", Utils::readline($body));
106
+ $this->assertEquals("0005\n", Utils::readline($body));
107
+
108
+ // Overwrite part of the cached body (so don't skip any bytes)
109
+ $body->seek(5);
110
+ $this->assertEquals(5, $body->write("ABCD\n"));
111
+ $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
112
+ $this->assertEquals("TEST\n", Utils::readline($body));
113
+ $this->assertEquals("0003\n", Utils::readline($body));
114
+ $this->assertEquals("0004\n", Utils::readline($body));
115
+ $this->assertEquals("0005\n", Utils::readline($body));
116
+ $this->assertEquals("0006\n", Utils::readline($body));
117
+ $this->assertEquals(5, $body->write("1234\n"));
118
+ $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
119
+
120
+ // Seek to 0 and ensure the overwritten bit is replaced
121
+ $body->seek(0);
122
+ $this->assertEquals("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", $body->read(50));
123
+
124
+ // Ensure that casting it to a string does not include the bit that was overwritten
125
+ $this->assertContains("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", (string) $body);
126
+ }
127
+
128
+ public function testClosesBothStreams()
129
+ {
130
+ $s = fopen('php://temp', 'r');
131
+ $a = Stream::factory($s);
132
+ $d = new CachingStream($a);
133
+ $d->close();
134
+ $this->assertFalse(is_resource($s));
135
+ }
136
+ }
vendor/guzzlehttp/streams/tests/DroppingStreamTest.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\BufferStream;
5
+ use GuzzleHttp\Stream\DroppingStream;
6
+
7
+ class DroppingStreamTest extends \PHPUnit_Framework_TestCase
8
+ {
9
+ public function testBeginsDroppingWhenSizeExceeded()
10
+ {
11
+ $stream = new BufferStream();
12
+ $drop = new DroppingStream($stream, 5);
13
+ $this->assertEquals(3, $drop->write('hel'));
14
+ $this->assertFalse($drop->write('lo'));
15
+ $this->assertEquals(5, $drop->getSize());
16
+ $this->assertEquals('hello', $drop->read(5));
17
+ $this->assertEquals(0, $drop->getSize());
18
+ $drop->write('12345678910');
19
+ $this->assertEquals(5, $stream->getSize());
20
+ $this->assertEquals(5, $drop->getSize());
21
+ $this->assertEquals('12345', (string) $drop);
22
+ $this->assertEquals(0, $drop->getSize());
23
+ $drop->write('hello');
24
+ $this->assertFalse($drop->write('test'));
25
+ }
26
+ }
vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream\Exception;
3
+
4
+ use GuzzleHttp\Stream\Exception\SeekException;
5
+ use GuzzleHttp\Stream\Stream;
6
+
7
+ class SeekExceptionTest extends \PHPUnit_Framework_TestCase
8
+ {
9
+ public function testHasStream()
10
+ {
11
+ $s = Stream::factory('foo');
12
+ $e = new SeekException($s, 10);
13
+ $this->assertSame($s, $e->getStream());
14
+ $this->assertContains('10', $e->getMessage());
15
+ }
16
+ }
vendor/guzzlehttp/streams/tests/FnStreamTest.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\Stream;
5
+ use GuzzleHttp\Stream\FnStream;
6
+
7
+ /**
8
+ * @covers GuzzleHttp\Stream\FnStream
9
+ */
10
+ class FnStreamTest extends \PHPUnit_Framework_TestCase
11
+ {
12
+ /**
13
+ * @expectedException \BadMethodCallException
14
+ * @expectedExceptionMessage seek() is not implemented in the FnStream
15
+ */
16
+ public function testThrowsWhenNotImplemented()
17
+ {
18
+ (new FnStream([]))->seek(1);
19
+ }
20
+
21
+ public function testProxiesToFunction()
22
+ {
23
+ $s = new FnStream([
24
+ 'read' => function ($len) {
25
+ $this->assertEquals(3, $len);
26
+ return 'foo';
27
+ }
28
+ ]);
29
+
30
+ $this->assertEquals('foo', $s->read(3));
31
+ }
32
+
33
+ public function testCanCloseOnDestruct()
34
+ {
35
+ $called = false;
36
+ $s = new FnStream([
37
+ 'close' => function () use (&$called) {
38
+ $called = true;
39
+ }
40
+ ]);
41
+ unset($s);
42
+ $this->assertTrue($called);
43
+ }
44
+
45
+ public function testDoesNotRequireClose()
46
+ {
47
+ $s = new FnStream([]);
48
+ unset($s);
49
+ }
50
+
51
+ public function testDecoratesStream()
52
+ {
53
+ $a = Stream::factory('foo');
54
+ $b = FnStream::decorate($a, []);
55
+ $this->assertEquals(3, $b->getSize());
56
+ $this->assertEquals($b->isWritable(), true);
57
+ $this->assertEquals($b->isReadable(), true);
58
+ $this->assertEquals($b->isSeekable(), true);
59
+ $this->assertEquals($b->read(3), 'foo');
60
+ $this->assertEquals($b->tell(), 3);
61
+ $this->assertEquals($a->tell(), 3);
62
+ $this->assertEquals($b->eof(), true);
63
+ $this->assertEquals($a->eof(), true);
64
+ $b->seek(0);
65
+ $this->assertEquals('foo', (string) $b);
66
+ $b->seek(0);
67
+ $this->assertEquals('foo', $b->getContents());
68
+ $this->assertEquals($a->getMetadata(), $b->getMetadata());
69
+ $b->seek(0, SEEK_END);
70
+ $b->write('bar');
71
+ $this->assertEquals('foobar', (string) $b);
72
+ $this->assertInternalType('resource', $b->detach());
73
+ $b->close();
74
+ }
75
+
76
+ public function testDecoratesWithCustomizations()
77
+ {
78
+ $called = false;
79
+ $a = Stream::factory('foo');
80
+ $b = FnStream::decorate($a, [
81
+ 'read' => function ($len) use (&$called, $a) {
82
+ $called = true;
83
+ return $a->read($len);
84
+ }
85
+ ]);
86
+ $this->assertEquals('foo', $b->read(3));
87
+ $this->assertTrue($called);
88
+ }
89
+ }
vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\GuzzleStreamWrapper;
5
+ use GuzzleHttp\Stream\Stream;
6
+
7
+ /**
8
+ * @covers GuzzleHttp\Stream\GuzzleStreamWrapper
9
+ */
10
+ class GuzzleStreamWrapperTest extends \PHPUnit_Framework_TestCase
11
+ {
12
+ public function testResource()
13
+ {
14
+ $stream = Stream::factory('foo');
15
+ $handle = GuzzleStreamWrapper::getResource($stream);
16
+ $this->assertSame('foo', fread($handle, 3));
17
+ $this->assertSame(3, ftell($handle));
18
+ $this->assertSame(3, fwrite($handle, 'bar'));
19
+ $this->assertSame(0, fseek($handle, 0));
20
+ $this->assertSame('foobar', fread($handle, 6));
21
+ $this->assertTrue(feof($handle));
22
+
23
+ // This fails on HHVM for some reason
24
+ if (!defined('HHVM_VERSION')) {
25
+ $this->assertEquals([
26
+ 'dev' => 0,
27
+ 'ino' => 0,
28
+ 'mode' => 33206,
29
+ 'nlink' => 0,
30
+ 'uid' => 0,
31
+ 'gid' => 0,
32
+ 'rdev' => 0,
33
+ 'size' => 6,
34
+ 'atime' => 0,
35
+ 'mtime' => 0,
36
+ 'ctime' => 0,
37
+ 'blksize' => 0,
38
+ 'blocks' => 0,
39
+ 0 => 0,
40
+ 1 => 0,
41
+ 2 => 33206,
42
+ 3 => 0,
43
+ 4 => 0,
44
+ 5 => 0,
45
+ 6 => 0,
46
+ 7 => 6,
47
+ 8 => 0,
48
+ 9 => 0,
49
+ 10 => 0,
50
+ 11 => 0,
51
+ 12 => 0,
52
+ ], fstat($handle));
53
+ }
54
+
55
+ $this->assertTrue(fclose($handle));
56
+ $this->assertSame('foobar', (string) $stream);
57
+ }
58
+
59
+ /**
60
+ * @expectedException \InvalidArgumentException
61
+ */
62
+ public function testValidatesStream()
63
+ {
64
+ $stream = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
65
+ ->setMethods(['isReadable', 'isWritable'])
66
+ ->getMockForAbstractClass();
67
+ $stream->expects($this->once())
68
+ ->method('isReadable')
69
+ ->will($this->returnValue(false));
70
+ $stream->expects($this->once())
71
+ ->method('isWritable')
72
+ ->will($this->returnValue(false));
73
+ GuzzleStreamWrapper::getResource($stream);
74
+ }
75
+
76
+ /**
77
+ * @expectedException \PHPUnit_Framework_Error_Warning
78
+ */
79
+ public function testReturnsFalseWhenStreamDoesNotExist()
80
+ {
81
+ fopen('guzzle://foo', 'r');
82
+ }
83
+
84
+ public function testCanOpenReadonlyStream()
85
+ {
86
+ $stream = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
87
+ ->setMethods(['isReadable', 'isWritable'])
88
+ ->getMockForAbstractClass();
89
+ $stream->expects($this->once())
90
+ ->method('isReadable')
91
+ ->will($this->returnValue(false));
92
+ $stream->expects($this->once())
93
+ ->method('isWritable')
94
+ ->will($this->returnValue(true));
95
+ $r = GuzzleStreamWrapper::getResource($stream);
96
+ $this->assertInternalType('resource', $r);
97
+ fclose($r);
98
+ }
99
+ }
vendor/guzzlehttp/streams/tests/InflateStreamTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\InflateStream;
5
+ use GuzzleHttp\Stream\Stream;
6
+
7
+ class InflateStreamtest extends \PHPUnit_Framework_TestCase
8
+ {
9
+ public function testInflatesStreams()
10
+ {
11
+ $content = gzencode('test');
12
+ $a = Stream::factory($content);
13
+ $b = new InflateStream($a);
14
+ $this->assertEquals('test', (string) $b);
15
+ }
16
+ }
vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\LazyOpenStream;
5
+
6
+ class LazyOpenStreamTest extends \PHPUnit_Framework_TestCase
7
+ {
8
+ private $fname;
9
+
10
+ public function setup()
11
+ {
12
+ $this->fname = tempnam('/tmp', 'tfile');
13
+
14
+ if (file_exists($this->fname)) {
15
+ unlink($this->fname);
16
+ }
17
+ }
18
+
19
+ public function tearDown()
20
+ {
21
+ if (file_exists($this->fname)) {
22
+ unlink($this->fname);
23
+ }
24
+ }
25
+
26
+ public function testOpensLazily()
27
+ {
28
+ $l = new LazyOpenStream($this->fname, 'w+');
29
+ $l->write('foo');
30
+ $this->assertInternalType('array', $l->getMetadata());
31
+ $this->assertFileExists($this->fname);
32
+ $this->assertEquals('foo', file_get_contents($this->fname));
33
+ $this->assertEquals('foo', (string) $l);
34
+ }
35
+
36
+ public function testProxiesToFile()
37
+ {
38
+ file_put_contents($this->fname, 'foo');
39
+ $l = new LazyOpenStream($this->fname, 'r');
40
+ $this->assertEquals('foo', $l->read(4));
41
+ $this->assertTrue($l->eof());
42
+ $this->assertEquals(3, $l->tell());
43
+ $this->assertTrue($l->isReadable());
44
+ $this->assertTrue($l->isSeekable());
45
+ $this->assertFalse($l->isWritable());
46
+ $l->seek(1);
47
+ $this->assertEquals('oo', $l->getContents());
48
+ $this->assertEquals('foo', (string) $l);
49
+ $this->assertEquals(3, $l->getSize());
50
+ $this->assertInternalType('array', $l->getMetadata());
51
+ $l->close();
52
+ }
53
+
54
+ public function testDetachesUnderlyingStream()
55
+ {
56
+ file_put_contents($this->fname, 'foo');
57
+ $l = new LazyOpenStream($this->fname, 'r');
58
+ $r = $l->detach();
59
+ $this->assertInternalType('resource', $r);
60
+ fseek($r, 0);
61
+ $this->assertEquals('foo', stream_get_contents($r));
62
+ fclose($r);
63
+ }
64
+ }
vendor/guzzlehttp/streams/tests/LimitStreamTest.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Http;
3
+
4
+ use GuzzleHttp\Stream\FnStream;
5
+ use GuzzleHttp\Stream\Stream;
6
+ use GuzzleHttp\Stream\LimitStream;
7
+ use GuzzleHttp\Stream\NoSeekStream;
8
+
9
+ /**
10
+ * @covers GuzzleHttp\Stream\LimitStream
11
+ */
12
+ class LimitStreamTest extends \PHPUnit_Framework_TestCase
13
+ {
14
+ /** @var LimitStream */
15
+ protected $body;
16
+
17
+ /** @var Stream */
18
+ protected $decorated;
19
+
20
+ public function setUp()
21
+ {
22
+ $this->decorated = Stream::factory(fopen(__FILE__, 'r'));
23
+ $this->body = new LimitStream($this->decorated, 10, 3);
24
+ }
25
+
26
+ public function testReturnsSubset()
27
+ {
28
+ $body = new LimitStream(Stream::factory('foo'), -1, 1);
29
+ $this->assertEquals('oo', (string) $body);
30
+ $this->assertTrue($body->eof());
31
+ $body->seek(0);
32
+ $this->assertFalse($body->eof());
33
+ $this->assertEquals('oo', $body->read(100));
34
+ $this->assertTrue($body->eof());
35
+ }
36
+
37
+ public function testReturnsSubsetWhenCastToString()
38
+ {
39
+ $body = Stream::factory('foo_baz_bar');
40
+ $limited = new LimitStream($body, 3, 4);
41
+ $this->assertEquals('baz', (string) $limited);
42
+ }
43
+
44
+ public function testReturnsSubsetOfEmptyBodyWhenCastToString()
45
+ {
46
+ $body = Stream::factory('');
47
+ $limited = new LimitStream($body, 0, 10);
48
+ $this->assertEquals('', (string) $limited);
49
+ }
50
+
51
+ public function testSeeksWhenConstructed()
52
+ {
53
+ $this->assertEquals(0, $this->body->tell());
54
+ $this->assertEquals(3, $this->decorated->tell());
55
+ }
56
+
57
+ public function testAllowsBoundedSeek()
58
+ {
59
+ $this->assertEquals(true, $this->body->seek(100));
60
+ $this->assertEquals(10, $this->body->tell());
61
+ $this->assertEquals(13, $this->decorated->tell());
62
+ $this->assertEquals(true, $this->body->seek(0));
63
+ $this->assertEquals(0, $this->body->tell());
64
+ $this->assertEquals(3, $this->decorated->tell());
65
+ $this->assertEquals(false, $this->body->seek(-10));
66
+ $this->assertEquals(0, $this->body->tell());
67
+ $this->assertEquals(3, $this->decorated->tell());
68
+ $this->assertEquals(true, $this->body->seek(5));
69
+ $this->assertEquals(5, $this->body->tell());
70
+ $this->assertEquals(8, $this->decorated->tell());
71
+ $this->assertEquals(false, $this->body->seek(1000, SEEK_END));
72
+ }
73
+
74
+ public function testReadsOnlySubsetOfData()
75
+ {
76
+ $data = $this->body->read(100);
77
+ $this->assertEquals(10, strlen($data));
78
+ $this->assertFalse($this->body->read(1000));
79
+
80
+ $this->body->setOffset(10);
81
+ $newData = $this->body->read(100);
82
+ $this->assertEquals(10, strlen($newData));
83
+ $this->assertNotSame($data, $newData);
84
+ }
85
+
86
+ /**
87
+ * @expectedException \GuzzleHttp\Stream\Exception\SeekException
88
+ * @expectedExceptionMessage Could not seek the stream to position 2
89
+ */
90
+ public function testThrowsWhenCurrentGreaterThanOffsetSeek()
91
+ {
92
+ $a = Stream::factory('foo_bar');
93
+ $b = new NoSeekStream($a);
94
+ $c = new LimitStream($b);
95
+ $a->getContents();
96
+ $c->setOffset(2);
97
+ }
98
+
99
+ public function testClaimsConsumedWhenReadLimitIsReached()
100
+ {
101
+ $this->assertFalse($this->body->eof());
102
+ $this->body->read(1000);
103
+ $this->assertTrue($this->body->eof());
104
+ }
105
+
106
+ public function testContentLengthIsBounded()
107
+ {
108
+ $this->assertEquals(10, $this->body->getSize());
109
+ }
110
+
111
+ public function testGetContentsIsBasedOnSubset()
112
+ {
113
+ $body = new LimitStream(Stream::factory('foobazbar'), 3, 3);
114
+ $this->assertEquals('baz', $body->getContents());
115
+ }
116
+
117
+ public function testReturnsNullIfSizeCannotBeDetermined()
118
+ {
119
+ $a = new FnStream([
120
+ 'getSize' => function () { return null; },
121
+ 'tell' => function () { return 0; },
122
+ ]);
123
+ $b = new LimitStream($a);
124
+ $this->assertNull($b->getSize());
125
+ }
126
+
127
+ public function testLengthLessOffsetWhenNoLimitSize()
128
+ {
129
+ $a = Stream::factory('foo_bar');
130
+ $b = new LimitStream($a, -1, 4);
131
+ $this->assertEquals(3, $b->getSize());
132
+ }
133
+ }
vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\Stream;
5
+ use GuzzleHttp\Stream\NoSeekStream;
6
+
7
+ /**
8
+ * @covers GuzzleHttp\Stream\NoSeekStream
9
+ * @covers GuzzleHttp\Stream\StreamDecoratorTrait
10
+ */
11
+ class NoSeekStreamTest extends \PHPUnit_Framework_TestCase
12
+ {
13
+ public function testCannotSeek()
14
+ {
15
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
16
+ ->setMethods(['isSeekable', 'seek'])
17
+ ->getMockForAbstractClass();
18
+ $s->expects($this->never())->method('seek');
19
+ $s->expects($this->never())->method('isSeekable');
20
+ $wrapped = new NoSeekStream($s);
21
+ $this->assertFalse($wrapped->isSeekable());
22
+ $this->assertFalse($wrapped->seek(2));
23
+ }
24
+
25
+ public function testHandlesClose()
26
+ {
27
+ $s = Stream::factory('foo');
28
+ $wrapped = new NoSeekStream($s);
29
+ $wrapped->close();
30
+ $this->assertFalse($wrapped->write('foo'));
31
+ }
32
+
33
+ public function testCanAttach()
34
+ {
35
+ $s1 = Stream::factory('foo');
36
+ $s2 = Stream::factory('bar');
37
+ $wrapped = new NoSeekStream($s1);
38
+ $wrapped->attach($s2->detach());
39
+ $this->assertEquals('bar', (string) $wrapped);
40
+ }
41
+ }
vendor/guzzlehttp/streams/tests/NullStreamTest.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\NullStream;
5
+
6
+ class NullStreamTest extends \PHPUnit_Framework_TestCase
7
+ {
8
+ public function testDoesNothing()
9
+ {
10
+ $b = new NullStream();
11
+ $this->assertEquals('', $b->read(10));
12
+ $this->assertEquals(4, $b->write('test'));
13
+ $this->assertEquals('', (string) $b);
14
+ $this->assertNull($b->getMetadata('a'));
15
+ $this->assertEquals([], $b->getMetadata());
16
+ $this->assertEquals(0, $b->getSize());
17
+ $this->assertEquals('', $b->getContents());
18
+ $this->assertEquals(0, $b->tell());
19
+
20
+ $this->assertTrue($b->isReadable());
21
+ $this->assertTrue($b->isWritable());
22
+ $this->assertTrue($b->isSeekable());
23
+ $this->assertFalse($b->seek(10));
24
+
25
+ $this->assertTrue($b->eof());
26
+ $b->detach();
27
+ $this->assertTrue($b->eof());
28
+ $b->close();
29
+ }
30
+
31
+ /**
32
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
33
+ */
34
+ public function testCannotAttach()
35
+ {
36
+ $p = new NullStream();
37
+ $p->attach('a');
38
+ }
39
+ }
vendor/guzzlehttp/streams/tests/PumpStreamTest.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\LimitStream;
5
+ use GuzzleHttp\Stream\PumpStream;
6
+ use GuzzleHttp\Stream\Stream;
7
+
8
+ class PumpStreamTest extends \PHPUnit_Framework_TestCase
9
+ {
10
+ public function testHasMetadataAndSize()
11
+ {
12
+ $p = new PumpStream(function () {}, [
13
+ 'metadata' => ['foo' => 'bar'],
14
+ 'size' => 100
15
+ ]);
16
+
17
+ $this->assertEquals('bar', $p->getMetadata('foo'));
18
+ $this->assertEquals(['foo' => 'bar'], $p->getMetadata());
19
+ $this->assertEquals(100, $p->getSize());
20
+ }
21
+
22
+ public function testCanReadFromCallable()
23
+ {
24
+ $p = Stream::factory(function ($size) {
25
+ return 'a';
26
+ });
27
+ $this->assertEquals('a', $p->read(1));
28
+ $this->assertEquals(1, $p->tell());
29
+ $this->assertEquals('aaaaa', $p->read(5));
30
+ $this->assertEquals(6, $p->tell());
31
+ }
32
+
33
+ public function testStoresExcessDataInBuffer()
34
+ {
35
+ $called = [];
36
+ $p = Stream::factory(function ($size) use (&$called) {
37
+ $called[] = $size;
38
+ return 'abcdef';
39
+ });
40
+ $this->assertEquals('a', $p->read(1));
41
+ $this->assertEquals('b', $p->read(1));
42
+ $this->assertEquals('cdef', $p->read(4));
43
+ $this->assertEquals('abcdefabc', $p->read(9));
44
+ $this->assertEquals([1, 9, 3], $called);
45
+ }
46
+
47
+ public function testInifiniteStreamWrappedInLimitStream()
48
+ {
49
+ $p = Stream::factory(function () { return 'a'; });
50
+ $s = new LimitStream($p, 5);
51
+ $this->assertEquals('aaaaa', (string) $s);
52
+ }
53
+
54
+ public function testDescribesCapabilities()
55
+ {
56
+ $p = Stream::factory(function () {});
57
+ $this->assertTrue($p->isReadable());
58
+ $this->assertFalse($p->isSeekable());
59
+ $this->assertFalse($p->isWritable());
60
+ $this->assertNull($p->getSize());
61
+ $this->assertFalse($p->write('aa'));
62
+ $this->assertEquals('', $p->getContents());
63
+ $this->assertEquals('', (string) $p);
64
+ $p->close();
65
+ $this->assertEquals('', $p->read(10));
66
+ $this->assertTrue($p->eof());
67
+ }
68
+
69
+ /**
70
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
71
+ */
72
+ public function testCannotAttach()
73
+ {
74
+ $p = Stream::factory(function () {});
75
+ $p->attach('a');
76
+ }
77
+ }
vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\StreamInterface;
5
+ use GuzzleHttp\Stream\Stream;
6
+ use GuzzleHttp\Stream\StreamDecoratorTrait;
7
+
8
+ class Str implements StreamInterface
9
+ {
10
+ use StreamDecoratorTrait;
11
+ }
12
+
13
+ /**
14
+ * @covers GuzzleHttp\Stream\StreamDecoratorTrait
15
+ */
16
+ class StreamDecoratorTraitTest extends \PHPUnit_Framework_TestCase
17
+ {
18
+ private $a;
19
+ private $b;
20
+ private $c;
21
+
22
+ public function setUp()
23
+ {
24
+ $this->c = fopen('php://temp', 'r+');
25
+ fwrite($this->c, 'foo');
26
+ fseek($this->c, 0);
27
+ $this->a = Stream::factory($this->c);
28
+ $this->b = new Str($this->a);
29
+ }
30
+
31
+ public function testCatchesExceptionsWhenCastingToString()
32
+ {
33
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
34
+ ->setMethods(['read'])
35
+ ->getMockForAbstractClass();
36
+ $s->expects($this->once())
37
+ ->method('read')
38
+ ->will($this->throwException(new \Exception('foo')));
39
+ $msg = '';
40
+ set_error_handler(function ($errNo, $str) use (&$msg) { $msg = $str; });
41
+ echo new Str($s);
42
+ restore_error_handler();
43
+ $this->assertContains('foo', $msg);
44
+ }
45
+
46
+ public function testToString()
47
+ {
48
+ $this->assertEquals('foo', (string) $this->b);
49
+ }
50
+
51
+ public function testHasSize()
52
+ {
53
+ $this->assertEquals(3, $this->b->getSize());
54
+ $this->assertSame($this->b, $this->b->setSize(2));
55
+ $this->assertEquals(2, $this->b->getSize());
56
+ }
57
+
58
+ public function testReads()
59
+ {
60
+ $this->assertEquals('foo', $this->b->read(10));
61
+ }
62
+
63
+ public function testCheckMethods()
64
+ {
65
+ $this->assertEquals($this->a->isReadable(), $this->b->isReadable());
66
+ $this->assertEquals($this->a->isWritable(), $this->b->isWritable());
67
+ $this->assertEquals($this->a->isSeekable(), $this->b->isSeekable());
68
+ }
69
+
70
+ public function testSeeksAndTells()
71
+ {
72
+ $this->assertTrue($this->b->seek(1));
73
+ $this->assertEquals(1, $this->a->tell());
74
+ $this->assertEquals(1, $this->b->tell());
75
+ $this->assertTrue($this->b->seek(0));
76
+ $this->assertEquals(0, $this->a->tell());
77
+ $this->assertEquals(0, $this->b->tell());
78
+ $this->assertTrue($this->b->seek(0, SEEK_END));
79
+ $this->assertEquals(3, $this->a->tell());
80
+ $this->assertEquals(3, $this->b->tell());
81
+ }
82
+
83
+ public function testGetsContents()
84
+ {
85
+ $this->assertEquals('foo', $this->b->getContents());
86
+ $this->assertEquals('', $this->b->getContents());
87
+ $this->b->seek(1);
88
+ $this->assertEquals('oo', $this->b->getContents(1));
89
+ }
90
+
91
+ public function testCloses()
92
+ {
93
+ $this->b->close();
94
+ $this->assertFalse(is_resource($this->c));
95
+ }
96
+
97
+ public function testDetaches()
98
+ {
99
+ $this->b->detach();
100
+ $this->assertFalse($this->b->isReadable());
101
+ }
102
+
103
+ /**
104
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
105
+ */
106
+ public function testCannotAttachByDefault()
107
+ {
108
+ $this->b->attach('a');
109
+ }
110
+
111
+ public function testWrapsMetadata()
112
+ {
113
+ $this->assertSame($this->b->getMetadata(), $this->a->getMetadata());
114
+ $this->assertSame($this->b->getMetadata('uri'), $this->a->getMetadata('uri'));
115
+ }
116
+
117
+ public function testWrapsWrites()
118
+ {
119
+ $this->b->seek(0, SEEK_END);
120
+ $this->b->write('foo');
121
+ $this->assertEquals('foofoo', (string) $this->a);
122
+ }
123
+
124
+ /**
125
+ * @expectedException \UnexpectedValueException
126
+ */
127
+ public function testThrowsWithInvalidGetter()
128
+ {
129
+ $this->b->foo;
130
+ }
131
+
132
+ /**
133
+ * @expectedException \BadMethodCallException
134
+ */
135
+ public function testThrowsWhenGetterNotImplemented()
136
+ {
137
+ $s = new BadStream();
138
+ $s->stream;
139
+ }
140
+ }
141
+
142
+ class BadStream
143
+ {
144
+ use StreamDecoratorTrait;
145
+
146
+ public function __construct() {}
147
+ }
vendor/guzzlehttp/streams/tests/StreamTest.php ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\Stream;
5
+
6
+ /**
7
+ * @covers GuzzleHttp\Stream\Stream
8
+ */
9
+ class StreamTest extends \PHPUnit_Framework_TestCase
10
+ {
11
+ /**
12
+ * @expectedException \InvalidArgumentException
13
+ */
14
+ public function testConstructorThrowsExceptionOnInvalidArgument()
15
+ {
16
+ new Stream(true);
17
+ }
18
+
19
+ public function testConstructorInitializesProperties()
20
+ {
21
+ $handle = fopen('php://temp', 'r+');
22
+ fwrite($handle, 'data');
23
+ $stream = new Stream($handle);
24
+ $this->assertTrue($stream->isReadable());
25
+ $this->assertTrue($stream->isWritable());
26
+ $this->assertTrue($stream->isSeekable());
27
+ $this->assertEquals('php://temp', $stream->getMetadata('uri'));
28
+ $this->assertInternalType('array', $stream->getMetadata());
29
+ $this->assertEquals(4, $stream->getSize());
30
+ $this->assertFalse($stream->eof());
31
+ $stream->close();
32
+ }
33
+
34
+ public function testStreamClosesHandleOnDestruct()
35
+ {
36
+ $handle = fopen('php://temp', 'r');
37
+ $stream = new Stream($handle);
38
+ unset($stream);
39
+ $this->assertFalse(is_resource($handle));
40
+ }
41
+
42
+ public function testConvertsToString()
43
+ {
44
+ $handle = fopen('php://temp', 'w+');
45
+ fwrite($handle, 'data');
46
+ $stream = new Stream($handle);
47
+ $this->assertEquals('data', (string) $stream);
48
+ $this->assertEquals('data', (string) $stream);
49
+ $stream->close();
50
+ }
51
+
52
+ public function testGetsContents()
53
+ {
54
+ $handle = fopen('php://temp', 'w+');
55
+ fwrite($handle, 'data');
56
+ $stream = new Stream($handle);
57
+ $this->assertEquals('', $stream->getContents());
58
+ $stream->seek(0);
59
+ $this->assertEquals('data', $stream->getContents());
60
+ $this->assertEquals('', $stream->getContents());
61
+ }
62
+
63
+ public function testChecksEof()
64
+ {
65
+ $handle = fopen('php://temp', 'w+');
66
+ fwrite($handle, 'data');
67
+ $stream = new Stream($handle);
68
+ $this->assertFalse($stream->eof());
69
+ $stream->read(4);
70
+ $this->assertTrue($stream->eof());
71
+ $stream->close();
72
+ }
73
+
74
+ public function testAllowsSettingManualSize()
75
+ {
76
+ $handle = fopen('php://temp', 'w+');
77
+ fwrite($handle, 'data');
78
+ $stream = new Stream($handle);
79
+ $stream->setSize(10);
80
+ $this->assertEquals(10, $stream->getSize());
81
+ $stream->close();
82
+ }
83
+
84
+ public function testGetSize()
85
+ {
86
+ $size = filesize(__FILE__);
87
+ $handle = fopen(__FILE__, 'r');
88
+ $stream = new Stream($handle);
89
+ $this->assertEquals($size, $stream->getSize());
90
+ // Load from cache
91
+ $this->assertEquals($size, $stream->getSize());
92
+ $stream->close();
93
+ }
94
+
95
+ public function testEnsuresSizeIsConsistent()
96
+ {
97
+ $h = fopen('php://temp', 'w+');
98
+ $this->assertEquals(3, fwrite($h, 'foo'));
99
+ $stream = new Stream($h);
100
+ $this->assertEquals(3, $stream->getSize());
101
+ $this->assertEquals(4, $stream->write('test'));
102
+ $this->assertEquals(7, $stream->getSize());
103
+ $this->assertEquals(7, $stream->getSize());
104
+ $stream->close();
105
+ }
106
+
107
+ public function testProvidesStreamPosition()
108
+ {
109
+ $handle = fopen('php://temp', 'w+');
110
+ $stream = new Stream($handle);
111
+ $this->assertEquals(0, $stream->tell());
112
+ $stream->write('foo');
113
+ $this->assertEquals(3, $stream->tell());
114
+ $stream->seek(1);
115
+ $this->assertEquals(1, $stream->tell());
116
+ $this->assertSame(ftell($handle), $stream->tell());
117
+ $stream->close();
118
+ }
119
+
120
+ public function testKeepsPositionOfResource()
121
+ {
122
+ $h = fopen(__FILE__, 'r');
123
+ fseek($h, 10);
124
+ $stream = Stream::factory($h);
125
+ $this->assertEquals(10, $stream->tell());
126
+ $stream->close();
127
+ }
128
+
129
+ public function testCanDetachAndAttachStream()
130
+ {
131
+ $r = fopen('php://temp', 'w+');
132
+ $stream = new Stream($r);
133
+ $stream->write('foo');
134
+ $this->assertTrue($stream->isReadable());
135
+ $this->assertSame($r, $stream->detach());
136
+ $this->assertNull($stream->detach());
137
+
138
+ $this->assertFalse($stream->isReadable());
139
+ $this->assertFalse($stream->read(10));
140
+ $this->assertFalse($stream->isWritable());
141
+ $this->assertFalse($stream->write('bar'));
142
+ $this->assertFalse($stream->isSeekable());
143
+ $this->assertFalse($stream->seek(10));
144
+ $this->assertFalse($stream->tell());
145
+ $this->assertTrue($stream->eof());
146
+ $this->assertNull($stream->getSize());
147
+ $this->assertSame('', (string) $stream);
148
+ $this->assertSame('', $stream->getContents());
149
+
150
+ $stream->attach($r);
151
+ $stream->seek(0);
152
+ $this->assertEquals('foo', $stream->getContents());
153
+ $this->assertTrue($stream->isReadable());
154
+ $this->assertTrue($stream->isWritable());
155
+ $this->assertTrue($stream->isSeekable());
156
+
157
+ $stream->close();
158
+ }
159
+
160
+ public function testCloseClearProperties()
161
+ {
162
+ $handle = fopen('php://temp', 'r+');
163
+ $stream = new Stream($handle);
164
+ $stream->close();
165
+
166
+ $this->assertEmpty($stream->getMetadata());
167
+ $this->assertFalse($stream->isSeekable());
168
+ $this->assertFalse($stream->isReadable());
169
+ $this->assertFalse($stream->isWritable());
170
+ $this->assertNull($stream->getSize());
171
+ }
172
+
173
+ public function testCreatesWithFactory()
174
+ {
175
+ $stream = Stream::factory('foo');
176
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $stream);
177
+ $this->assertEquals('foo', $stream->getContents());
178
+ $stream->close();
179
+ }
180
+
181
+ public function testFactoryCreatesFromEmptyString()
182
+ {
183
+ $s = Stream::factory();
184
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
185
+ }
186
+
187
+ public function testFactoryCreatesFromResource()
188
+ {
189
+ $r = fopen(__FILE__, 'r');
190
+ $s = Stream::factory($r);
191
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
192
+ $this->assertSame(file_get_contents(__FILE__), (string) $s);
193
+ }
194
+
195
+ public function testFactoryCreatesFromObjectWithToString()
196
+ {
197
+ $r = new HasToString();
198
+ $s = Stream::factory($r);
199
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
200
+ $this->assertEquals('foo', (string) $s);
201
+ }
202
+
203
+ public function testCreatePassesThrough()
204
+ {
205
+ $s = Stream::factory('foo');
206
+ $this->assertSame($s, Stream::factory($s));
207
+ }
208
+
209
+ /**
210
+ * @expectedException \InvalidArgumentException
211
+ */
212
+ public function testThrowsExceptionForUnknown()
213
+ {
214
+ Stream::factory(new \stdClass());
215
+ }
216
+
217
+ public function testReturnsCustomMetadata()
218
+ {
219
+ $s = Stream::factory('foo', ['metadata' => ['hwm' => 3]]);
220
+ $this->assertEquals(3, $s->getMetadata('hwm'));
221
+ $this->assertArrayHasKey('hwm', $s->getMetadata());
222
+ }
223
+
224
+ public function testCanSetSize()
225
+ {
226
+ $s = Stream::factory('', ['size' => 10]);
227
+ $this->assertEquals(10, $s->getSize());
228
+ }
229
+
230
+ public function testCanCreateIteratorBasedStream()
231
+ {
232
+ $a = new \ArrayIterator(['foo', 'bar', '123']);
233
+ $p = Stream::factory($a);
234
+ $this->assertInstanceOf('GuzzleHttp\Stream\PumpStream', $p);
235
+ $this->assertEquals('foo', $p->read(3));
236
+ $this->assertFalse($p->eof());
237
+ $this->assertEquals('b', $p->read(1));
238
+ $this->assertEquals('a', $p->read(1));
239
+ $this->assertEquals('r12', $p->read(3));
240
+ $this->assertFalse($p->eof());
241
+ $this->assertEquals('3', $p->getContents());
242
+ $this->assertTrue($p->eof());
243
+ $this->assertEquals(9, $p->tell());
244
+ }
245
+ }
246
+
247
+ class HasToString
248
+ {
249
+ public function __toString() {
250
+ return 'foo';
251
+ }
252
+ }
vendor/guzzlehttp/streams/tests/UtilsTest.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Tests\Stream;
3
+
4
+ use GuzzleHttp\Stream\FnStream;
5
+ use GuzzleHttp\Stream\NoSeekStream;
6
+ use GuzzleHttp\Stream\Stream;
7
+ use GuzzleHttp\Stream\Utils;
8
+
9
+ class UtilsTest extends \PHPUnit_Framework_TestCase
10
+ {
11
+ public function testCopiesToString()
12
+ {
13
+ $s = Stream::factory('foobaz');
14
+ $this->assertEquals('foobaz', Utils::copyToString($s));
15
+ $s->seek(0);
16
+ $this->assertEquals('foo', Utils::copyToString($s, 3));
17
+ $this->assertEquals('baz', Utils::copyToString($s, 3));
18
+ $this->assertEquals('', Utils::copyToString($s));
19
+ }
20
+
21
+ public function testCopiesToStringStopsWhenReadFails()
22
+ {
23
+ $s1 = Stream::factory('foobaz');
24
+ $s1 = FnStream::decorate($s1, [
25
+ 'read' => function () {
26
+ return false;
27
+ }
28
+ ]);
29
+ $result = Utils::copyToString($s1);
30
+ $this->assertEquals('', $result);
31
+ }
32
+
33
+ public function testCopiesToStream()
34
+ {
35
+ $s1 = Stream::factory('foobaz');
36
+ $s2 = Stream::factory('');
37
+ Utils::copyToStream($s1, $s2);
38
+ $this->assertEquals('foobaz', (string) $s2);
39
+ $s2 = Stream::factory('');
40
+ $s1->seek(0);
41
+ Utils::copyToStream($s1, $s2, 3);
42
+ $this->assertEquals('foo', (string) $s2);
43
+ Utils::copyToStream($s1, $s2, 3);
44
+ $this->assertEquals('foobaz', (string) $s2);
45
+ }
46
+
47
+ public function testStopsCopyToStreamWhenWriteFails()
48
+ {
49
+ $s1 = Stream::factory('foobaz');
50
+ $s2 = Stream::factory('');
51
+ $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
52
+ Utils::copyToStream($s1, $s2);
53
+ $this->assertEquals('', (string) $s2);
54
+ }
55
+
56
+ public function testStopsCopyToSteamWhenWriteFailsWithMaxLen()
57
+ {
58
+ $s1 = Stream::factory('foobaz');
59
+ $s2 = Stream::factory('');
60
+ $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
61
+ Utils::copyToStream($s1, $s2, 10);
62
+ $this->assertEquals('', (string) $s2);
63
+ }
64
+
65
+ public function testStopsCopyToSteamWhenReadFailsWithMaxLen()
66
+ {
67
+ $s1 = Stream::factory('foobaz');
68
+ $s1 = FnStream::decorate($s1, ['read' => function () { return ''; }]);
69
+ $s2 = Stream::factory('');
70
+ Utils::copyToStream($s1, $s2, 10);
71
+ $this->assertEquals('', (string) $s2);
72
+ }
73
+
74
+ public function testReadsLines()
75
+ {
76
+ $s = Stream::factory("foo\nbaz\nbar");
77
+ $this->assertEquals("foo\n", Utils::readline($s));
78
+ $this->assertEquals("baz\n", Utils::readline($s));
79
+ $this->assertEquals("bar", Utils::readline($s));
80
+ }
81
+
82
+ public function testReadsLinesUpToMaxLength()
83
+ {
84
+ $s = Stream::factory("12345\n");
85
+ $this->assertEquals("123", Utils::readline($s, 4));
86
+ $this->assertEquals("45\n", Utils::readline($s));
87
+ }
88
+
89
+ public function testReadsLineUntilFalseReturnedFromRead()
90
+ {
91
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\Stream')
92
+ ->setMethods(['read', 'eof'])
93
+ ->disableOriginalConstructor()
94
+ ->getMock();
95
+ $s->expects($this->exactly(2))
96
+ ->method('read')
97
+ ->will($this->returnCallback(function () {
98
+ static $c = false;
99
+ if ($c) {
100
+ return false;
101
+ }
102
+ $c = true;
103
+ return 'h';
104
+ }));
105
+ $s->expects($this->exactly(2))
106
+ ->method('eof')
107
+ ->will($this->returnValue(false));
108
+ $this->assertEquals("h", Utils::readline($s));
109
+ }
110
+
111
+ public function testCalculatesHash()
112
+ {
113
+ $s = Stream::factory('foobazbar');
114
+ $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
115
+ }
116
+
117
+ /**
118
+ * @expectedException \GuzzleHttp\Stream\Exception\SeekException
119
+ */
120
+ public function testCalculatesHashThrowsWhenSeekFails()
121
+ {
122
+ $s = new NoSeekStream(Stream::factory('foobazbar'));
123
+ $s->read(2);
124
+ Utils::hash($s, 'md5');
125
+ }
126
+
127
+ public function testCalculatesHashSeeksToOriginalPosition()
128
+ {
129
+ $s = Stream::factory('foobazbar');
130
+ $s->seek(4);
131
+ $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
132
+ $this->assertEquals(4, $s->tell());
133
+ }
134
+
135
+ public function testOpensFilesSuccessfully()
136
+ {
137
+ $r = Utils::open(__FILE__, 'r');
138
+ $this->assertInternalType('resource', $r);
139
+ fclose($r);
140
+ }
141
+
142
+ /**
143
+ * @expectedException \RuntimeException
144
+ * @expectedExceptionMessage Unable to open /path/to/does/not/exist using mode r
145
+ */
146
+ public function testThrowsExceptionNotWarning()
147
+ {
148
+ Utils::open('/path/to/does/not/exist', 'r');
149
+ }
150
+
151
+ public function testProxiesToFactory()
152
+ {
153
+ $this->assertEquals('foo', (string) Utils::create('foo'));
154
+ }
155
+ }
vendor/react/promise/CHANGELOG.md ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CHANGELOG for 2.x
2
+ =================
3
+
4
+ * 2.8.0 (2020-05-12)
5
+
6
+ * Mark `FulfilledPromise`, `RejectedPromise` and `LazyPromise` as deprecated for Promise v2 (and remove for Promise v3).
7
+ (#143 and #165 by @clue)
8
+
9
+ ```php
10
+ // deprecated
11
+ $fulfilled = new React\Promise\FulfilledPromise($value);
12
+ $rejected = new React\Promise\RejectedPromise($reason);
13
+
14
+ // recommended alternatives
15
+ $fulfilled = React\Promise\resolve($value);
16
+ $rejected = React\Promise\reject($reason);
17
+ ```
18
+
19
+ * Fix: Fix checking whether cancellable promise is an object and avoid possible warning.
20
+ (#168 by @smscr and @jsor)
21
+
22
+ * Improve documentation and add docblocks to functions and interfaces.
23
+ (#135 by @CharlotteDunois)
24
+
25
+ * Add `.gitattributes` to exclude dev files from exports.
26
+ (#154 by @reedy)
27
+
28
+ * Improve test suite, run tests on PHP 7.4 and update PHPUnit test setup.
29
+ (#163 by @clue)
30
+
31
+ * 2.7.1 (2018-01-07)
32
+
33
+ * Fix: file_exists warning when resolving with long strings.
34
+ (#130 by @sbesselsen)
35
+ * Improve performance by prefixing all global functions calls with \ to skip the look up and resolve process and go straight to the global function.
36
+ (#133 by @WyriHaximus)
37
+
38
+ * 2.7.0 (2018-06-13)
39
+
40
+ * Feature: Improve memory consumption for pending promises by using static internal callbacks without binding to self.
41
+ (#124 by @clue)
42
+
43
+ * 2.6.0 (2018-06-11)
44
+
45
+ * Feature: Significantly improve memory consumption and performance by only passing resolver args
46
+ to resolver and canceller if callback requires them. Also use static callbacks without
47
+ binding to promise, clean up canceller function reference when they are no longer
48
+ needed and hide resolver and canceller references from call stack on PHP 7+.
49
+ (#113, #115, #116, #117, #118, #119 and #123 by @clue)
50
+
51
+ These changes combined mean that rejecting promises with an `Exception` should
52
+ no longer cause any internal circular references which could cause some unexpected
53
+ memory growth in previous versions. By explicitly avoiding and explicitly
54
+ cleaning up said references, we can avoid relying on PHP's circular garbage collector
55
+ to kick in which significantly improves performance when rejecting many promises.
56
+
57
+ * Mark legacy progress support / notification API as deprecated
58
+ (#112 by @clue)
59
+
60
+ * Recommend rejecting promises by throwing an exception
61
+ (#114 by @jsor)
62
+
63
+ * Improve documentation to properly instantiate LazyPromise
64
+ (#121 by @holtkamp)
65
+
66
+ * Follower cancellation propagation was originally planned for this release
67
+ but has been reverted for now and is planned for a future release.
68
+ (#99 by @jsor and #122 by @clue)
69
+
70
+ * 2.5.1 (2017-03-25)
71
+
72
+ * Fix circular references when resolving with a promise which follows
73
+ itself (#94).
74
+
75
+ * 2.5.0 (2016-12-22)
76
+
77
+ * Revert automatic cancellation of pending collection promises once the
78
+ output promise resolves. This was introduced in 42d86b7 (PR #36, released
79
+ in [v2.3.0](https://github.com/reactphp/promise/releases/tag/v2.3.0)) and
80
+ was both unintended and backward incompatible.
81
+
82
+ If you need automatic cancellation, you can use something like:
83
+
84
+ ```php
85
+ function allAndCancel(array $promises)
86
+ {
87
+ return \React\Promise\all($promises)
88
+ ->always(function() use ($promises) {
89
+ foreach ($promises as $promise) {
90
+ if ($promise instanceof \React\Promise\CancellablePromiseInterface) {
91
+ $promise->cancel();
92
+ }
93
+ }
94
+ });
95
+ }
96
+ ```
97
+ * `all()` and `map()` functions now preserve the order of the array (#77).
98
+ * Fix circular references when resolving a promise with itself (#71).
99
+
100
+ * 2.4.1 (2016-05-03)
101
+
102
+ * Fix `some()` not cancelling pending promises when too much input promises
103
+ reject (16ff799).
104
+
105
+ * 2.4.0 (2016-03-31)
106
+
107
+ * Support foreign thenables in `resolve()`.
108
+ Any object that provides a `then()` method is now assimilated to a trusted
109
+ promise that follows the state of this thenable (#52).
110
+ * Fix `some()` and `any()` for input arrays containing not enough items
111
+ (#34).
112
+
113
+ * 2.3.0 (2016-03-24)
114
+
115
+ * Allow cancellation of promises returned by functions working on promise
116
+ collections (#36).
117
+ * Handle `\Throwable` in the same way as `\Exception` (#51 by @joshdifabio).
118
+
119
+ * 2.2.2 (2016-02-26)
120
+
121
+ * Fix cancellation handlers called multiple times (#47 by @clue).
122
+
123
+ * 2.2.1 (2015-07-03)
124
+
125
+ * Fix stack error when resolving a promise in its own fulfillment or
126
+ rejection handlers.
127
+
128
+ * 2.2.0 (2014-12-30)
129
+
130
+ * Introduce new `ExtendedPromiseInterface` implemented by all promises.
131
+ * Add new `done()` method (part of the `ExtendedPromiseInterface`).
132
+ * Add new `otherwise()` method (part of the `ExtendedPromiseInterface`).
133
+ * Add new `always()` method (part of the `ExtendedPromiseInterface`).
134
+ * Add new `progress()` method (part of the `ExtendedPromiseInterface`).
135
+ * Rename `Deferred::progress` to `Deferred::notify` to avoid confusion with
136
+ `ExtendedPromiseInterface::progress` (a `Deferred::progress` alias is
137
+ still available for backward compatibility)
138
+ * `resolve()` now always returns a `ExtendedPromiseInterface`.
139
+
140
+ * 2.1.0 (2014-10-15)
141
+
142
+ * Introduce new `CancellablePromiseInterface` implemented by all promises.
143
+ * Add new `cancel()` method (part of the `CancellablePromiseInterface`).
144
+
145
+ * 2.0.0 (2013-12-10)
146
+
147
+ New major release. The goal is to streamline the API and to make it more
148
+ compliant with other promise libraries and especially with the new upcoming
149
+ [ES6 promises specification](https://github.com/domenic/promises-unwrapping/).
150
+
151
+ * Add standalone Promise class.
152
+ * Add new `race()` function.
153
+ * BC break: Bump minimum PHP version to PHP 5.4.
154
+ * BC break: Remove `ResolverInterface` and `PromiseInterface` from
155
+ `Deferred`.
156
+ * BC break: Change signature of `PromiseInterface`.
157
+ * BC break: Remove `When` and `Util` classes and move static methods to
158
+ functions.
159
+ * BC break: `FulfilledPromise` and `RejectedPromise` now throw an exception
160
+ when initialized with a promise instead of a value/reason.
161
+ * BC break: `Deferred::resolve()` and `Deferred::reject()` no longer return
162
+ a promise.
vendor/react/promise/LICENSE ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2012-2016 Jan Sorgalla
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
vendor/react/promise/README.md ADDED
@@ -0,0 +1,876 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Promise
2
+ =======
3
+
4
+ A lightweight implementation of
5
+ [CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP.
6
+
7
+ [![Build Status](https://travis-ci.org/reactphp/promise.svg?branch=master)](http://travis-ci.org/reactphp/promise)
8
+ [![Coverage Status](https://coveralls.io/repos/github/reactphp/promise/badge.svg?branch=master)](https://coveralls.io/github/reactphp/promise?branch=master)
9
+
10
+ Table of Contents
11
+ -----------------
12
+
13
+ 1. [Introduction](#introduction)
14
+ 2. [Concepts](#concepts)
15
+ * [Deferred](#deferred)
16
+ * [Promise](#promise-1)
17
+ 3. [API](#api)
18
+ * [Deferred](#deferred-1)
19
+ * [Deferred::promise()](#deferredpromise)
20
+ * [Deferred::resolve()](#deferredresolve)
21
+ * [Deferred::reject()](#deferredreject)
22
+ * [Deferred::notify()](#deferrednotify)
23
+ * [PromiseInterface](#promiseinterface)
24
+ * [PromiseInterface::then()](#promiseinterfacethen)
25
+ * [ExtendedPromiseInterface](#extendedpromiseinterface)
26
+ * [ExtendedPromiseInterface::done()](#extendedpromiseinterfacedone)
27
+ * [ExtendedPromiseInterface::otherwise()](#extendedpromiseinterfaceotherwise)
28
+ * [ExtendedPromiseInterface::always()](#extendedpromiseinterfacealways)
29
+ * [ExtendedPromiseInterface::progress()](#extendedpromiseinterfaceprogress)
30
+ * [CancellablePromiseInterface](#cancellablepromiseinterface)
31
+ * [CancellablePromiseInterface::cancel()](#cancellablepromiseinterfacecancel)
32
+ * [Promise](#promise-2)
33
+ * [FulfilledPromise](#fulfilledpromise)
34
+ * [RejectedPromise](#rejectedpromise)
35
+ * [LazyPromise](#lazypromise)
36
+ * [Functions](#functions)
37
+ * [resolve()](#resolve)
38
+ * [reject()](#reject)
39
+ * [all()](#all)
40
+ * [race()](#race)
41
+ * [any()](#any)
42
+ * [some()](#some)
43
+ * [map()](#map)
44
+ * [reduce()](#reduce)
45
+ * [PromisorInterface](#promisorinterface)
46
+ 4. [Examples](#examples)
47
+ * [How to use Deferred](#how-to-use-deferred)
48
+ * [How promise forwarding works](#how-promise-forwarding-works)
49
+ * [Resolution forwarding](#resolution-forwarding)
50
+ * [Rejection forwarding](#rejection-forwarding)
51
+ * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding)
52
+ * [Progress event forwarding](#progress-event-forwarding)
53
+ * [done() vs. then()](#done-vs-then)
54
+ 5. [Install](#install)
55
+ 6. [Credits](#credits)
56
+ 7. [License](#license)
57
+
58
+ Introduction
59
+ ------------
60
+
61
+ Promise is a library implementing
62
+ [CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP.
63
+
64
+ It also provides several other useful promise-related concepts, such as joining
65
+ multiple promises and mapping and reducing collections of promises.
66
+
67
+ If you've never heard about promises before,
68
+ [read this first](https://gist.github.com/3889970).
69
+
70
+ Concepts
71
+ --------
72
+
73
+ ### Deferred
74
+
75
+ A **Deferred** represents a computation or unit of work that may not have
76
+ completed yet. Typically (but not always), that computation will be something
77
+ that executes asynchronously and completes at some point in the future.
78
+
79
+ ### Promise
80
+
81
+ While a deferred represents the computation itself, a **Promise** represents
82
+ the result of that computation. Thus, each deferred has a promise that acts as
83
+ a placeholder for its actual result.
84
+
85
+ API
86
+ ---
87
+
88
+ ### Deferred
89
+
90
+ A deferred represents an operation whose resolution is pending. It has separate
91
+ promise and resolver parts.
92
+
93
+ ```php
94
+ $deferred = new React\Promise\Deferred();
95
+
96
+ $promise = $deferred->promise();
97
+
98
+ $deferred->resolve(mixed $value = null);
99
+ $deferred->reject(mixed $reason = null);
100
+ $deferred->notify(mixed $update = null);
101
+ ```
102
+
103
+ The `promise` method returns the promise of the deferred.
104
+
105
+ The `resolve` and `reject` methods control the state of the deferred.
106
+
107
+ The deprecated `notify` method is for progress notification.
108
+
109
+ The constructor of the `Deferred` accepts an optional `$canceller` argument.
110
+ See [Promise](#promise-2) for more information.
111
+
112
+ #### Deferred::promise()
113
+
114
+ ```php
115
+ $promise = $deferred->promise();
116
+ ```
117
+
118
+ Returns the promise of the deferred, which you can hand out to others while
119
+ keeping the authority to modify its state to yourself.
120
+
121
+ #### Deferred::resolve()
122
+
123
+ ```php
124
+ $deferred->resolve(mixed $value = null);
125
+ ```
126
+
127
+ Resolves the promise returned by `promise()`. All consumers are notified by
128
+ having `$onFulfilled` (which they registered via `$promise->then()`) called with
129
+ `$value`.
130
+
131
+ If `$value` itself is a promise, the promise will transition to the state of
132
+ this promise once it is resolved.
133
+
134
+ #### Deferred::reject()
135
+
136
+ ```php
137
+ $deferred->reject(mixed $reason = null);
138
+ ```
139
+
140
+ Rejects the promise returned by `promise()`, signalling that the deferred's
141
+ computation failed.
142
+ All consumers are notified by having `$onRejected` (which they registered via
143
+ `$promise->then()`) called with `$reason`.
144
+
145
+ If `$reason` itself is a promise, the promise will be rejected with the outcome
146
+ of this promise regardless whether it fulfills or rejects.
147
+
148
+ #### Deferred::notify()
149
+
150
+ > Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore.
151
+
152
+ ```php
153
+ $deferred->notify(mixed $update = null);
154
+ ```
155
+
156
+ Triggers progress notifications, to indicate to consumers that the computation
157
+ is making progress toward its result.
158
+
159
+ All consumers are notified by having `$onProgress` (which they registered via
160
+ `$promise->then()`) called with `$update`.
161
+
162
+ ### PromiseInterface
163
+
164
+ The promise interface provides the common interface for all promise
165
+ implementations.
166
+
167
+ A promise represents an eventual outcome, which is either fulfillment (success)
168
+ and an associated value, or rejection (failure) and an associated reason.
169
+
170
+ Once in the fulfilled or rejected state, a promise becomes immutable.
171
+ Neither its state nor its result (or error) can be modified.
172
+
173
+ #### Implementations
174
+
175
+ * [Promise](#promise-2)
176
+ * [FulfilledPromise](#fulfilledpromise) (deprecated)
177
+ * [RejectedPromise](#rejectedpromise) (deprecated)
178
+ * [LazyPromise](#lazypromise) (deprecated)
179
+
180
+ #### PromiseInterface::then()
181
+
182
+ ```php
183
+ $transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
184
+ ```
185
+
186
+ Transforms a promise's value by applying a function to the promise's fulfillment
187
+ or rejection value. Returns a new promise for the transformed result.
188
+
189
+ The `then()` method registers new fulfilled, rejection and progress handlers
190
+ with a promise (all parameters are optional):
191
+
192
+ * `$onFulfilled` will be invoked once the promise is fulfilled and passed
193
+ the result as the first argument.
194
+ * `$onRejected` will be invoked once the promise is rejected and passed the
195
+ reason as the first argument.
196
+ * `$onProgress` (deprecated) will be invoked whenever the producer of the promise
197
+ triggers progress notifications and passed a single argument (whatever it
198
+ wants) to indicate progress.
199
+
200
+ It returns a new promise that will fulfill with the return value of either
201
+ `$onFulfilled` or `$onRejected`, whichever is called, or will reject with
202
+ the thrown exception if either throws.
203
+
204
+ A promise makes the following guarantees about handlers registered in
205
+ the same call to `then()`:
206
+
207
+ 1. Only one of `$onFulfilled` or `$onRejected` will be called,
208
+ never both.
209
+ 2. `$onFulfilled` and `$onRejected` will never be called more
210
+ than once.
211
+ 3. `$onProgress` (deprecated) may be called multiple times.
212
+
213
+ #### See also
214
+
215
+ * [resolve()](#resolve) - Creating a resolved promise
216
+ * [reject()](#reject) - Creating a rejected promise
217
+ * [ExtendedPromiseInterface::done()](#extendedpromiseinterfacedone)
218
+ * [done() vs. then()](#done-vs-then)
219
+
220
+ ### ExtendedPromiseInterface
221
+
222
+ The ExtendedPromiseInterface extends the PromiseInterface with useful shortcut
223
+ and utility methods which are not part of the Promises/A specification.
224
+
225
+ #### Implementations
226
+
227
+ * [Promise](#promise-1)
228
+ * [FulfilledPromise](#fulfilledpromise) (deprecated)
229
+ * [RejectedPromise](#rejectedpromise) (deprecated)
230
+ * [LazyPromise](#lazypromise) (deprecated)
231
+
232
+ #### ExtendedPromiseInterface::done()
233
+
234
+ ```php
235
+ $promise->done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
236
+ ```
237
+
238
+ Consumes the promise's ultimate value if the promise fulfills, or handles the
239
+ ultimate error.
240
+
241
+ It will cause a fatal error if either `$onFulfilled` or `$onRejected` throw or
242
+ return a rejected promise.
243
+
244
+ Since the purpose of `done()` is consumption rather than transformation,
245
+ `done()` always returns `null`.
246
+
247
+ #### See also
248
+
249
+ * [PromiseInterface::then()](#promiseinterfacethen)
250
+ * [done() vs. then()](#done-vs-then)
251
+
252
+ #### ExtendedPromiseInterface::otherwise()
253
+
254
+ ```php
255
+ $promise->otherwise(callable $onRejected);
256
+ ```
257
+
258
+ Registers a rejection handler for promise. It is a shortcut for:
259
+
260
+ ```php
261
+ $promise->then(null, $onRejected);
262
+ ```
263
+
264
+ Additionally, you can type hint the `$reason` argument of `$onRejected` to catch
265
+ only specific errors.
266
+
267
+ ```php
268
+ $promise
269
+ ->otherwise(function (\RuntimeException $reason) {
270
+ // Only catch \RuntimeException instances
271
+ // All other types of errors will propagate automatically
272
+ })
273
+ ->otherwise(function ($reason) {
274
+ // Catch other errors
275
+ )};
276
+ ```
277
+
278
+ #### ExtendedPromiseInterface::always()
279
+
280
+ ```php
281
+ $newPromise = $promise->always(callable $onFulfilledOrRejected);
282
+ ```
283
+
284
+ Allows you to execute "cleanup" type tasks in a promise chain.
285
+
286
+ It arranges for `$onFulfilledOrRejected` to be called, with no arguments,
287
+ when the promise is either fulfilled or rejected.
288
+
289
+ * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully,
290
+ `$newPromise` will fulfill with the same value as `$promise`.
291
+ * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a
292
+ rejected promise, `$newPromise` will reject with the thrown exception or
293
+ rejected promise's reason.
294
+ * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully,
295
+ `$newPromise` will reject with the same reason as `$promise`.
296
+ * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a
297
+ rejected promise, `$newPromise` will reject with the thrown exception or
298
+ rejected promise's reason.
299
+
300
+ `always()` behaves similarly to the synchronous finally statement. When combined
301
+ with `otherwise()`, `always()` allows you to write code that is similar to the familiar
302
+ synchronous catch/finally pair.
303
+
304
+ Consider the following synchronous code:
305
+
306
+ ```php
307
+ try {
308
+ return doSomething();
309
+ } catch(\Exception $e) {
310
+ return handleError($e);
311
+ } finally {
312
+ cleanup();
313
+ }
314
+ ```
315
+
316
+ Similar asynchronous code (with `doSomething()` that returns a promise) can be
317
+ written:
318
+
319
+ ```php
320
+ return doSomething()
321
+ ->otherwise('handleError')
322
+ ->always('cleanup');
323
+ ```
324
+
325
+ #### ExtendedPromiseInterface::progress()
326
+
327
+ > Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore.
328
+
329
+ ```php
330
+ $promise->progress(callable $onProgress);
331
+ ```
332
+
333
+ Registers a handler for progress updates from promise. It is a shortcut for:
334
+
335
+ ```php
336
+ $promise->then(null, null, $onProgress);
337
+ ```
338
+
339
+ ### CancellablePromiseInterface
340
+
341
+ A cancellable promise provides a mechanism for consumers to notify the creator
342
+ of the promise that they are not longer interested in the result of an
343
+ operation.
344
+
345
+ #### CancellablePromiseInterface::cancel()
346
+
347
+ ``` php
348
+ $promise->cancel();
349
+ ```
350
+
351
+ The `cancel()` method notifies the creator of the promise that there is no
352
+ further interest in the results of the operation.
353
+
354
+ Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
355
+ a promise has no effect.
356
+
357
+ #### Implementations
358
+
359
+ * [Promise](#promise-1)
360
+ * [FulfilledPromise](#fulfilledpromise) (deprecated)
361
+ * [RejectedPromise](#rejectedpromise) (deprecated)
362
+ * [LazyPromise](#lazypromise) (deprecated)
363
+
364
+ ### Promise
365
+
366
+ Creates a promise whose state is controlled by the functions passed to
367
+ `$resolver`.
368
+
369
+ ```php
370
+ $resolver = function (callable $resolve, callable $reject, callable $notify) {
371
+ // Do some work, possibly asynchronously, and then
372
+ // resolve or reject. You can notify of progress events (deprecated)
373
+ // along the way if you want/need.
374
+
375
+ $resolve($awesomeResult);
376
+ // or throw new Exception('Promise rejected');
377
+ // or $resolve($anotherPromise);
378
+ // or $reject($nastyError);
379
+ // or $notify($progressNotification);
380
+ };
381
+
382
+ $canceller = function () {
383
+ // Cancel/abort any running operations like network connections, streams etc.
384
+
385
+ // Reject promise by throwing an exception
386
+ throw new Exception('Promise cancelled');
387
+ };
388
+
389
+ $promise = new React\Promise\Promise($resolver, $canceller);
390
+ ```
391
+
392
+ The promise constructor receives a resolver function and an optional canceller
393
+ function which both will be called with 3 arguments:
394
+
395
+ * `$resolve($value)` - Primary function that seals the fate of the
396
+ returned promise. Accepts either a non-promise value, or another promise.
397
+ When called with a non-promise value, fulfills promise with that value.
398
+ When called with another promise, e.g. `$resolve($otherPromise)`, promise's
399
+ fate will be equivalent to that of `$otherPromise`.
400
+ * `$reject($reason)` - Function that rejects the promise. It is recommended to
401
+ just throw an exception instead of using `$reject()`.
402
+ * `$notify($update)` - Deprecated function that issues progress events for the promise.
403
+
404
+ If the resolver or canceller throw an exception, the promise will be rejected
405
+ with that thrown exception as the rejection reason.
406
+
407
+ The resolver function will be called immediately, the canceller function only
408
+ once all consumers called the `cancel()` method of the promise.
409
+
410
+ ### FulfilledPromise
411
+
412
+ > Deprecated in v2.8.0: External usage of `FulfilledPromise` is deprecated, use `resolve()` instead.
413
+
414
+ Creates a already fulfilled promise.
415
+
416
+ ```php
417
+ $promise = React\Promise\FulfilledPromise($value);
418
+ ```
419
+
420
+ Note, that `$value` **cannot** be a promise. It's recommended to use
421
+ [resolve()](#resolve) for creating resolved promises.
422
+
423
+ ### RejectedPromise
424
+
425
+ > Deprecated in v2.8.0: External usage of `RejectedPromise` is deprecated, use `reject()` instead.
426
+
427
+ Creates a already rejected promise.
428
+
429
+ ```php
430
+ $promise = React\Promise\RejectedPromise($reason);
431
+ ```
432
+
433
+ Note, that `$reason` **cannot** be a promise. It's recommended to use
434
+ [reject()](#reject) for creating rejected promises.
435
+
436
+ ### LazyPromise
437
+
438
+ > Deprecated in v2.8.0: LazyPromise is deprecated and should not be used anymore.
439
+
440
+ Creates a promise which will be lazily initialized by `$factory` once a consumer
441
+ calls the `then()` method.
442
+
443
+ ```php
444
+ $factory = function () {
445
+ $deferred = new React\Promise\Deferred();
446
+
447
+ // Do some heavy stuff here and resolve the deferred once completed
448
+
449
+ return $deferred->promise();
450
+ };
451
+
452
+ $promise = new React\Promise\LazyPromise($factory);
453
+
454
+ // $factory will only be executed once we call then()
455
+ $promise->then(function ($value) {
456
+ });
457
+ ```
458
+
459
+ ### Functions
460
+
461
+ Useful functions for creating, joining, mapping and reducing collections of
462
+ promises.
463
+
464
+ All functions working on promise collections (like `all()`, `race()`, `some()`
465
+ etc.) support cancellation. This means, if you call `cancel()` on the returned
466
+ promise, all promises in the collection are cancelled. If the collection itself
467
+ is a promise which resolves to an array, this promise is also cancelled.
468
+
469
+ #### resolve()
470
+
471
+ ```php
472
+ $promise = React\Promise\resolve(mixed $promiseOrValue);
473
+ ```
474
+
475
+ Creates a promise for the supplied `$promiseOrValue`.
476
+
477
+ If `$promiseOrValue` is a value, it will be the resolution value of the
478
+ returned promise.
479
+
480
+ If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
481
+ a trusted promise that follows the state of the thenable is returned.
482
+
483
+ If `$promiseOrValue` is a promise, it will be returned as is.
484
+
485
+ Note: The promise returned is always a promise implementing
486
+ [ExtendedPromiseInterface](#extendedpromiseinterface). If you pass in a custom
487
+ promise which only implements [PromiseInterface](#promiseinterface), this
488
+ promise will be assimilated to a extended promise following `$promiseOrValue`.
489
+
490
+ #### reject()
491
+
492
+ ```php
493
+ $promise = React\Promise\reject(mixed $promiseOrValue);
494
+ ```
495
+
496
+ Creates a rejected promise for the supplied `$promiseOrValue`.
497
+
498
+ If `$promiseOrValue` is a value, it will be the rejection value of the
499
+ returned promise.
500
+
501
+ If `$promiseOrValue` is a promise, its completion value will be the rejected
502
+ value of the returned promise.
503
+
504
+ This can be useful in situations where you need to reject a promise without
505
+ throwing an exception. For example, it allows you to propagate a rejection with
506
+ the value of another promise.
507
+
508
+ #### all()
509
+
510
+ ```php
511
+ $promise = React\Promise\all(array|React\Promise\PromiseInterface $promisesOrValues);
512
+ ```
513
+
514
+ Returns a promise that will resolve only once all the items in
515
+ `$promisesOrValues` have resolved. The resolution value of the returned promise
516
+ will be an array containing the resolution values of each of the items in
517
+ `$promisesOrValues`.
518
+
519
+ #### race()
520
+
521
+ ```php
522
+ $promise = React\Promise\race(array|React\Promise\PromiseInterface $promisesOrValues);
523
+ ```
524
+
525
+ Initiates a competitive race that allows one winner. Returns a promise which is
526
+ resolved in the same way the first settled promise resolves.
527
+
528
+ #### any()
529
+
530
+ ```php
531
+ $promise = React\Promise\any(array|React\Promise\PromiseInterface $promisesOrValues);
532
+ ```
533
+
534
+ Returns a promise that will resolve when any one of the items in
535
+ `$promisesOrValues` resolves. The resolution value of the returned promise
536
+ will be the resolution value of the triggering item.
537
+
538
+ The returned promise will only reject if *all* items in `$promisesOrValues` are
539
+ rejected. The rejection value will be an array of all rejection reasons.
540
+
541
+ The returned promise will also reject with a `React\Promise\Exception\LengthException`
542
+ if `$promisesOrValues` contains 0 items.
543
+
544
+ #### some()
545
+
546
+ ```php
547
+ $promise = React\Promise\some(array|React\Promise\PromiseInterface $promisesOrValues, integer $howMany);
548
+ ```
549
+
550
+ Returns a promise that will resolve when `$howMany` of the supplied items in
551
+ `$promisesOrValues` resolve. The resolution value of the returned promise
552
+ will be an array of length `$howMany` containing the resolution values of the
553
+ triggering items.
554
+
555
+ The returned promise will reject if it becomes impossible for `$howMany` items
556
+ to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
557
+ reject). The rejection value will be an array of
558
+ `(count($promisesOrValues) - $howMany) + 1` rejection reasons.
559
+
560
+ The returned promise will also reject with a `React\Promise\Exception\LengthException`
561
+ if `$promisesOrValues` contains less items than `$howMany`.
562
+
563
+ #### map()
564
+
565
+ ```php
566
+ $promise = React\Promise\map(array|React\Promise\PromiseInterface $promisesOrValues, callable $mapFunc);
567
+ ```
568
+
569
+ Traditional map function, similar to `array_map()`, but allows input to contain
570
+ promises and/or values, and `$mapFunc` may return either a value or a promise.
571
+
572
+ The map function receives each item as argument, where item is a fully resolved
573
+ value of a promise or value in `$promisesOrValues`.
574
+
575
+ #### reduce()
576
+
577
+ ```php
578
+ $promise = React\Promise\reduce(array|React\Promise\PromiseInterface $promisesOrValues, callable $reduceFunc , $initialValue = null);
579
+ ```
580
+
581
+ Traditional reduce function, similar to `array_reduce()`, but input may contain
582
+ promises and/or values, and `$reduceFunc` may return either a value or a
583
+ promise, *and* `$initialValue` may be a promise or a value for the starting
584
+ value.
585
+
586
+ ### PromisorInterface
587
+
588
+ The `React\Promise\PromisorInterface` provides a common interface for objects
589
+ that provide a promise. `React\Promise\Deferred` implements it, but since it
590
+ is part of the public API anyone can implement it.
591
+
592
+ Examples
593
+ --------
594
+
595
+ ### How to use Deferred
596
+
597
+ ```php
598
+ function getAwesomeResultPromise()
599
+ {
600
+ $deferred = new React\Promise\Deferred();
601
+
602
+ // Execute a Node.js-style function using the callback pattern
603
+ computeAwesomeResultAsynchronously(function ($error, $result) use ($deferred) {
604
+ if ($error) {
605
+ $deferred->reject($error);
606
+ } else {
607
+ $deferred->resolve($result);
608
+ }
609
+ });
610
+
611
+ // Return the promise
612
+ return $deferred->promise();
613
+ }
614
+
615
+ getAwesomeResultPromise()
616
+ ->then(
617
+ function ($value) {
618
+ // Deferred resolved, do something with $value
619
+ },
620
+ function ($reason) {
621
+ // Deferred rejected, do something with $reason
622
+ },
623
+ function ($update) {
624
+ // Progress notification triggered, do something with $update
625
+ }
626
+ );
627
+ ```
628
+
629
+ ### How promise forwarding works
630
+
631
+ A few simple examples to show how the mechanics of Promises/A forwarding works.
632
+ These examples are contrived, of course, and in real usage, promise chains will
633
+ typically be spread across several function calls, or even several levels of
634
+ your application architecture.
635
+
636
+ #### Resolution forwarding
637
+
638
+ Resolved promises forward resolution values to the next promise.
639
+ The first promise, `$deferred->promise()`, will resolve with the value passed
640
+ to `$deferred->resolve()` below.
641
+
642
+ Each call to `then()` returns a new promise that will resolve with the return
643
+ value of the previous handler. This creates a promise "pipeline".
644
+
645
+ ```php
646
+ $deferred = new React\Promise\Deferred();
647
+
648
+ $deferred->promise()
649
+ ->then(function ($x) {
650
+ // $x will be the value passed to $deferred->resolve() below
651
+ // and returns a *new promise* for $x + 1
652
+ return $x + 1;
653
+ })
654
+ ->then(function ($x) {
655
+ // $x === 2
656
+ // This handler receives the return value of the
657
+ // previous handler.
658
+ return $x + 1;
659
+ })
660
+ ->then(function ($x) {
661
+ // $x === 3
662
+ // This handler receives the return value of the
663
+ // previous handler.
664
+ return $x + 1;
665
+ })
666
+ ->then(function ($x) {
667
+ // $x === 4
668
+ // This handler receives the return value of the
669
+ // previous handler.
670
+ echo 'Resolve ' . $x;
671
+ });
672
+
673
+ $deferred->resolve(1); // Prints "Resolve 4"
674
+ ```
675
+
676
+ #### Rejection forwarding
677
+
678
+ Rejected promises behave similarly, and also work similarly to try/catch:
679
+ When you catch an exception, you must rethrow for it to propagate.
680
+
681
+ Similarly, when you handle a rejected promise, to propagate the rejection,
682
+ "rethrow" it by either returning a rejected promise, or actually throwing
683
+ (since promise translates thrown exceptions into rejections)
684
+
685
+ ```php
686
+ $deferred = new React\Promise\Deferred();
687
+
688
+ $deferred->promise()
689
+ ->then(function ($x) {
690
+ throw new \Exception($x + 1);
691
+ })
692
+ ->otherwise(function (\Exception $x) {
693
+ // Propagate the rejection
694
+ throw $x;
695
+ })
696
+ ->otherwise(function (\Exception $x) {
697
+ // Can also propagate by returning another rejection
698
+ return React\Promise\reject(
699
+ new \Exception($x->getMessage() + 1)
700
+ );
701
+ })
702
+ ->otherwise(function ($x) {
703
+ echo 'Reject ' . $x->getMessage(); // 3
704
+ });
705
+
706
+ $deferred->resolve(1); // Prints "Reject 3"
707
+ ```
708
+
709
+ #### Mixed resolution and rejection forwarding
710
+
711
+ Just like try/catch, you can choose to propagate or not. Mixing resolutions and
712
+ rejections will still forward handler results in a predictable way.
713
+
714
+ ```php
715
+ $deferred = new React\Promise\Deferred();
716
+
717
+ $deferred->promise()
718
+ ->then(function ($x) {
719
+ return $x + 1;
720
+ })
721
+ ->then(function ($x) {
722
+ throw new \Exception($x + 1);
723
+ })
724
+ ->otherwise(function (\Exception $x) {
725
+ // Handle the rejection, and don't propagate.
726
+ // This is like catch without a rethrow
727
+ return $x->getMessage() + 1;
728
+ })
729
+ ->then(function ($x) {
730
+ echo 'Mixed ' . $x; // 4
731
+ });
732
+
733
+ $deferred->resolve(1); // Prints "Mixed 4"
734
+ ```
735
+
736
+ #### Progress event forwarding
737
+
738
+ > Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore.
739
+
740
+ In the same way as resolution and rejection handlers, your progress handler
741
+ **MUST** return a progress event to be propagated to the next link in the chain.
742
+ If you return nothing, `null` will be propagated.
743
+
744
+ Also in the same way as resolutions and rejections, if you don't register a
745
+ progress handler, the update will be propagated through.
746
+
747
+ If your progress handler throws an exception, the exception will be propagated
748
+ to the next link in the chain. The best thing to do is to ensure your progress
749
+ handlers do not throw exceptions.
750
+
751
+ This gives you the opportunity to transform progress events at each step in the
752
+ chain so that they are meaningful to the next step. It also allows you to choose
753
+ not to transform them, and simply let them propagate untransformed, by not
754
+ registering a progress handler.
755
+
756
+ ```php
757
+ $deferred = new React\Promise\Deferred();
758
+
759
+ $deferred->promise()
760
+ ->progress(function ($update) {
761
+ return $update + 1;
762
+ })
763
+ ->progress(function ($update) {
764
+ echo 'Progress ' . $update; // 2
765
+ });
766
+
767
+ $deferred->notify(1); // Prints "Progress 2"
768
+ ```
769
+
770
+ ### done() vs. then()
771
+
772
+ The golden rule is:
773
+
774
+ Either return your promise, or call done() on it.
775
+
776
+ At a first glance, `then()` and `done()` seem very similar. However, there are
777
+ important distinctions.
778
+
779
+ The intent of `then()` is to transform a promise's value and to pass or return
780
+ a new promise for the transformed value along to other parts of your code.
781
+
782
+ The intent of `done()` is to consume a promise's value, transferring
783
+ responsibility for the value to your code.
784
+
785
+ In addition to transforming a value, `then()` allows you to recover from, or
786
+ propagate intermediate errors. Any errors that are not handled will be caught
787
+ by the promise machinery and used to reject the promise returned by `then()`.
788
+
789
+ Calling `done()` transfers all responsibility for errors to your code. If an
790
+ error (either a thrown exception or returned rejection) escapes the
791
+ `$onFulfilled` or `$onRejected` callbacks you provide to done, it will be
792
+ rethrown in an uncatchable way causing a fatal error.
793
+
794
+ ```php
795
+ function getJsonResult()
796
+ {
797
+ return queryApi()
798
+ ->then(
799
+ // Transform API results to an object
800
+ function ($jsonResultString) {
801
+ return json_decode($jsonResultString);
802
+ },
803
+ // Transform API errors to an exception
804
+ function ($jsonErrorString) {
805
+ $object = json_decode($jsonErrorString);
806
+ throw new ApiErrorException($object->errorMessage);
807
+ }
808
+ );
809
+ }
810
+
811
+ // Here we provide no rejection handler. If the promise returned has been
812
+ // rejected, the ApiErrorException will be thrown
813
+ getJsonResult()
814
+ ->done(
815
+ // Consume transformed object
816
+ function ($jsonResultObject) {
817
+ // Do something with $jsonResultObject
818
+ }
819
+ );
820
+
821
+ // Here we provide a rejection handler which will either throw while debugging
822
+ // or log the exception
823
+ getJsonResult()
824
+ ->done(
825
+ function ($jsonResultObject) {
826
+ // Do something with $jsonResultObject
827
+ },
828
+ function (ApiErrorException $exception) {
829
+ if (isDebug()) {
830
+ throw $exception;
831
+ } else {
832
+ logException($exception);
833
+ }
834
+ }
835
+ );
836
+ ```
837
+
838
+ Note that if a rejection value is not an instance of `\Exception`, it will be
839
+ wrapped in an exception of the type `React\Promise\UnhandledRejectionException`.
840
+
841
+ You can get the original rejection reason by calling `$exception->getReason()`.
842
+
843
+ Install
844
+ -------
845
+
846
+ The recommended way to install this library is [through Composer](https://getcomposer.org).
847
+ [New to Composer?](https://getcomposer.org/doc/00-intro.md)
848
+
849
+ This project follows [SemVer](https://semver.org/).
850
+ This will install the latest supported version:
851
+
852
+ ```bash
853
+ $ composer require react/promise:^2.8
854
+ ```
855
+
856
+ See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
857
+
858
+ This project aims to run on any platform and thus does not require any PHP
859
+ extensions and supports running on legacy PHP 5.4 through current PHP 7+ and HHVM.
860
+ It's *highly recommended to use PHP 7+* for this project due to its vast
861
+ performance improvements.
862
+
863
+ Credits
864
+ -------
865
+
866
+ Promise is a port of [when.js](https://github.com/cujojs/when)
867
+ by [Brian Cavalier](https://github.com/briancavalier).
868
+
869
+ Also, large parts of the documentation have been ported from the when.js
870
+ [Wiki](https://github.com/cujojs/when/wiki) and the
871
+ [API docs](https://github.com/cujojs/when/blob/master/docs/api.md).
872
+
873
+ License
874
+ -------
875
+
876
+ Released under the [MIT](LICENSE) license.
vendor/react/promise/composer.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "react/promise",
3
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
4
+ "license": "MIT",
5
+ "authors": [
6
+ {"name": "Jan Sorgalla", "email": "jsorgalla@gmail.com"}
7
+ ],
8
+ "require": {
9
+ "php": ">=5.4.0"
10
+ },
11
+ "require-dev": {
12
+ "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36"
13
+ },
14
+ "autoload": {
15
+ "psr-4": {
16
+ "React\\Promise\\": "src/"
17
+ },
18
+ "files": ["src/functions_include.php"]
19
+ },
20
+ "autoload-dev": {
21
+ "psr-4": {
22
+ "React\\Promise\\": ["tests", "tests/fixtures"]
23
+ }
24
+ },
25
+ "keywords": [
26
+ "promise",
27
+ "promises"
28
+ ]
29
+ }
vendor/react/promise/src/CancellablePromiseInterface.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ interface CancellablePromiseInterface extends PromiseInterface
6
+ {
7
+ /**
8
+ * The `cancel()` method notifies the creator of the promise that there is no
9
+ * further interest in the results of the operation.
10
+ *
11
+ * Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
12
+ * a promise has no effect.
13
+ *
14
+ * @return void
15
+ */
16
+ public function cancel();
17
+ }
vendor/react/promise/src/CancellationQueue.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class CancellationQueue
6
+ {
7
+ private $started = false;
8
+ private $queue = [];
9
+
10
+ public function __invoke()
11
+ {
12
+ if ($this->started) {
13
+ return;
14
+ }
15
+
16
+ $this->started = true;
17
+ $this->drain();
18
+ }
19
+
20
+ public function enqueue($cancellable)
21
+ {
22
+ if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) {
23
+ return;
24
+ }
25
+
26
+ $length = \array_push($this->queue, $cancellable);
27
+
28
+ if ($this->started && 1 === $length) {
29
+ $this->drain();
30
+ }
31
+ }
32
+
33
+ private function drain()
34
+ {
35
+ for ($i = key($this->queue); isset($this->queue[$i]); $i++) {
36
+ $cancellable = $this->queue[$i];
37
+
38
+ $exception = null;
39
+
40
+ try {
41
+ $cancellable->cancel();
42
+ } catch (\Throwable $exception) {
43
+ } catch (\Exception $exception) {
44
+ }
45
+
46
+ unset($this->queue[$i]);
47
+
48
+ if ($exception) {
49
+ throw $exception;
50
+ }
51
+ }
52
+
53
+ $this->queue = [];
54
+ }
55
+ }
vendor/react/promise/src/Deferred.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class Deferred implements PromisorInterface
6
+ {
7
+ private $promise;
8
+ private $resolveCallback;
9
+ private $rejectCallback;
10
+ private $notifyCallback;
11
+ private $canceller;
12
+
13
+ public function __construct(callable $canceller = null)
14
+ {
15
+ $this->canceller = $canceller;
16
+ }
17
+
18
+ public function promise()
19
+ {
20
+ if (null === $this->promise) {
21
+ $this->promise = new Promise(function ($resolve, $reject, $notify) {
22
+ $this->resolveCallback = $resolve;
23
+ $this->rejectCallback = $reject;
24
+ $this->notifyCallback = $notify;
25
+ }, $this->canceller);
26
+ $this->canceller = null;
27
+ }
28
+
29
+ return $this->promise;
30
+ }
31
+
32
+ public function resolve($value = null)
33
+ {
34
+ $this->promise();
35
+
36
+ \call_user_func($this->resolveCallback, $value);
37
+ }
38
+
39
+ public function reject($reason = null)
40
+ {
41
+ $this->promise();
42
+
43
+ \call_user_func($this->rejectCallback, $reason);
44
+ }
45
+
46
+ /**
47
+ * @deprecated 2.6.0 Progress support is deprecated and should not be used anymore.
48
+ * @param mixed $update
49
+ */
50
+ public function notify($update = null)
51
+ {
52
+ $this->promise();
53
+
54
+ \call_user_func($this->notifyCallback, $update);
55
+ }
56
+
57
+ /**
58
+ * @deprecated 2.2.0
59
+ * @see Deferred::notify()
60
+ */
61
+ public function progress($update = null)
62
+ {
63
+ $this->notify($update);
64
+ }
65
+ }
vendor/react/promise/src/Exception/LengthException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise\Exception;
4
+
5
+ class LengthException extends \LengthException
6
+ {
7
+ }
vendor/react/promise/src/ExtendedPromiseInterface.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ interface ExtendedPromiseInterface extends PromiseInterface
6
+ {
7
+ /**
8
+ * Consumes the promise's ultimate value if the promise fulfills, or handles the
9
+ * ultimate error.
10
+ *
11
+ * It will cause a fatal error if either `$onFulfilled` or
12
+ * `$onRejected` throw or return a rejected promise.
13
+ *
14
+ * Since the purpose of `done()` is consumption rather than transformation,
15
+ * `done()` always returns `null`.
16
+ *
17
+ * @param callable|null $onFulfilled
18
+ * @param callable|null $onRejected
19
+ * @param callable|null $onProgress This argument is deprecated and should not be used anymore.
20
+ * @return void
21
+ */
22
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
23
+
24
+ /**
25
+ * Registers a rejection handler for promise. It is a shortcut for:
26
+ *
27
+ * ```php
28
+ * $promise->then(null, $onRejected);
29
+ * ```
30
+ *
31
+ * Additionally, you can type hint the `$reason` argument of `$onRejected` to catch
32
+ * only specific errors.
33
+ *
34
+ * @param callable $onRejected
35
+ * @return ExtendedPromiseInterface
36
+ */
37
+ public function otherwise(callable $onRejected);
38
+
39
+ /**
40
+ * Allows you to execute "cleanup" type tasks in a promise chain.
41
+ *
42
+ * It arranges for `$onFulfilledOrRejected` to be called, with no arguments,
43
+ * when the promise is either fulfilled or rejected.
44
+ *
45
+ * * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully,
46
+ * `$newPromise` will fulfill with the same value as `$promise`.
47
+ * * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a
48
+ * rejected promise, `$newPromise` will reject with the thrown exception or
49
+ * rejected promise's reason.
50
+ * * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully,
51
+ * `$newPromise` will reject with the same reason as `$promise`.
52
+ * * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a
53
+ * rejected promise, `$newPromise` will reject with the thrown exception or
54
+ * rejected promise's reason.
55
+ *
56
+ * `always()` behaves similarly to the synchronous finally statement. When combined
57
+ * with `otherwise()`, `always()` allows you to write code that is similar to the familiar
58
+ * synchronous catch/finally pair.
59
+ *
60
+ * Consider the following synchronous code:
61
+ *
62
+ * ```php
63
+ * try {
64
+ * return doSomething();
65
+ * } catch(\Exception $e) {
66
+ * return handleError($e);
67
+ * } finally {
68
+ * cleanup();
69
+ * }
70
+ * ```
71
+ *
72
+ * Similar asynchronous code (with `doSomething()` that returns a promise) can be
73
+ * written:
74
+ *
75
+ * ```php
76
+ * return doSomething()
77
+ * ->otherwise('handleError')
78
+ * ->always('cleanup');
79
+ * ```
80
+ *
81
+ * @param callable $onFulfilledOrRejected
82
+ * @return ExtendedPromiseInterface
83
+ */
84
+ public function always(callable $onFulfilledOrRejected);
85
+
86
+ /**
87
+ * Registers a handler for progress updates from promise. It is a shortcut for:
88
+ *
89
+ * ```php
90
+ * $promise->then(null, null, $onProgress);
91
+ * ```
92
+ *
93
+ * @param callable $onProgress
94
+ * @return ExtendedPromiseInterface
95
+ * @deprecated 2.6.0 Progress support is deprecated and should not be used anymore.
96
+ */
97
+ public function progress(callable $onProgress);
98
+ }
vendor/react/promise/src/FulfilledPromise.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ /**
6
+ * @deprecated 2.8.0 External usage of FulfilledPromise is deprecated, use `resolve()` instead.
7
+ */
8
+ class FulfilledPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
9
+ {
10
+ private $value;
11
+
12
+ public function __construct($value = null)
13
+ {
14
+ if ($value instanceof PromiseInterface) {
15
+ throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.');
16
+ }
17
+
18
+ $this->value = $value;
19
+ }
20
+
21
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
22
+ {
23
+ if (null === $onFulfilled) {
24
+ return $this;
25
+ }
26
+
27
+ try {
28
+ return resolve($onFulfilled($this->value));
29
+ } catch (\Throwable $exception) {
30
+ return new RejectedPromise($exception);
31
+ } catch (\Exception $exception) {
32
+ return new RejectedPromise($exception);
33
+ }
34
+ }
35
+
36
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
37
+ {
38
+ if (null === $onFulfilled) {
39
+ return;
40
+ }
41
+
42
+ $result = $onFulfilled($this->value);
43
+
44
+ if ($result instanceof ExtendedPromiseInterface) {
45
+ $result->done();
46
+ }
47
+ }
48
+
49
+ public function otherwise(callable $onRejected)
50
+ {
51
+ return $this;
52
+ }
53
+
54
+ public function always(callable $onFulfilledOrRejected)
55
+ {
56
+ return $this->then(function ($value) use ($onFulfilledOrRejected) {
57
+ return resolve($onFulfilledOrRejected())->then(function () use ($value) {
58
+ return $value;
59
+ });
60
+ });
61
+ }
62
+
63
+ public function progress(callable $onProgress)
64
+ {
65
+ return $this;
66
+ }
67
+
68
+ public function cancel()
69
+ {
70
+ }
71
+ }
vendor/react/promise/src/LazyPromise.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ /**
6
+ * @deprecated 2.8.0 LazyPromise is deprecated and should not be used anymore.
7
+ */
8
+ class LazyPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
9
+ {
10
+ private $factory;
11
+ private $promise;
12
+
13
+ public function __construct(callable $factory)
14
+ {
15
+ $this->factory = $factory;
16
+ }
17
+
18
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
19
+ {
20
+ return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
21
+ }
22
+
23
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
24
+ {
25
+ return $this->promise()->done($onFulfilled, $onRejected, $onProgress);
26
+ }
27
+
28
+ public function otherwise(callable $onRejected)
29
+ {
30
+ return $this->promise()->otherwise($onRejected);
31
+ }
32
+
33
+ public function always(callable $onFulfilledOrRejected)
34
+ {
35
+ return $this->promise()->always($onFulfilledOrRejected);
36
+ }
37
+
38
+ public function progress(callable $onProgress)
39
+ {
40
+ return $this->promise()->progress($onProgress);
41
+ }
42
+
43
+ public function cancel()
44
+ {
45
+ return $this->promise()->cancel();
46
+ }
47
+
48
+ /**
49
+ * @internal
50
+ * @see Promise::settle()
51
+ */
52
+ public function promise()
53
+ {
54
+ if (null === $this->promise) {
55
+ try {
56
+ $this->promise = resolve(\call_user_func($this->factory));
57
+ } catch (\Throwable $exception) {
58
+ $this->promise = new RejectedPromise($exception);
59
+ } catch (\Exception $exception) {
60
+ $this->promise = new RejectedPromise($exception);
61
+ }
62
+ }
63
+
64
+ return $this->promise;
65
+ }
66
+ }
vendor/react/promise/src/Promise.php ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class Promise implements ExtendedPromiseInterface, CancellablePromiseInterface
6
+ {
7
+ private $canceller;
8
+ private $result;
9
+
10
+ private $handlers = [];
11
+ private $progressHandlers = [];
12
+
13
+ private $requiredCancelRequests = 0;
14
+ private $cancelRequests = 0;
15
+
16
+ public function __construct(callable $resolver, callable $canceller = null)
17
+ {
18
+ $this->canceller = $canceller;
19
+
20
+ // Explicitly overwrite arguments with null values before invoking
21
+ // resolver function. This ensure that these arguments do not show up
22
+ // in the stack trace in PHP 7+ only.
23
+ $cb = $resolver;
24
+ $resolver = $canceller = null;
25
+ $this->call($cb);
26
+ }
27
+
28
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
29
+ {
30
+ if (null !== $this->result) {
31
+ return $this->result->then($onFulfilled, $onRejected, $onProgress);
32
+ }
33
+
34
+ if (null === $this->canceller) {
35
+ return new static($this->resolver($onFulfilled, $onRejected, $onProgress));
36
+ }
37
+
38
+ // This promise has a canceller, so we create a new child promise which
39
+ // has a canceller that invokes the parent canceller if all other
40
+ // followers are also cancelled. We keep a reference to this promise
41
+ // instance for the static canceller function and clear this to avoid
42
+ // keeping a cyclic reference between parent and follower.
43
+ $parent = $this;
44
+ ++$parent->requiredCancelRequests;
45
+
46
+ return new static(
47
+ $this->resolver($onFulfilled, $onRejected, $onProgress),
48
+ static function () use (&$parent) {
49
+ if (++$parent->cancelRequests >= $parent->requiredCancelRequests) {
50
+ $parent->cancel();
51
+ }
52
+
53
+ $parent = null;
54
+ }
55
+ );
56
+ }
57
+
58
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
59
+ {
60
+ if (null !== $this->result) {
61
+ return $this->result->done($onFulfilled, $onRejected, $onProgress);
62
+ }
63
+
64
+ $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected) {
65
+ $promise
66
+ ->done($onFulfilled, $onRejected);
67
+ };
68
+
69
+ if ($onProgress) {
70
+ $this->progressHandlers[] = $onProgress;
71
+ }
72
+ }
73
+
74
+ public function otherwise(callable $onRejected)
75
+ {
76
+ return $this->then(null, static function ($reason) use ($onRejected) {
77
+ if (!_checkTypehint($onRejected, $reason)) {
78
+ return new RejectedPromise($reason);
79
+ }
80
+
81
+ return $onRejected($reason);
82
+ });
83
+ }
84
+
85
+ public function always(callable $onFulfilledOrRejected)
86
+ {
87
+ return $this->then(static function ($value) use ($onFulfilledOrRejected) {
88
+ return resolve($onFulfilledOrRejected())->then(function () use ($value) {
89
+ return $value;
90
+ });
91
+ }, static function ($reason) use ($onFulfilledOrRejected) {
92
+ return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
93
+ return new RejectedPromise($reason);
94
+ });
95
+ });
96
+ }
97
+
98
+ public function progress(callable $onProgress)
99
+ {
100
+ return $this->then(null, null, $onProgress);
101
+ }
102
+
103
+ public function cancel()
104
+ {
105
+ if (null === $this->canceller || null !== $this->result) {
106
+ return;
107
+ }
108
+
109
+ $canceller = $this->canceller;
110
+ $this->canceller = null;
111
+
112
+ $this->call($canceller);
113
+ }
114
+
115
+ private function resolver(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
116
+ {
117
+ return function ($resolve, $reject, $notify) use ($onFulfilled, $onRejected, $onProgress) {
118
+ if ($onProgress) {
119
+ $progressHandler = static function ($update) use ($notify, $onProgress) {
120
+ try {
121
+ $notify($onProgress($update));
122
+ } catch (\Throwable $e) {
123
+ $notify($e);
124
+ } catch (\Exception $e) {
125
+ $notify($e);
126
+ }
127
+ };
128
+ } else {
129
+ $progressHandler = $notify;
130
+ }
131
+
132
+ $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) {
133
+ $promise
134
+ ->then($onFulfilled, $onRejected)
135
+ ->done($resolve, $reject, $progressHandler);
136
+ };
137
+
138
+ $this->progressHandlers[] = $progressHandler;
139
+ };
140
+ }
141
+
142
+ private function reject($reason = null)
143
+ {
144
+ if (null !== $this->result) {
145
+ return;
146
+ }
147
+
148
+ $this->settle(reject($reason));
149
+ }
150
+
151
+ private function settle(ExtendedPromiseInterface $promise)
152
+ {
153
+ $promise = $this->unwrap($promise);
154
+
155
+ if ($promise === $this) {
156
+ $promise = new RejectedPromise(
157
+ new \LogicException('Cannot resolve a promise with itself.')
158
+ );
159
+ }
160
+
161
+ $handlers = $this->handlers;
162
+
163
+ $this->progressHandlers = $this->handlers = [];
164
+ $this->result = $promise;
165
+ $this->canceller = null;
166
+
167
+ foreach ($handlers as $handler) {
168
+ $handler($promise);
169
+ }
170
+ }
171
+
172
+ private function unwrap($promise)
173
+ {
174
+ $promise = $this->extract($promise);
175
+
176
+ while ($promise instanceof self && null !== $promise->result) {
177
+ $promise = $this->extract($promise->result);
178
+ }
179
+
180
+ return $promise;
181
+ }
182
+
183
+ private function extract($promise)
184
+ {
185
+ if ($promise instanceof LazyPromise) {
186
+ $promise = $promise->promise();
187
+ }
188
+
189
+ return $promise;
190
+ }
191
+
192
+ private function call(callable $cb)
193
+ {
194
+ // Explicitly overwrite argument with null value. This ensure that this
195
+ // argument does not show up in the stack trace in PHP 7+ only.
196
+ $callback = $cb;
197
+ $cb = null;
198
+
199
+ // Use reflection to inspect number of arguments expected by this callback.
200
+ // We did some careful benchmarking here: Using reflection to avoid unneeded
201
+ // function arguments is actually faster than blindly passing them.
202
+ // Also, this helps avoiding unnecessary function arguments in the call stack
203
+ // if the callback creates an Exception (creating garbage cycles).
204
+ if (\is_array($callback)) {
205
+ $ref = new \ReflectionMethod($callback[0], $callback[1]);
206
+ } elseif (\is_object($callback) && !$callback instanceof \Closure) {
207
+ $ref = new \ReflectionMethod($callback, '__invoke');
208
+ } else {
209
+ $ref = new \ReflectionFunction($callback);
210
+ }
211
+ $args = $ref->getNumberOfParameters();
212
+
213
+ try {
214
+ if ($args === 0) {
215
+ $callback();
216
+ } else {
217
+ // Keep references to this promise instance for the static resolve/reject functions.
218
+ // By using static callbacks that are not bound to this instance
219
+ // and passing the target promise instance by reference, we can
220
+ // still execute its resolving logic and still clear this
221
+ // reference when settling the promise. This helps avoiding
222
+ // garbage cycles if any callback creates an Exception.
223
+ // These assumptions are covered by the test suite, so if you ever feel like
224
+ // refactoring this, go ahead, any alternative suggestions are welcome!
225
+ $target =& $this;
226
+ $progressHandlers =& $this->progressHandlers;
227
+
228
+ $callback(
229
+ static function ($value = null) use (&$target) {
230
+ if ($target !== null) {
231
+ $target->settle(resolve($value));
232
+ $target = null;
233
+ }
234
+ },
235
+ static function ($reason = null) use (&$target) {
236
+ if ($target !== null) {
237
+ $target->reject($reason);
238
+ $target = null;
239
+ }
240
+ },
241
+ static function ($update = null) use (&$progressHandlers) {
242
+ foreach ($progressHandlers as $handler) {
243
+ $handler($update);
244
+ }
245
+ }
246
+ );
247
+ }
248
+ } catch (\Throwable $e) {
249
+ $target = null;
250
+ $this->reject($e);
251
+ } catch (\Exception $e) {
252
+ $target = null;
253
+ $this->reject($e);
254
+ }
255
+ }
256
+ }
vendor/react/promise/src/PromiseInterface.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ interface PromiseInterface
6
+ {
7
+ /**
8
+ * Transforms a promise's value by applying a function to the promise's fulfillment
9
+ * or rejection value. Returns a new promise for the transformed result.
10
+ *
11
+ * The `then()` method registers new fulfilled and rejection handlers with a promise
12
+ * (all parameters are optional):
13
+ *
14
+ * * `$onFulfilled` will be invoked once the promise is fulfilled and passed
15
+ * the result as the first argument.
16
+ * * `$onRejected` will be invoked once the promise is rejected and passed the
17
+ * reason as the first argument.
18
+ * * `$onProgress` (deprecated) will be invoked whenever the producer of the promise
19
+ * triggers progress notifications and passed a single argument (whatever it
20
+ * wants) to indicate progress.
21
+ *
22
+ * It returns a new promise that will fulfill with the return value of either
23
+ * `$onFulfilled` or `$onRejected`, whichever is called, or will reject with
24
+ * the thrown exception if either throws.
25
+ *
26
+ * A promise makes the following guarantees about handlers registered in
27
+ * the same call to `then()`:
28
+ *
29
+ * 1. Only one of `$onFulfilled` or `$onRejected` will be called,
30
+ * never both.
31
+ * 2. `$onFulfilled` and `$onRejected` will never be called more
32
+ * than once.
33
+ * 3. `$onProgress` (deprecated) may be called multiple times.
34
+ *
35
+ * @param callable|null $onFulfilled
36
+ * @param callable|null $onRejected
37
+ * @param callable|null $onProgress This argument is deprecated and should not be used anymore.
38
+ * @return PromiseInterface
39
+ */
40
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
41
+ }
vendor/react/promise/src/PromisorInterface.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ interface PromisorInterface
6
+ {
7
+ /**
8
+ * Returns the promise of the deferred.
9
+ *
10
+ * @return PromiseInterface
11
+ */
12
+ public function promise();
13
+ }
vendor/react/promise/src/RejectedPromise.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ /**
6
+ * @deprecated 2.8.0 External usage of RejectedPromise is deprecated, use `reject()` instead.
7
+ */
8
+ class RejectedPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
9
+ {
10
+ private $reason;
11
+
12
+ public function __construct($reason = null)
13
+ {
14
+ if ($reason instanceof PromiseInterface) {
15
+ throw new \InvalidArgumentException('You cannot create React\Promise\RejectedPromise with a promise. Use React\Promise\reject($promiseOrValue) instead.');
16
+ }
17
+
18
+ $this->reason = $reason;
19
+ }
20
+
21
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
22
+ {
23
+ if (null === $onRejected) {
24
+ return $this;
25
+ }
26
+
27
+ try {
28
+ return resolve($onRejected($this->reason));
29
+ } catch (\Throwable $exception) {
30
+ return new RejectedPromise($exception);
31
+ } catch (\Exception $exception) {
32
+ return new RejectedPromise($exception);
33
+ }
34
+ }
35
+
36
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
37
+ {
38
+ if (null === $onRejected) {
39
+ throw UnhandledRejectionException::resolve($this->reason);
40
+ }
41
+
42
+ $result = $onRejected($this->reason);
43
+
44
+ if ($result instanceof self) {
45
+ throw UnhandledRejectionException::resolve($result->reason);
46
+ }
47
+
48
+ if ($result instanceof ExtendedPromiseInterface) {
49
+ $result->done();
50
+ }
51
+ }
52
+
53
+ public function otherwise(callable $onRejected)
54
+ {
55
+ if (!_checkTypehint($onRejected, $this->reason)) {
56
+ return $this;
57
+ }
58
+
59
+ return $this->then(null, $onRejected);
60
+ }
61
+
62
+ public function always(callable $onFulfilledOrRejected)
63
+ {
64
+ return $this->then(null, function ($reason) use ($onFulfilledOrRejected) {
65
+ return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
66
+ return new RejectedPromise($reason);
67
+ });
68
+ });
69
+ }
70
+
71
+ public function progress(callable $onProgress)
72
+ {
73
+ return $this;
74
+ }
75
+
76
+ public function cancel()
77
+ {
78
+ }
79
+ }
vendor/react/promise/src/UnhandledRejectionException.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class UnhandledRejectionException extends \RuntimeException
6
+ {
7
+ private $reason;
8
+
9
+ public static function resolve($reason)
10
+ {
11
+ if ($reason instanceof \Exception || $reason instanceof \Throwable) {
12
+ return $reason;
13
+ }
14
+
15
+ return new static($reason);
16
+ }
17
+
18
+ public function __construct($reason)
19
+ {
20
+ $this->reason = $reason;
21
+
22
+ $message = \sprintf('Unhandled Rejection: %s', \json_encode($reason));
23
+
24
+ parent::__construct($message, 0);
25
+ }
26
+
27
+ public function getReason()
28
+ {
29
+ return $this->reason;
30
+ }
31
+ }
vendor/react/promise/src/functions.php ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ /**
6
+ * Creates a promise for the supplied `$promiseOrValue`.
7
+ *
8
+ * If `$promiseOrValue` is a value, it will be the resolution value of the
9
+ * returned promise.
10
+ *
11
+ * If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
12
+ * a trusted promise that follows the state of the thenable is returned.
13
+ *
14
+ * If `$promiseOrValue` is a promise, it will be returned as is.
15
+ *
16
+ * @param mixed $promiseOrValue
17
+ * @return PromiseInterface
18
+ */
19
+ function resolve($promiseOrValue = null)
20
+ {
21
+ if ($promiseOrValue instanceof ExtendedPromiseInterface) {
22
+ return $promiseOrValue;
23
+ }
24
+
25
+ // Check is_object() first to avoid method_exists() triggering
26
+ // class autoloaders if $promiseOrValue is a string.
27
+ if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) {
28
+ $canceller = null;
29
+
30
+ if (\method_exists($promiseOrValue, 'cancel')) {
31
+ $canceller = [$promiseOrValue, 'cancel'];
32
+ }
33
+
34
+ return new Promise(function ($resolve, $reject, $notify) use ($promiseOrValue) {
35
+ $promiseOrValue->then($resolve, $reject, $notify);
36
+ }, $canceller);
37
+ }
38
+
39
+ return new FulfilledPromise($promiseOrValue);
40
+ }
41
+
42
+ /**
43
+ * Creates a rejected promise for the supplied `$promiseOrValue`.
44
+ *
45
+ * If `$promiseOrValue` is a value, it will be the rejection value of the
46
+ * returned promise.
47
+ *
48
+ * If `$promiseOrValue` is a promise, its completion value will be the rejected
49
+ * value of the returned promise.
50
+ *
51
+ * This can be useful in situations where you need to reject a promise without
52
+ * throwing an exception. For example, it allows you to propagate a rejection with
53
+ * the value of another promise.
54
+ *
55
+ * @param mixed $promiseOrValue
56
+ * @return PromiseInterface
57
+ */
58
+ function reject($promiseOrValue = null)
59
+ {
60
+ if ($promiseOrValue instanceof PromiseInterface) {
61
+ return resolve($promiseOrValue)->then(function ($value) {
62
+ return new RejectedPromise($value);
63
+ });
64
+ }
65
+
66
+ return new RejectedPromise($promiseOrValue);
67
+ }
68
+
69
+ /**
70
+ * Returns a promise that will resolve only once all the items in
71
+ * `$promisesOrValues` have resolved. The resolution value of the returned promise
72
+ * will be an array containing the resolution values of each of the items in
73
+ * `$promisesOrValues`.
74
+ *
75
+ * @param array $promisesOrValues
76
+ * @return PromiseInterface
77
+ */
78
+ function all($promisesOrValues)
79
+ {
80
+ return map($promisesOrValues, function ($val) {
81
+ return $val;
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Initiates a competitive race that allows one winner. Returns a promise which is
87
+ * resolved in the same way the first settled promise resolves.
88
+ *
89
+ * The returned promise will become **infinitely pending** if `$promisesOrValues`
90
+ * contains 0 items.
91
+ *
92
+ * @param array $promisesOrValues
93
+ * @return PromiseInterface
94
+ */
95
+ function race($promisesOrValues)
96
+ {
97
+ $cancellationQueue = new CancellationQueue();
98
+ $cancellationQueue->enqueue($promisesOrValues);
99
+
100
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $cancellationQueue) {
101
+ resolve($promisesOrValues)
102
+ ->done(function ($array) use ($cancellationQueue, $resolve, $reject, $notify) {
103
+ if (!is_array($array) || !$array) {
104
+ $resolve();
105
+ return;
106
+ }
107
+
108
+ foreach ($array as $promiseOrValue) {
109
+ $cancellationQueue->enqueue($promiseOrValue);
110
+
111
+ resolve($promiseOrValue)
112
+ ->done($resolve, $reject, $notify);
113
+ }
114
+ }, $reject, $notify);
115
+ }, $cancellationQueue);
116
+ }
117
+
118
+ /**
119
+ * Returns a promise that will resolve when any one of the items in
120
+ * `$promisesOrValues` resolves. The resolution value of the returned promise
121
+ * will be the resolution value of the triggering item.
122
+ *
123
+ * The returned promise will only reject if *all* items in `$promisesOrValues` are
124
+ * rejected. The rejection value will be an array of all rejection reasons.
125
+ *
126
+ * The returned promise will also reject with a `React\Promise\Exception\LengthException`
127
+ * if `$promisesOrValues` contains 0 items.
128
+ *
129
+ * @param array $promisesOrValues
130
+ * @return PromiseInterface
131
+ */
132
+ function any($promisesOrValues)
133
+ {
134
+ return some($promisesOrValues, 1)
135
+ ->then(function ($val) {
136
+ return \array_shift($val);
137
+ });
138
+ }
139
+
140
+ /**
141
+ * Returns a promise that will resolve when `$howMany` of the supplied items in
142
+ * `$promisesOrValues` resolve. The resolution value of the returned promise
143
+ * will be an array of length `$howMany` containing the resolution values of the
144
+ * triggering items.
145
+ *
146
+ * The returned promise will reject if it becomes impossible for `$howMany` items
147
+ * to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
148
+ * reject). The rejection value will be an array of
149
+ * `(count($promisesOrValues) - $howMany) + 1` rejection reasons.
150
+ *
151
+ * The returned promise will also reject with a `React\Promise\Exception\LengthException`
152
+ * if `$promisesOrValues` contains less items than `$howMany`.
153
+ *
154
+ * @param array $promisesOrValues
155
+ * @param int $howMany
156
+ * @return PromiseInterface
157
+ */
158
+ function some($promisesOrValues, $howMany)
159
+ {
160
+ $cancellationQueue = new CancellationQueue();
161
+ $cancellationQueue->enqueue($promisesOrValues);
162
+
163
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $howMany, $cancellationQueue) {
164
+ resolve($promisesOrValues)
165
+ ->done(function ($array) use ($howMany, $cancellationQueue, $resolve, $reject, $notify) {
166
+ if (!\is_array($array) || $howMany < 1) {
167
+ $resolve([]);
168
+ return;
169
+ }
170
+
171
+ $len = \count($array);
172
+
173
+ if ($len < $howMany) {
174
+ throw new Exception\LengthException(
175
+ \sprintf(
176
+ 'Input array must contain at least %d item%s but contains only %s item%s.',
177
+ $howMany,
178
+ 1 === $howMany ? '' : 's',
179
+ $len,
180
+ 1 === $len ? '' : 's'
181
+ )
182
+ );
183
+ }
184
+
185
+ $toResolve = $howMany;
186
+ $toReject = ($len - $toResolve) + 1;
187
+ $values = [];
188
+ $reasons = [];
189
+
190
+ foreach ($array as $i => $promiseOrValue) {
191
+ $fulfiller = function ($val) use ($i, &$values, &$toResolve, $toReject, $resolve) {
192
+ if ($toResolve < 1 || $toReject < 1) {
193
+ return;
194
+ }
195
+
196
+ $values[$i] = $val;
197
+
198
+ if (0 === --$toResolve) {
199
+ $resolve($values);
200
+ }
201
+ };
202
+
203
+ $rejecter = function ($reason) use ($i, &$reasons, &$toReject, $toResolve, $reject) {
204
+ if ($toResolve < 1 || $toReject < 1) {
205
+ return;
206
+ }
207
+
208
+ $reasons[$i] = $reason;
209
+
210
+ if (0 === --$toReject) {
211
+ $reject($reasons);
212
+ }
213
+ };
214
+
215
+ $cancellationQueue->enqueue($promiseOrValue);
216
+
217
+ resolve($promiseOrValue)
218
+ ->done($fulfiller, $rejecter, $notify);
219
+ }
220
+ }, $reject, $notify);
221
+ }, $cancellationQueue);
222
+ }
223
+
224
+ /**
225
+ * Traditional map function, similar to `array_map()`, but allows input to contain
226
+ * promises and/or values, and `$mapFunc` may return either a value or a promise.
227
+ *
228
+ * The map function receives each item as argument, where item is a fully resolved
229
+ * value of a promise or value in `$promisesOrValues`.
230
+ *
231
+ * @param array $promisesOrValues
232
+ * @param callable $mapFunc
233
+ * @return PromiseInterface
234
+ */
235
+ function map($promisesOrValues, callable $mapFunc)
236
+ {
237
+ $cancellationQueue = new CancellationQueue();
238
+ $cancellationQueue->enqueue($promisesOrValues);
239
+
240
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $mapFunc, $cancellationQueue) {
241
+ resolve($promisesOrValues)
242
+ ->done(function ($array) use ($mapFunc, $cancellationQueue, $resolve, $reject, $notify) {
243
+ if (!\is_array($array) || !$array) {
244
+ $resolve([]);
245
+ return;
246
+ }
247
+
248
+ $toResolve = \count($array);
249
+ $values = [];
250
+
251
+ foreach ($array as $i => $promiseOrValue) {
252
+ $cancellationQueue->enqueue($promiseOrValue);
253
+ $values[$i] = null;
254
+
255
+ resolve($promiseOrValue)
256
+ ->then($mapFunc)
257
+ ->done(
258
+ function ($mapped) use ($i, &$values, &$toResolve, $resolve) {
259
+ $values[$i] = $mapped;
260
+
261
+ if (0 === --$toResolve) {
262
+ $resolve($values);
263
+ }
264
+ },
265
+ $reject,
266
+ $notify
267
+ );
268
+ }
269
+ }, $reject, $notify);
270
+ }, $cancellationQueue);
271
+ }
272
+
273
+ /**
274
+ * Traditional reduce function, similar to `array_reduce()`, but input may contain
275
+ * promises and/or values, and `$reduceFunc` may return either a value or a
276
+ * promise, *and* `$initialValue` may be a promise or a value for the starting
277
+ * value.
278
+ *
279
+ * @param array $promisesOrValues
280
+ * @param callable $reduceFunc
281
+ * @param mixed $initialValue
282
+ * @return PromiseInterface
283
+ */
284
+ function reduce($promisesOrValues, callable $reduceFunc, $initialValue = null)
285
+ {
286
+ $cancellationQueue = new CancellationQueue();
287
+ $cancellationQueue->enqueue($promisesOrValues);
288
+
289
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $reduceFunc, $initialValue, $cancellationQueue) {
290
+ resolve($promisesOrValues)
291
+ ->done(function ($array) use ($reduceFunc, $initialValue, $cancellationQueue, $resolve, $reject, $notify) {
292
+ if (!\is_array($array)) {
293
+ $array = [];
294
+ }
295
+
296
+ $total = \count($array);
297
+ $i = 0;
298
+
299
+ // Wrap the supplied $reduceFunc with one that handles promises and then
300
+ // delegates to the supplied.
301
+ $wrappedReduceFunc = function ($current, $val) use ($reduceFunc, $cancellationQueue, $total, &$i) {
302
+ $cancellationQueue->enqueue($val);
303
+
304
+ return $current
305
+ ->then(function ($c) use ($reduceFunc, $total, &$i, $val) {
306
+ return resolve($val)
307
+ ->then(function ($value) use ($reduceFunc, $total, &$i, $c) {
308
+ return $reduceFunc($c, $value, $i++, $total);
309
+ });
310
+ });
311
+ };
312
+
313
+ $cancellationQueue->enqueue($initialValue);
314
+
315
+ \array_reduce($array, $wrappedReduceFunc, resolve($initialValue))
316
+ ->done($resolve, $reject, $notify);
317
+ }, $reject, $notify);
318
+ }, $cancellationQueue);
319
+ }
320
+
321
+ /**
322
+ * @internal
323
+ */
324
+ function _checkTypehint(callable $callback, $object)
325
+ {
326
+ if (!\is_object($object)) {
327
+ return true;
328
+ }
329
+
330
+ if (\is_array($callback)) {
331
+ $callbackReflection = new \ReflectionMethod($callback[0], $callback[1]);
332
+ } elseif (\is_object($callback) && !$callback instanceof \Closure) {
333
+ $callbackReflection = new \ReflectionMethod($callback, '__invoke');
334
+ } else {
335
+ $callbackReflection = new \ReflectionFunction($callback);
336
+ }
337
+
338
+ $parameters = $callbackReflection->getParameters();
339
+
340
+ if (!isset($parameters[0])) {
341
+ return true;
342
+ }
343
+
344
+ $expectedException = $parameters[0];
345
+
346
+ if (!$expectedException->getClass()) {
347
+ return true;
348
+ }
349
+
350
+ return $expectedException->getClass()->isInstance($object);
351
+ }
vendor/react/promise/src/functions_include.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!\function_exists('React\Promise\resolve')) {
4
+ require __DIR__.'/functions.php';
5
+ }