Shariff Wrapper - Version 1.0.0

Version Description

Download this release

Release Info

Developer starguide
Plugin Icon 128x128 Shariff Wrapper
Version 1.0.0
Comparing to
See all releases

Code changes from version 3.4.2 to 1.0.0

Files changed (234) hide show
  1. LICENSE.txt +3 -26
  2. admin/admin_menu.php +0 -1404
  3. admin/admin_notices.php +0 -83
  4. backend/index.php +29 -209
  5. backend/services/addthis.php +0 -14
  6. backend/services/facebook.php +0 -38
  7. backend/services/flattr.php +0 -19
  8. backend/services/googleplus.php +0 -41
  9. backend/services/linkedin.php +0 -14
  10. backend/services/pinterest.php +0 -15
  11. backend/services/reddit.php +0 -18
  12. backend/services/stumbleupon.php +0 -19
  13. backend/services/tumblr.php +0 -14
  14. backend/services/twitter.php +0 -14
  15. backend/services/vk.php +0 -17
  16. backend/services/xing.php +0 -30
  17. backend/shariff.json +11 -0
  18. backend/src/Backend.php +101 -0
  19. backend/src/Backend/Facebook.php +25 -0
  20. backend/src/Backend/GooglePlus.php +37 -0
  21. backend/src/Backend/Request.php +27 -0
  22. backend/src/Backend/ServiceInterface.php +9 -0
  23. backend/src/Backend/Twitter.php +23 -0
  24. backend/vendor/autoload.php +7 -0
  25. backend/vendor/composer/ClassLoader.php +354 -0
  26. backend/vendor/composer/autoload_classmap.php +9 -0
  27. backend/vendor/composer/autoload_files.php +10 -0
  28. backend/vendor/composer/autoload_namespaces.php +15 -0
  29. backend/vendor/composer/autoload_psr4.php +14 -0
  30. backend/vendor/composer/autoload_real.php +53 -0
  31. backend/vendor/composer/installed.json +527 -0
  32. backend/vendor/guzzlehttp/guzzle/.gitignore +11 -0
  33. backend/vendor/guzzlehttp/guzzle/.travis.yml +39 -0
  34. backend/vendor/guzzlehttp/guzzle/CHANGELOG.md +1013 -0
  35. backend/vendor/guzzlehttp/guzzle/LICENSE +19 -0
  36. backend/vendor/guzzlehttp/guzzle/Makefile +50 -0
  37. backend/vendor/guzzlehttp/guzzle/README.md +70 -0
  38. backend/vendor/guzzlehttp/guzzle/UPGRADING.md +1050 -0
  39. backend/vendor/guzzlehttp/guzzle/build/packager.php +21 -0
  40. backend/vendor/guzzlehttp/guzzle/composer.json +39 -0
  41. backend/vendor/guzzlehttp/guzzle/docs/Makefile +153 -0
  42. backend/vendor/guzzlehttp/guzzle/docs/_static/guzzle-icon.png +0 -0
  43. backend/vendor/guzzlehttp/guzzle/docs/_static/logo.png +0 -0
  44. backend/vendor/guzzlehttp/guzzle/docs/_templates/nav_links.html +3 -0
  45. backend/vendor/guzzlehttp/guzzle/docs/clients.rst +1298 -0
  46. backend/vendor/guzzlehttp/guzzle/docs/conf.py +28 -0
  47. backend/vendor/guzzlehttp/guzzle/docs/events.rst +508 -0
  48. backend/vendor/guzzlehttp/guzzle/docs/faq.rst +199 -0
  49. backend/vendor/guzzlehttp/guzzle/docs/handlers.rst +43 -0
  50. backend/vendor/guzzlehttp/guzzle/docs/http-messages.rst +483 -0
  51. backend/vendor/guzzlehttp/guzzle/docs/index.rst +98 -0
  52. backend/vendor/guzzlehttp/guzzle/docs/overview.rst +150 -0
  53. backend/vendor/guzzlehttp/guzzle/docs/quickstart.rst +448 -0
  54. backend/vendor/guzzlehttp/guzzle/docs/requirements.txt +2 -0
  55. backend/vendor/guzzlehttp/guzzle/docs/streams.rst +213 -0
  56. backend/vendor/guzzlehttp/guzzle/docs/testing.rst +232 -0
  57. backend/vendor/guzzlehttp/guzzle/phpunit.xml.dist +17 -0
  58. backend/vendor/guzzlehttp/guzzle/src/BatchResults.php +148 -0
  59. backend/vendor/guzzlehttp/guzzle/src/Client.php +390 -0
  60. backend/vendor/guzzlehttp/guzzle/src/ClientInterface.php +150 -0
  61. backend/vendor/guzzlehttp/guzzle/src/Collection.php +236 -0
  62. backend/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +248 -0
  63. backend/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +75 -0
  64. backend/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +86 -0
  65. backend/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +66 -0
  66. backend/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +373 -0
  67. backend/vendor/guzzlehttp/guzzle/src/Event/AbstractEvent.php +20 -0
  68. backend/vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php +51 -0
  69. backend/vendor/guzzlehttp/guzzle/src/Event/AbstractRetryableEvent.php +40 -0
  70. backend/vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php +61 -0
  71. backend/vendor/guzzlehttp/guzzle/src/Event/BeforeEvent.php +26 -0
  72. backend/vendor/guzzlehttp/guzzle/src/Event/CompleteEvent.php +14 -0
  73. backend/vendor/guzzlehttp/guzzle/src/Event/Emitter.php +146 -0
  74. backend/vendor/guzzlehttp/guzzle/src/Event/EmitterInterface.php +96 -0
  75. backend/vendor/guzzlehttp/guzzle/src/Event/EndEvent.php +28 -0
  76. backend/vendor/guzzlehttp/guzzle/src/Event/ErrorEvent.php +27 -0
  77. backend/vendor/guzzlehttp/guzzle/src/Event/EventInterface.php +23 -0
  78. backend/vendor/guzzlehttp/guzzle/src/Event/HasEmitterInterface.php +15 -0
  79. backend/vendor/guzzlehttp/guzzle/src/Event/HasEmitterTrait.php +20 -0
  80. backend/vendor/guzzlehttp/guzzle/src/Event/ListenerAttacherTrait.php +88 -0
  81. backend/vendor/guzzlehttp/guzzle/src/Event/ProgressEvent.php +51 -0
  82. backend/vendor/guzzlehttp/guzzle/src/Event/RequestEvents.php +56 -0
  83. backend/vendor/guzzlehttp/guzzle/src/Event/SubscriberInterface.php +34 -0
  84. backend/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php +7 -0
  85. backend/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php +7 -0
  86. backend/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php +4 -0
  87. backend/vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php +4 -0
  88. backend/vendor/guzzlehttp/guzzle/src/Exception/ParseException.php +31 -0
  89. backend/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +121 -0
  90. backend/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php +7 -0
  91. backend/vendor/guzzlehttp/guzzle/src/Exception/StateException.php +4 -0
  92. backend/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +4 -0
  93. backend/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php +4 -0
  94. backend/vendor/guzzlehttp/guzzle/src/Exception/XmlParseException.php +34 -0
  95. backend/vendor/guzzlehttp/guzzle/src/HasDataTrait.php +75 -0
  96. backend/vendor/guzzlehttp/guzzle/src/Message/AbstractMessage.php +253 -0
  97. backend/vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php +158 -0
  98. backend/vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php +368 -0
  99. backend/vendor/guzzlehttp/guzzle/src/Message/MessageFactoryInterface.php +71 -0
  100. backend/vendor/guzzlehttp/guzzle/src/Message/MessageInterface.php +136 -0
  101. backend/vendor/guzzlehttp/guzzle/src/Message/MessageParser.php +171 -0
  102. backend/vendor/guzzlehttp/guzzle/src/Message/Request.php +195 -0
  103. backend/vendor/guzzlehttp/guzzle/src/Message/RequestInterface.php +136 -0
  104. backend/vendor/guzzlehttp/guzzle/src/Message/Response.php +208 -0
  105. backend/vendor/guzzlehttp/guzzle/src/Message/ResponseInterface.php +111 -0
  106. backend/vendor/guzzlehttp/guzzle/src/Mimetypes.php +963 -0
  107. backend/vendor/guzzlehttp/guzzle/src/Pool.php +280 -0
  108. backend/vendor/guzzlehttp/guzzle/src/Post/MultipartBody.php +109 -0
  109. backend/vendor/guzzlehttp/guzzle/src/Post/PostBody.php +287 -0
  110. backend/vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php +116 -0
  111. backend/vendor/guzzlehttp/guzzle/src/Post/PostFile.php +135 -0
  112. backend/vendor/guzzlehttp/guzzle/src/Post/PostFileInterface.php +41 -0
  113. backend/vendor/guzzlehttp/guzzle/src/Query.php +204 -0
  114. backend/vendor/guzzlehttp/guzzle/src/QueryParser.php +163 -0
  115. backend/vendor/guzzlehttp/guzzle/src/RequestFsm.php +214 -0
  116. backend/vendor/guzzlehttp/guzzle/src/RingBridge.php +170 -0
  117. backend/vendor/guzzlehttp/guzzle/src/Subscriber/Cookie.php +58 -0
  118. backend/vendor/guzzlehttp/guzzle/src/Subscriber/History.php +172 -0
  119. backend/vendor/guzzlehttp/guzzle/src/Subscriber/HttpError.php +36 -0
  120. backend/vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php +132 -0
  121. backend/vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php +130 -0
  122. backend/vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php +156 -0
  123. backend/vendor/guzzlehttp/guzzle/src/ToArrayInterface.php +15 -0
  124. backend/vendor/guzzlehttp/guzzle/src/Transaction.php +85 -0
  125. backend/vendor/guzzlehttp/guzzle/src/UriTemplate.php +241 -0
  126. backend/vendor/guzzlehttp/guzzle/src/Url.php +595 -0
  127. backend/vendor/guzzlehttp/guzzle/src/Utils.php +145 -0
  128. backend/vendor/guzzlehttp/ringphp/.gitignore +4 -0
  129. backend/vendor/guzzlehttp/ringphp/.travis.yml +21 -0
  130. backend/vendor/guzzlehttp/ringphp/CHANGELOG.md +22 -0
  131. backend/vendor/guzzlehttp/ringphp/LICENSE +19 -0
  132. backend/vendor/guzzlehttp/ringphp/Makefile +46 -0
  133. backend/vendor/guzzlehttp/ringphp/README.rst +46 -0
  134. backend/vendor/guzzlehttp/ringphp/composer.json +38 -0
  135. backend/vendor/guzzlehttp/ringphp/docs/Makefile +153 -0
  136. backend/vendor/guzzlehttp/ringphp/docs/client_handlers.rst +173 -0
  137. backend/vendor/guzzlehttp/ringphp/docs/client_middleware.rst +165 -0
  138. backend/vendor/guzzlehttp/ringphp/docs/conf.py +23 -0
  139. backend/vendor/guzzlehttp/ringphp/docs/futures.rst +164 -0
  140. backend/vendor/guzzlehttp/ringphp/docs/index.rst +50 -0
  141. backend/vendor/guzzlehttp/ringphp/docs/requirements.txt +1 -0
  142. backend/vendor/guzzlehttp/ringphp/docs/spec.rst +311 -0
  143. backend/vendor/guzzlehttp/ringphp/docs/testing.rst +74 -0
  144. backend/vendor/guzzlehttp/ringphp/phpunit.xml.dist +14 -0
  145. backend/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php +74 -0
  146. backend/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php +538 -0
  147. backend/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php +117 -0
  148. backend/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php +239 -0
  149. backend/vendor/guzzlehttp/ringphp/src/Client/Middleware.php +58 -0
  150. backend/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php +52 -0
  151. backend/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php +400 -0
  152. backend/vendor/guzzlehttp/ringphp/src/Core.php +364 -0
  153. backend/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php +7 -0
  154. backend/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php +4 -0
  155. backend/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php +7 -0
  156. backend/vendor/guzzlehttp/ringphp/src/Exception/RingException.php +4 -0
  157. backend/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php +125 -0
  158. backend/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php +43 -0
  159. backend/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php +57 -0
  160. backend/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php +40 -0
  161. backend/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php +11 -0
  162. backend/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php +56 -0
  163. backend/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php +12 -0
  164. backend/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php +32 -0
  165. backend/vendor/guzzlehttp/streams/.gitignore +6 -0
  166. backend/vendor/guzzlehttp/streams/.travis.yml +17 -0
  167. backend/vendor/guzzlehttp/streams/CHANGELOG.rst +94 -0
  168. backend/vendor/guzzlehttp/streams/LICENSE +19 -0
  169. backend/vendor/guzzlehttp/streams/Makefile +19 -0
  170. backend/vendor/guzzlehttp/streams/README.rst +36 -0
  171. backend/vendor/guzzlehttp/streams/composer.json +28 -0
  172. backend/vendor/guzzlehttp/streams/phpunit.xml.dist +17 -0
  173. backend/vendor/guzzlehttp/streams/src/AppendStream.php +220 -0
  174. backend/vendor/guzzlehttp/streams/src/AsyncReadStream.php +207 -0
  175. backend/vendor/guzzlehttp/streams/src/BufferStream.php +138 -0
  176. backend/vendor/guzzlehttp/streams/src/CachingStream.php +122 -0
  177. backend/vendor/guzzlehttp/streams/src/DroppingStream.php +42 -0
  178. backend/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php +4 -0
  179. backend/vendor/guzzlehttp/streams/src/Exception/SeekException.php +27 -0
  180. backend/vendor/guzzlehttp/streams/src/FnStream.php +147 -0
  181. backend/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php +117 -0
  182. backend/vendor/guzzlehttp/streams/src/InflateStream.php +27 -0
  183. backend/vendor/guzzlehttp/streams/src/LazyOpenStream.php +37 -0
  184. backend/vendor/guzzlehttp/streams/src/LimitStream.php +161 -0
  185. backend/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php +11 -0
  186. backend/vendor/guzzlehttp/streams/src/NoSeekStream.php +25 -0
  187. backend/vendor/guzzlehttp/streams/src/NullStream.php +78 -0
  188. backend/vendor/guzzlehttp/streams/src/PumpStream.php +161 -0
  189. backend/vendor/guzzlehttp/streams/src/Stream.php +261 -0
  190. backend/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php +143 -0
  191. backend/vendor/guzzlehttp/streams/src/StreamInterface.php +159 -0
  192. backend/vendor/guzzlehttp/streams/src/Utils.php +196 -0
  193. backend/vendor/react/promise/.gitignore +4 -0
  194. backend/vendor/react/promise/.travis.yml +13 -0
  195. backend/vendor/react/promise/CHANGELOG.md +48 -0
  196. backend/vendor/react/promise/LICENSE +22 -0
  197. backend/vendor/react/promise/README.md +617 -0
  198. backend/vendor/react/promise/composer.json +22 -0
  199. backend/vendor/react/promise/phpunit.xml.dist +25 -0
  200. backend/vendor/react/promise/src/CancellablePromiseInterface.php +11 -0
  201. backend/vendor/react/promise/src/Deferred.php +51 -0
  202. backend/vendor/react/promise/src/FulfilledPromise.php +36 -0
  203. backend/vendor/react/promise/src/LazyPromise.php +37 -0
  204. backend/vendor/react/promise/src/Promise.php +135 -0
  205. backend/vendor/react/promise/src/PromiseInterface.php +11 -0
  206. backend/vendor/react/promise/src/PromisorInterface.php +11 -0
  207. backend/vendor/react/promise/src/RejectedPromise.php +34 -0
  208. backend/vendor/react/promise/src/functions.php +160 -0
  209. backend/vendor/zendframework/zend-cache/Zend/Cache/CONTRIBUTING.md +3 -0
  210. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/BadMethodCallException.php +15 -0
  211. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/ExceptionInterface.php +14 -0
  212. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/ExtensionNotLoadedException.php +14 -0
  213. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/InvalidArgumentException.php +15 -0
  214. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/LogicException.php +14 -0
  215. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/MissingDependencyException.php +14 -0
  216. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/MissingKeyException.php +14 -0
  217. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/OutOfSpaceException.php +14 -0
  218. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/RuntimeException.php +14 -0
  219. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/UnexpectedValueException.php +15 -0
  220. backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/UnsupportedMethodCallException.php +15 -0
  221. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/AbstractPattern.php +50 -0
  222. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/CallbackCache.php +200 -0
  223. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/CaptureCache.php +389 -0
  224. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/ClassCache.php +167 -0
  225. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/ObjectCache.php +284 -0
  226. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/OutputCache.php +89 -0
  227. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/PatternInterface.php +28 -0
  228. backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/PatternOptions.php +765 -0
  229. backend/vendor/zendframework/zend-cache/Zend/Cache/PatternFactory.php +92 -0
  230. backend/vendor/zendframework/zend-cache/Zend/Cache/PatternPluginManager.php +66 -0
  231. backend/vendor/zendframework/zend-cache/Zend/Cache/README.md +14 -0
  232. backend/vendor/zendframework/zend-cache/Zend/Cache/Service/StorageCacheAbstractServiceFactory.php +88 -0
  233. backend/vendor/zendframework/zend-cache/Zend/Cache/Service/StorageCacheFactory.php +30 -0
  234. backend/vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/AbstractAdapter.php +972 -0
LICENSE.txt CHANGED
@@ -1,8 +1,6 @@
1
- Shariff
2
-
3
  The MIT License (MIT)
4
 
5
- Copyright (c) 2015 Heise Medien GmbH & Co. KG and other contributors.
6
 
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
8
  of this software and associated documentation files (the "Software"), to deal
@@ -22,26 +20,5 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
  THE SOFTWARE.
24
 
25
- Shariff Wrapper (WordPress Plugin)
26
-
27
- The MIT License (MIT)
28
-
29
- Copyright (c) 2015 3UU productions ("Ritze") and other contributors.
30
-
31
- Permission is hereby granted, free of charge, to any person obtaining a copy
32
- of this software and associated documentation files (the "Software"), to deal
33
- in the Software without restriction, including without limitation the rights
34
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
- copies of the Software, and to permit persons to whom the Software is
36
- furnished to do so, subject to the following conditions:
37
-
38
- The above copyright notice and this permission notice shall be included in
39
- all copies or substantial portions of the Software.
40
-
41
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
- THE SOFTWARE.
 
 
1
  The MIT License (MIT)
2
 
3
+ Copyright (c) 2014 Heise Zeitschriften Verlag GmbH & Co. KG and other contributors.
4
 
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
  of this software and associated documentation files (the "Software"), to deal
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
  THE SOFTWARE.
22
 
23
+ Copyright (c) 2014 by 3UU productions ("Ritze")
24
+ Same as above for my Wordpress plugin.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/admin_menu.php DELETED
@@ -1,1404 +0,0 @@
1
- <?php
2
- /**
3
- * Will be included in the shariff.php only, when an admin is logged in.
4
- * Everything reagarding the admin menu was moved to this file.
5
- */
6
-
7
- // prevent direct calls to admin_menu.php
8
- if ( ! class_exists('WP') ) { die(); }
9
-
10
- // the admin page
11
- add_action( 'admin_menu', 'shariff3UU_add_admin_menu' );
12
- add_action( 'admin_init', 'shariff3UU_options_init' );
13
- add_action( 'init', 'shariff3UU_init_locale' );
14
-
15
- // add settings link on plugin page
16
- function shariff3UU_settings_link( $links ) {
17
- $settings_link = '<a href="options-general.php?page=shariff3uu">' . __( 'Settings', 'shariff3UU' ) . '</a>';
18
- array_unshift( $links, $settings_link );
19
- return $links;
20
- }
21
- $plugin = plugin_basename( __FILE__ );
22
- add_filter( "plugin_action_links_$plugin", 'shariff3UU_settings_link' );
23
-
24
- // scripts and styles for admin pages e.g. info notice
25
- function shariff3UU_admin_style( $hook ) {
26
- // styles for admin notice - needed on _ALL_ admin pages
27
- wp_enqueue_style( 'shariff_admin-notice', plugins_url( '../css/shariff_admin-notice.css', __FILE__ ) );
28
- // styles and scripts only needed on our plugin options page - no need to load them on _ALL_ admin pages
29
- if ( $hook == 'settings_page_shariff3uu' ) {
30
- // styles for our plugin options page
31
- wp_enqueue_style( 'shariff_options', plugins_url( '../css/shariff_options.css', __FILE__ ) );
32
- // scripts for pinterest default image media uploader
33
- wp_enqueue_script( 'jquery' ); // just in case
34
- wp_enqueue_media();
35
- }
36
- }
37
- add_action( 'admin_enqueue_scripts', 'shariff3UU_admin_style' );
38
-
39
- // add admin menu
40
- function shariff3UU_add_admin_menu() {
41
- add_options_page( 'Shariff', 'Shariff', 'manage_options', 'shariff3uu', 'shariff3UU_options_page' );
42
- }
43
-
44
- // plugin options page
45
- function shariff3UU_options_init(){
46
-
47
- // first tab - basic
48
-
49
- // register first tab (basic) settings and call sanitize function
50
- register_setting( 'basic', 'shariff3UU_basic', 'shariff3UU_basic_sanitize' );
51
-
52
- // first tab - basic options
53
- add_settings_section( 'shariff3UU_basic_section', __( 'Basic options', 'shariff3UU' ),
54
- 'shariff3UU_basic_section_callback', 'basic' );
55
-
56
- // services
57
- add_settings_field( 'shariff3UU_text_services', '<div class="shariff_status-col">' . __( 'Enable the following services in the provided order:', 'shariff3UU' ) . '</div>',
58
- 'shariff3UU_text_services_render', 'basic', 'shariff3UU_basic_section' );
59
-
60
- // add after
61
- add_settings_field( 'shariff3UU_multiplecheckbox_add_after', __( 'Add the Shariff buttons <u>after</u> all:', 'shariff3UU' ),
62
- 'shariff3UU_multiplecheckbox_add_after_render', 'basic', 'shariff3UU_basic_section' );
63
-
64
- // add before
65
- add_settings_field( 'shariff3UU_checkbox_add_before', __( 'Add the Shariff buttons <u>before</u> all:', 'shariff3UU' ),
66
- 'shariff3UU_multiplecheckbox_add_before_render', 'basic', 'shariff3UU_basic_section' );
67
-
68
- // disable on protected posts
69
- add_settings_field( 'shariff3UU_checkbox_disable_on_protected', __( 'Disable the Shariff buttons on password protected posts.', 'shariff3UU' ),
70
- 'shariff3UU_checkbox_disable_on_protected_render', 'basic', 'shariff3UU_basic_section' );
71
-
72
- // second tab - design
73
-
74
- // register second tab (design) settings and call sanitize function
75
- register_setting( 'design', 'shariff3UU_design', 'shariff3UU_design_sanitize' );
76
-
77
- // second tab - design options
78
- add_settings_section( 'shariff3UU_design_section', __( 'Design options', 'shariff3UU' ),
79
- 'shariff3UU_design_section_callback', 'design' );
80
-
81
- // button language
82
- add_settings_field( 'shariff3UU_select_language', '<div class="shariff_status-col">' . __( 'Shariff button language:', 'shariff3UU' ) . '</div>',
83
- 'shariff3UU_select_language_render', 'design', 'shariff3UU_design_section' );
84
-
85
- // theme
86
- add_settings_field( 'shariff3UU_radio_theme', __( 'Shariff button design:', 'shariff3UU' ),
87
- 'shariff3UU_radio_theme_render', 'design', 'shariff3UU_design_section' );
88
-
89
- // button size
90
- add_settings_field( 'shariff3UU_checkbox_buttonsize', __( 'Reduce button size by 30%.', 'shariff3UU' ),
91
- 'shariff3UU_checkbox_buttonsize_render', 'design', 'shariff3UU_design_section' );
92
-
93
- // button stretch
94
- add_settings_field( 'shariff3UU_checkbox_buttonsstretch', __( 'Stretch buttons horizontally to full width.', 'shariff3UU' ),
95
- 'shariff3UU_checkbox_buttonstretch_render', 'design', 'shariff3UU_design_section' );
96
-
97
- // vertical
98
- add_settings_field( 'shariff3UU_checkbox_vertical', __( 'Shariff button orientation <b>vertical</b>.', 'shariff3UU' ),
99
- 'shariff3UU_checkbox_vertical_render', 'design', 'shariff3UU_design_section' );
100
-
101
- // alignment option
102
- add_settings_field( 'shariff3UU_radio_align', __( 'Alignment of the Shariff buttons:', 'shariff3UU' ),
103
- 'shariff3UU_radio_align_render', 'design', 'shariff3UU_design_section' );
104
-
105
- // alignment option for the widget
106
- add_settings_field( 'shariff3UU_radio_align_widget', __( 'Alignment of the Shariff buttons in the widget:', 'shariff3UU' ),
107
- 'shariff3UU_radio_align_widget_render', 'design', 'shariff3UU_design_section' );
108
-
109
- // headline
110
- add_settings_field( 'shariff3UU_text_headline', __( 'Headline above all Shariff buttons:', 'shariff3UU' ),
111
- 'shariff3UU_text_headline_render', 'design', 'shariff3UU_design_section' );
112
-
113
- // custom css
114
- add_settings_field( 'shariff3UU_text_style', __( 'CSS attributes for the container <span style="text-decoration: underline;">around</span> Shariff:', 'shariff3UU' ),
115
- 'shariff3UU_text_style_render', 'design', 'shariff3UU_design_section' );
116
-
117
- // third tab - advanced
118
-
119
- // register third tab (advanced) settings and call sanitize function
120
- register_setting( 'advanced', 'shariff3UU_advanced', 'shariff3UU_advanced_sanitize' );
121
-
122
- // third tab - advanced options
123
- add_settings_section( 'shariff3UU_advanced_section', __( 'Advanced options', 'shariff3UU' ),
124
- 'shariff3UU_advanced_section_callback', 'advanced' );
125
-
126
- // info url
127
- add_settings_field(
128
- 'shariff3UU_text_info_url', '<div class="shariff_status-col">' . __( 'Custom link for the info button:', 'shariff3UU' ) . '</div>',
129
- 'shariff3UU_text_info_url_render', 'advanced', 'shariff3UU_advanced_section' );
130
-
131
- // twitter via
132
- add_settings_field(
133
- 'shariff3UU_text_twittervia', __( 'Twitter username for the via tag:', 'shariff3UU' ),
134
- 'shariff3UU_text_twittervia_render', 'advanced', 'shariff3UU_advanced_section' );
135
-
136
- // flattr username
137
- add_settings_field(
138
- 'shariff3UU_text_flattruser', __( 'Flattr username:', 'shariff3UU' ),
139
- 'shariff3UU_text_flattruser_render', 'advanced', 'shariff3UU_advanced_section' );
140
-
141
- // patreon username
142
- add_settings_field(
143
- 'shariff3UU_text_patreonid', __( 'Patreon username:', 'shariff3UU' ),
144
- 'shariff3UU_text_patreonid_render', 'advanced', 'shariff3UU_advanced_section' );
145
-
146
- // paypal button id
147
- add_settings_field(
148
- 'shariff3UU_text_paypalbuttonid', __( 'PayPal hosted button ID:', 'shariff3UU' ),
149
- 'shariff3UU_text_paypalbuttonid_render', 'advanced', 'shariff3UU_advanced_section' );
150
-
151
- // paypalme id
152
- add_settings_field(
153
- 'shariff3UU_text_paypalmeid', __( 'PayPal.Me ID:', 'shariff3UU' ),
154
- 'shariff3UU_text_paypalmeid_render', 'advanced', 'shariff3UU_advanced_section' );
155
-
156
- // bitcoin address
157
- add_settings_field(
158
- 'shariff3UU_text_bitcoinaddress', __( 'Bitcoin address:', 'shariff3UU' ),
159
- 'shariff3UU_text_bitcoinaddress_render', 'advanced', 'shariff3UU_advanced_section' );
160
-
161
- // rss feed
162
- add_settings_field(
163
- 'shariff3UU_text_rssfeed', __( 'RSS feed:', 'shariff3UU' ),
164
- 'shariff3UU_text_rssfeed_render', 'advanced', 'shariff3UU_advanced_section' );
165
-
166
- // default image for pinterest
167
- add_settings_field( 'shariff3UU_text_default_pinterest', __( 'Default image for Pinterest:', 'shariff3UU' ),
168
- 'shariff3UU_text_default_pinterest_render', 'advanced', 'shariff3UU_advanced_section' );
169
-
170
- // fourth tab - mailform
171
-
172
- // register fourth tab (mailform) settings and call sanitize function
173
- register_setting( 'mailform', 'shariff3UU_mailform', 'shariff3UU_mailform_sanitize' );
174
-
175
- // fourth tab - mailform options
176
- add_settings_section( 'shariff3UU_mailform_section', __( 'Mail form options', 'shariff3UU' ),
177
- 'shariff3UU_mailform_section_callback', 'mailform' );
178
-
179
- // disable mailform
180
- add_settings_field(
181
- 'shariff3UU_checkbox_disable_mailform', '<div class="shariff_status-col">' . __( 'Disable the mail form functionality.', 'shariff3UU' ) .'</div>',
182
- 'shariff3UU_checkbox_disable_mailform_render', 'mailform', 'shariff3UU_mailform_section' );
183
-
184
- // require sender e-mail address
185
- add_settings_field(
186
- 'shariff3UU_checkbox_require_sender', '<div class="shariff_status-col">' . __( 'Require sender e-mail address.', 'shariff3UU' ) .'</div>',
187
- 'shariff3UU_checkbox_require_sender_render', 'mailform', 'shariff3UU_mailform_section' );
188
-
189
- // mailform language
190
- add_settings_field(
191
- 'shariff3UU_select_mailform_language', '<div class="shariff_status-col">' . __( 'Mailform language:', 'shariff3UU' ) .'</div>',
192
- 'shariff3UU_select_mailform_language_render', 'mailform', 'shariff3UU_mailform_section' );
193
-
194
- // add content of the post to e-mails
195
- add_settings_field(
196
- 'shariff3UU_checkbox_mail_add_post_content', '<div class="shariff_status-col">' . __( 'Add the post content to the e-mail body.', 'shariff3UU' ) .'</div>',
197
- 'shariff3UU_checkbox_mail_add_post_content_render', 'mailform', 'shariff3UU_mailform_section' );
198
-
199
- // mail sender name
200
- add_settings_field(
201
- 'shariff3UU_text_mail_sender_name', '<div class="shariff_status-col">' . __( 'Default sender name:', 'shariff3UU' ) .'</div>',
202
- 'shariff3UU_text_mail_sender_name_render', 'mailform', 'shariff3UU_mailform_section' );
203
-
204
- // mail sender address
205
- add_settings_field(
206
- 'shariff3UU_text_mail_sender_from', '<div class="shariff_status-col">' . __( 'Default sender e-mail address:', 'shariff3UU' ) .'</div>',
207
- 'shariff3UU_text_mail_sender_from_render', 'mailform', 'shariff3UU_mailform_section' );
208
-
209
- // fifth tab - statistic
210
-
211
- // register fifth tab (statistic) settings and call sanitize function
212
- register_setting( 'statistic', 'shariff3UU_statistic', 'shariff3UU_statistic_sanitize' );
213
-
214
- // fifth tab (statistic)
215
- add_settings_section( 'shariff3UU_statistic_section', __( 'Statistic', 'shariff3UU' ),
216
- 'shariff3UU_statistic_section_callback', 'statistic' );
217
-
218
- // share counts
219
- add_settings_field( 'shariff3UU_checkbox_backend', '<div class="shariff_status-col">' . __( 'Enable share counts (statistic).', 'shariff3UU' ) .'</div>',
220
- 'shariff3UU_checkbox_backend_render', 'statistic', 'shariff3UU_statistic_section' );
221
-
222
- // Facebook App ID
223
- add_settings_field( 'shariff3UU_text_fb_id', '<div class="shariff_status-col">' . __( 'Facebook App ID:', 'shariff3UU' ) .'</div>',
224
- 'shariff3UU_text_fb_id_render', 'statistic', 'shariff3UU_statistic_section' );
225
-
226
- // Facebook App Secret
227
- add_settings_field( 'shariff3UU_text_fb_secret', '<div class="shariff_status-col">' . __( 'Facebook App Secret:', 'shariff3UU' ) .'</div>',
228
- 'shariff3UU_text_fb_secret_render', 'statistic', 'shariff3UU_statistic_section' );
229
-
230
- // ttl
231
- add_settings_field( 'shariff3UU_number_ttl', '<div class="shariff_status-col">' . __( 'Cache TTL in seconds (60 - 7200):', 'shariff3UU' ) .'</div>',
232
- 'shariff3UU_number_ttl_render', 'statistic', 'shariff3UU_statistic_section' );
233
-
234
- // disable services
235
- add_settings_field( 'shariff3UU_multiplecheckbox_disable_services', '<div class="shariff_status-col">' . __( 'Disable the following services (share counts only):', 'shariff3UU' ) .'</div>',
236
- 'shariff3UU_multiplecheckbox_disable_services_render', 'statistic', 'shariff3UU_statistic_section' );
237
-
238
- // external hosts
239
- add_settings_field( 'shariff3UU_text_external_host', '<div class="shariff_status-col">' . __( 'External host for share counts, shariff.js and CSS:', 'shariff3UU' ) .'</div>',
240
- 'shariff3UU_text_external_host_render', 'statistic', 'shariff3UU_statistic_section' );
241
-
242
- // sixth tab - help
243
-
244
- // register sixth tab (help)
245
- add_settings_section( 'shariff3UU_help_section', __( 'Shariff Help', 'shariff3UU' ),
246
- 'shariff3UU_help_section_callback', 'help' );
247
-
248
- // seventh tab - status
249
-
250
- // register seventh tab (status)
251
- add_settings_section( 'shariff3UU_status_section', __( 'Status', 'shariff3UU' ),
252
- 'shariff3UU_status_section_callback', 'status' );
253
- }
254
-
255
- // sanitize input from the basic settings page
256
- function shariff3UU_basic_sanitize( $input ) {
257
- // create array
258
- $valid = array();
259
-
260
- if ( isset( $input["version"] ) ) $valid["version"] = sanitize_text_field( $input["version"] );
261
- if ( isset( $input["services"] ) ) $valid["services"] = str_replace( ' ', '', sanitize_text_field( $input["services"] ) );
262
- if ( isset( $input["add_after"] ) ) $valid["add_after"] = sani_arrays( $input["add_after"] );
263
- if ( isset( $input["add_before"] ) ) $valid["add_before"] = sani_arrays( $input["add_before"] );
264
- if ( isset( $input["disable_on_protected"] ) ) $valid["disable_on_protected"] = absint( $input["disable_on_protected"] );
265
-
266
- // remove empty elements
267
- $valid = array_filter( $valid );
268
-
269
- return $valid;
270
- }
271
-
272
- // sanitize input from the design settings page
273
- function shariff3UU_design_sanitize( $input ) {
274
- // create array
275
- $valid = array();
276
-
277
- if ( isset( $input["lang"] ) ) $valid["lang"] = sanitize_text_field( $input["lang"] );
278
- if ( isset( $input["theme"] ) ) $valid["theme"] = sanitize_text_field( $input["theme"] );
279
- if ( isset( $input["buttonsize"] ) ) $valid["buttonsize"] = absint( $input["buttonsize"] );
280
- if ( isset( $input["buttonstretch"] ) ) $valid["buttonstretch"] = absint( $input["buttonstretch"] );
281
- if ( isset( $input["vertical"] ) ) $valid["vertical"] = absint( $input["vertical"] );
282
- if ( isset( $input["align"] ) ) $valid["align"] = sanitize_text_field( $input["align"] );
283
- if ( isset( $input["align_widget"] ) ) $valid["align_widget"] = sanitize_text_field( $input["align_widget"] );
284
- if ( isset( $input["style"] ) ) $valid["style"] = sanitize_text_field( $input["style"] );
285
- if ( isset( $input["headline"] ) ) $valid["headline"] = wp_kses( $input["headline"], $GLOBALS["allowed_tags"] );
286
-
287
- // remove empty elements
288
- $valid = array_filter($valid);
289
-
290
- return $valid;
291
- }
292
-
293
- // sanitize input from the advanced settings page
294
- function shariff3UU_advanced_sanitize( $input ) {
295
- // create array
296
- $valid = array();
297
-
298
- // waiting for fix https://core.trac.wordpress.org/ticket/28015 in order to use esc_url_raw instead for info_url
299
- if ( isset($input["info_url"] ) ) $valid["info_url"] = sanitize_text_field( $input["info_url"] );
300
- if ( isset($input["twitter_via"] ) ) $valid["twitter_via"] = str_replace( '@', '', sanitize_text_field( $input["twitter_via"] ) );
301
- if ( isset($input["flattruser"] ) ) $valid["flattruser"] = str_replace( '@', '', sanitize_text_field( $input["flattruser"] ) );
302
- if ( isset($input["patreonid"] ) ) $valid["patreonid"] = str_replace( '@', '', sanitize_text_field( $input["patreonid"] ) );
303
- if ( isset($input["paypalbuttonid"] ) ) $valid["paypalbuttonid"] = str_replace( '@', '', sanitize_text_field( $input["paypalbuttonid"] ) );
304
- if ( isset($input["paypalmeid"] ) ) $valid["paypalmeid"] = str_replace( '@', '', sanitize_text_field( $input["paypalmeid"] ) );
305
- if ( isset($input["bitcoinaddress"] ) ) $valid["bitcoinaddress"] = str_replace( '@', '', sanitize_text_field( $input["bitcoinaddress"] ) );
306
- if ( isset($input["rssfeed"] ) ) $valid["rssfeed"] = str_replace( '@', '', sanitize_text_field( $input["rssfeed"] ) );
307
- if ( isset($input["default_pinterest"] ) ) $valid["default_pinterest"] = sanitize_text_field( $input["default_pinterest"] );
308
-
309
- // remove empty elements
310
- $valid = array_filter( $valid );
311
-
312
- return $valid;
313
- }
314
-
315
- // sanitize input from the mailform settings page
316
- function shariff3UU_mailform_sanitize( $input ) {
317
- // create array
318
- $valid = array();
319
-
320
- if ( isset( $input["disable_mailform"] ) ) $valid["disable_mailform"] = absint( $input["disable_mailform"] );
321
- if ( isset( $input["require_sender"] ) ) $valid["require_sender"] = absint( $input["require_sender"] );
322
- if ( isset( $input["mailform_language"] ) ) $valid["mailform_language"] = sanitize_text_field( $input["mailform_language"] );
323
- if ( isset( $input["mail_add_post_content"] ) ) $valid["mail_add_post_content"] = absint( $input["mail_add_post_content"] );
324
- if ( isset( $input["mail_sender_name"] ) ) $valid["mail_sender_name"] = sanitize_text_field( $input["mail_sender_name"] );
325
- if ( isset( $input["mail_sender_from"] ) && is_email( $input["mail_sender_from"] ) != false ) $valid["mail_sender_from"] = sanitize_email( $input["mail_sender_from"] );
326
-
327
- // remove empty elements
328
- $valid = array_filter( $valid );
329
-
330
- return $valid;
331
- }
332
-
333
- // sanitize input from the statistic settings page
334
- function shariff3UU_statistic_sanitize( $input ) {
335
- // create array
336
- $valid = array();
337
-
338
- if ( isset( $input["backend"] ) ) $valid["backend"] = absint( $input["backend"] );
339
- if ( isset( $input["fb_id"] ) ) $valid["fb_id"] = sanitize_text_field( $input["fb_id"] );
340
- if ( isset( $input["fb_secret"] ) ) $valid["fb_secret"] = sanitize_text_field( $input["fb_secret"] );
341
- if ( isset( $input["ttl"] ) ) $valid["ttl"] = absint( $input["ttl"] );
342
- if ( isset( $input["disable"] ) ) $valid["disable"] = sani_arrays( $input["disable"] );
343
- if ( isset( $input["external_host"] ) ) $valid["external_host"] = str_replace( ' ', '', sanitize_text_field( $input["external_host"] ) );
344
-
345
- // protect users from themselfs
346
- if ( isset( $valid["ttl"] ) && $valid["ttl"] < '60' ) $valid["ttl"] = '';
347
- elseif ( isset( $valid["ttl"] ) && $valid["ttl"] > '7200' ) $valid["ttl"] = '7200';
348
-
349
- // remove empty elements
350
- $valid = array_filter( $valid );
351
-
352
- return $valid;
353
- }
354
-
355
- // helper function to sanitize arrays
356
- function sani_arrays( $data = array() ) {
357
- if ( ! is_array($data) || ! count( $data ) ) {
358
- return array();
359
- }
360
- foreach ( $data as $k => $v ) {
361
- if ( ! is_array( $v ) && ! is_object( $v ) ) {
362
- $data[ $k ] = absint( trim( $v ) );
363
- }
364
- if ( is_array( $v ) ) {
365
- $data[ $k ] = sani_arrays( $v );
366
- }
367
- }
368
- return $data;
369
- }
370
-
371
- // render admin options: use isset() to prevent errors while debug mode is on
372
-
373
- // basic options
374
-
375
- // description basic options
376
- function shariff3UU_basic_section_callback(){
377
- echo __( "Select the desired services in the order you want them to be displayed and where the Shariff buttons should be included automatically.", "shariff3UU" );
378
- }
379
-
380
- // services
381
- function shariff3UU_text_services_render(){
382
- if ( isset( $GLOBALS["shariff3UU_basic"]["services"] ) ) {
383
- $services = $GLOBALS["shariff3UU_basic"]["services"];
384
- }
385
- else {
386
- $services = '';
387
- }
388
- echo '<input type="text" name="shariff3UU_basic[services]" value="' . esc_html($services) . '" size="75" placeholder="twitter|facebook|googleplus|info">';
389
- echo '<p><code>facebook|twitter|googleplus|whatsapp|threema|pinterest|xing|linkedin|reddit|vk|diaspora|stumbleupon</code></p>';
390
- echo '<p><code>tumblr|addthis|flattr|patreon|paypal|paypalme|bitcoin|mailform|mailto|printer|info|rss</code></p>';
391
- echo '<p>' . __( 'Use the pipe sign | (Alt Gr + &lt; or &#8997; + 7) between two or more services.', 'shariff3UU' ) . '</p>';
392
- }
393
-
394
- // add after
395
- function shariff3UU_multiplecheckbox_add_after_render() {
396
- // add after all posts
397
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_after][posts]" ';
398
- if ( isset( $GLOBALS['shariff3UU_basic']['add_after']['posts'] ) ) echo checked( $GLOBALS['shariff3UU_basic']['add_after']['posts'], 1, 0 );
399
- echo ' value="1">' . __('Posts', 'shariff3UU') . '</p>';
400
-
401
- // add after all posts (blog page)
402
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_after][posts_blogpage]" ';
403
- if ( isset( $GLOBALS["shariff3UU_basic"]["add_after"]["posts_blogpage"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["add_after"]["posts_blogpage"], 1, 0 );
404
- echo ' value="1">' . __('Posts (blog page)', 'shariff3UU') . '</p>';
405
-
406
- // add after all pages
407
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_after][pages]" ';
408
- if ( isset( $GLOBALS["shariff3UU_basic"]["add_after"]["pages"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["add_after"]["pages"], 1, 0 );
409
- echo ' value="1">' . __('Pages', 'shariff3UU') . '</p>';
410
-
411
- // add after all bbpress replies
412
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_after][bbp_reply]" ';
413
- if ( isset( $GLOBALS["shariff3UU_basic"]["add_after"]["bbp_reply"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["add_after"]["bbp_reply"], 1, 0 );
414
- echo ' value="1">' . __('bbPress replies', 'shariff3UU') . '</p>';
415
-
416
- // add after all excerpts
417
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_after][excerpt]" ';
418
- if ( isset( $GLOBALS["shariff3UU_basic"]["add_after"]["excerpt"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["add_after"]["excerpt"], 1, 0 );
419
- echo ' value="1">' . __('Excerpt', 'shariff3UU') . '</p>';
420
-
421
- // add after custom post types - choose after which to add
422
- $post_types = get_post_types( array( '_builtin' => FALSE ) );
423
- if ( isset( $post_types ) && is_array( $post_types ) && ! empty( $post_types ) ) {
424
- echo '<p>Custom Post Types:</p>';
425
- };
426
-
427
- foreach ( $post_types as $post_type ) {
428
- $object = get_post_type_object( $post_type );
429
- printf(
430
- '<p><input type="checkbox" name="shariff3UU_basic[add_after][%s]" %s value="1">%s</p>',
431
- $post_type,
432
- isset( $GLOBALS['shariff3UU_basic']['add_after'][$post_type] ) ? checked( $GLOBALS['shariff3UU_basic']['add_after'][$post_type], 1, 0 ) : '',
433
- $object->labels->singular_name // this should already be localized <- not always, but there is no way to know, so we have to accept the language mixup
434
- );
435
- }
436
- }
437
-
438
- // add before
439
- function shariff3UU_multiplecheckbox_add_before_render() {
440
- // Add before all posts
441
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_before][posts]" ';
442
- if ( isset( $GLOBALS['shariff3UU_basic']['add_before']['posts'] ) ) echo checked( $GLOBALS['shariff3UU_basic']['add_before']['posts'], 1, 0 );
443
- echo ' value="1">' . __('Posts', 'shariff3UU') . '</p>';
444
-
445
- // Add before all posts (blog page)
446
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_before][posts_blogpage]" ';
447
- if ( isset( $GLOBALS["shariff3UU_basic"]["add_before"]["posts_blogpage"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["add_before"]["posts_blogpage"], 1, 0 );
448
- echo ' value="1">' . __('Posts (blog page)', 'shariff3UU') . '</p>';
449
-
450
- // Add before all pages
451
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_before][pages]" ';
452
- if ( isset( $GLOBALS["shariff3UU_basic"]["add_before"]["pages"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["add_before"]["pages"], 1, 0 );
453
- echo ' value="1">' . __('Pages', 'shariff3UU') . '</p>';
454
-
455
- // Add before all excerpts
456
- echo '<p><input type="checkbox" name="shariff3UU_basic[add_before][excerpt]" ';
457
- if ( isset( $GLOBALS["shariff3UU_basic"]["add_before"]["excerpt"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["add_before"]["excerpt"], 1, 0 );
458
- echo ' value="1">' . __('Excerpt', 'shariff3UU') . '</p>';
459
- }
460
-
461
- // disable on password protected posts
462
- function shariff3UU_checkbox_disable_on_protected_render() {
463
- echo '<input type="checkbox" name="shariff3UU_basic[disable_on_protected]" ';
464
- if ( isset( $GLOBALS["shariff3UU_basic"]["disable_on_protected"] ) ) echo checked( $GLOBALS["shariff3UU_basic"]["disable_on_protected"], 1, 0 );
465
- echo ' value="1">';
466
- }
467
-
468
- // design options
469
-
470
- // description design options
471
- function shariff3UU_design_section_callback(){
472
- echo __( 'This configures the default design of the Shariff buttons. Most options can be overwritten for single posts or pages with the options within the <code>[shariff]</code> shorttag. For more information have a look at the ', 'shariff3UU');
473
- echo '<a href="' . get_bloginfo('wpurl') . '/wp-admin/options-general.php?page=shariff3uu&tab=help">';
474
- echo __( 'Help Section</a> and the ', 'shariff3UU' );
475
- echo '<a href="https://wordpress.org/support/plugin/shariff/" target="_blank">';
476
- echo __( 'Support Forum</a>.', 'shariff3UU' );
477
- }
478
-
479
- // language
480
- function shariff3UU_select_language_render() {
481
- $options = $GLOBALS["shariff3UU_design"];
482
- if ( ! isset( $options["lang"] ) ) $options["lang"] = '';
483
- echo '<select name="shariff3UU_design[lang]">
484
- <option value="" ' . selected( $options["lang"], "", 0 ) . '>' . __( "auto", "shariff3UU") . '</option>
485
- <option value="en" ' . selected( $options["lang"], "en", 0 ) . '>English</option>
486
- <option value="de" ' . selected( $options["lang"], "de", 0 ) . '>Deutsch</option>
487
- <option value="fr" ' . selected( $options["lang"], "fr", 0 ) . '>Français</option>
488
- <option value="es" ' . selected( $options["lang"], "es", 0 ) . '>Español</option>
489
- <option value="zh" ' . selected( $options["lang"], "zh", 0 ) . '>Chinese</option>
490
- <option value="hr" ' . selected( $options["lang"], "hr", 0 ) . '>Croatian</option>
491
- <option value="da" ' . selected( $options["lang"], "da", 0 ) . '>Danish</option>
492
- <option value="nl" ' . selected( $options["lang"], "nl", 0 ) . '>Dutch</option>
493
- <option value="fi" ' . selected( $options["lang"], "fi", 0 ) . '>Finnish</option>
494
- <option value="it" ' . selected( $options["lang"], "it", 0 ) . '>Italiano</option>
495
- <option value="ja" ' . selected( $options["lang"], "ja", 0 ) . '>Japanese</option>
496
- <option value="ko" ' . selected( $options["lang"], "ko", 0 ) . '>Korean</option>
497
- <option value="no" ' . selected( $options["lang"], "no", 0 ) . '>Norwegian</option>
498
- <option value="pl" ' . selected( $options["lang"], "pl", 0 ) . '>Polish</option>
499
- <option value="pt" ' . selected( $options["lang"], "pt", 0 ) . '>Portuguese</option>
500
- <option value="ro" ' . selected( $options["lang"], "ro", 0 ) . '>Romanian</option>
501
- <option value="ru" ' . selected( $options["lang"], "ru", 0 ) . '>Russian</option>
502
- <option value="sk" ' . selected( $options["lang"], "sk", 0 ) . '>Slovak</option>
503
- <option value="sl" ' . selected( $options["lang"], "sl", 0 ) . '>Slovene</option>
504
- <option value="sr" ' . selected( $options["lang"], "sr", 0 ) . '>Serbian</option>
505
- <option value="sv" ' . selected( $options["lang"], "sv", 0 ) . '>Swedish</option>
506
- <option value="tr" ' . selected( $options["lang"], "tr", 0 ) . '>Turkish</option>
507
- </select>';
508
- }
509
-
510
- // theme
511
- function shariff3UU_radio_theme_render() {
512
- $options = $GLOBALS["shariff3UU_design"];
513
- if ( ! isset( $options["theme"] ) ) $options["theme"] = "";
514
- $plugins_url = plugins_url();
515
- echo '<div class="shariff_options-table">
516
- <div class="shariff_options-row"><div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[theme]" value="" ' . checked( $options["theme"], "", 0 ) . '>default</div><div class="shariff_options-cell"><img src="' . $plugins_url . '/shariff/pictos/defaultBtns.png"></div></div>
517
- <div class="shariff_options-row"><div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[theme]" value="color" ' . checked( $options["theme"], "color", 0 ) . '>color</div><div class="shariff_options-cell"><img src="' . $plugins_url . '/shariff/pictos/colorBtns.png"></div></div>
518
- <div class="shariff_options-row"><div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[theme]" value="grey" ' . checked( $options["theme"], "grey", 0 ) . '>grey</div><div class="shariff_options-cell"><img src="' . $plugins_url . '/shariff/pictos/greyBtns.png"></div></div>
519
- <div class="shariff_options-row"><div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[theme]" value="white" ' . checked( $options["theme"], "white", 0 ) . '>white</div><div class="shariff_options-cell"><img src="' . $plugins_url . '/shariff/pictos/whiteBtns.png"></div></div>
520
- <div class="shariff_options-row"><div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[theme]" value="round" ' . checked( $options["theme"], "round", 0 ) . '>round</div><div class="shariff_options-cell"><img src="' . $plugins_url . '/shariff/pictos/roundBtns.png"></div></div>
521
- </div>';
522
- }
523
-
524
- // button size
525
- function shariff3UU_checkbox_buttonsize_render() {
526
- $plugins_url = plugins_url();
527
- echo '<input type="checkbox" name="shariff3UU_design[buttonsize]" ';
528
- if ( isset( $GLOBALS["shariff3UU_design"]["buttonsize"] ) ) echo checked( $GLOBALS["shariff3UU_design"]["buttonsize"], 1, 0 );
529
- echo ' value="1"><img src="'. $plugins_url .'/shariff/pictos/smallBtns.png" align="middle">';
530
- }
531
-
532
- // button stretch
533
- function shariff3UU_checkbox_buttonstretch_render() {
534
- $plugins_url = plugins_url();
535
- echo '<input type="checkbox" name="shariff3UU_design[buttonstretch]" ';
536
- if ( isset( $GLOBALS["shariff3UU_design"]["buttonstretch"] ) ) echo checked( $GLOBALS["shariff3UU_design"]["buttonstretch"], 1, 0 );
537
- echo ' value="1">';
538
- }
539
-
540
- // vertical
541
- function shariff3UU_checkbox_vertical_render() {
542
- $plugins_url = plugins_url();
543
- echo '<input type="checkbox" name="shariff3UU_design[vertical]" ';
544
- if ( isset( $GLOBALS["shariff3UU_design"]["vertical"] ) ) echo checked( $GLOBALS["shariff3UU_design"]["vertical"], 1, 0 );
545
- echo ' value="1"><img src="'. $plugins_url .'/shariff/pictos/verticalBtns.png" align="top">';
546
- }
547
-
548
- // alignment
549
- function shariff3UU_radio_align_render() {
550
- $options = $GLOBALS['shariff3UU_design'];
551
- if ( ! isset( $options['align'] ) ) $options['align'] = 'flex-start';
552
- echo '<div class="shariff_options-table"><div class="shariff_options-row">
553
- <div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[align]" value="flex-start" ' . checked( $options["align"], "flex-start", 0 ) . '>' . __( "left", "shariff3UU" ) . '</div>
554
- <div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[align]" value="center" ' . checked( $options["align"], "center", 0 ) . '>' . __( "center", "shariff3UU" ) . '</div>
555
- <div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[align]" value="flex-end" ' . checked( $options["align"], "flex-end", 0 ) . '>' . __( "right", "shariff3UU" ) . '</div>
556
- </div></div>';
557
- }
558
-
559
- // alignment widget
560
- function shariff3UU_radio_align_widget_render() {
561
- $options = $GLOBALS['shariff3UU_design'];
562
- if ( ! isset( $options['align_widget'] ) ) $options['align_widget'] = 'flex-start';
563
- echo '<div class="shariff_options-table"><div class="shariff_options-row">
564
- <div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[align_widget]" value="flex-start" ' . checked( $options["align_widget"], "flex-start", 0 ) . '>' . __( "left", "shariff3UU" ) . '</div>
565
- <div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[align_widget]" value="center" ' . checked( $options["align_widget"], "center", 0 ) . '>' . __( "center", "shariff3UU" ) . '</div>
566
- <div class="shariff_options-cell"><input type="radio" name="shariff3UU_design[align_widget]" value="flex-end" ' . checked( $options["align_widget"], "flex-end", 0 ) . '>' . __( "right", "shariff3UU" ) . '</div>
567
- </div></div>';
568
- }
569
-
570
- // headline
571
- function shariff3UU_text_headline_render() {
572
- if ( isset( $GLOBALS["shariff3UU_design"]["headline"] ) ) {
573
- $headline = $GLOBALS["shariff3UU_design"]["headline"];
574
- }
575
- else {
576
- $headline = '';
577
- }
578
- echo '<input type="text" name="shariff3UU_design[headline]" value="' . esc_html( $headline ) . '" size="50" placeholder="' . __( "Share this post", "shariff3UU" ) . '">';
579
- echo __( '<p>Basic HTML as well as style and class attributes are allowed - e.g. <code>&lt;h3 class="shariff_headline"&gt;Share this post&lt;/h3&gt;</code></p>', "shariff3UU" );
580
- }
581
-
582
- // custom css
583
- function shariff3UU_text_style_render() {
584
- if ( isset( $GLOBALS["shariff3UU_design"]["style"] ) ) {
585
- $style = $GLOBALS["shariff3UU_design"]["style"];
586
- }
587
- else {
588
- $style = '';
589
- }
590
- echo '<input type="text" name="shariff3UU_design[style]" value="' . esc_html($style) . '" size="50" placeholder="' . __( "More information in the FAQ.", "shariff3UU" ) . '">';
591
- }
592
-
593
- // advanced options
594
-
595
- // description advanced options
596
- function shariff3UU_advanced_section_callback(){
597
- echo __( 'This configures the advanced options of Shariff regarding specific services. If you are unsure about an option, take a look at the ', 'shariff3UU' );
598
- echo '<a href="' . get_bloginfo('wpurl') . '/wp-admin/options-general.php?page=shariff3uu&tab=help">';
599
- echo __( 'Help Section</a> and the ', 'shariff3UU' );
600
- echo '<a href="https://wordpress.org/support/plugin/shariff/" target="_blank">';
601
- echo __( 'Support Forum</a>.', 'shariff3UU' );
602
- }
603
-
604
- // info url
605
- function shariff3UU_text_info_url_render() {
606
- if ( isset( $GLOBALS["shariff3UU_advanced"]["info_url"] ) ) {
607
- $info_url = $GLOBALS["shariff3UU_advanced"]["info_url"];
608
- }
609
- else {
610
- $info_url = '';
611
- }
612
- echo '<input type="text" name="shariff3UU_advanced[info_url]" value="'. esc_html($info_url) .'" size="50" placeholder="http://ct.de/-2467514">';
613
- }
614
-
615
- // twitter via
616
- function shariff3UU_text_twittervia_render() {
617
- if ( isset( $GLOBALS["shariff3UU_advanced"]["twitter_via"] ) ) {
618
- $twitter_via = $GLOBALS["shariff3UU_advanced"]["twitter_via"];
619
- }
620
- else {
621
- $twitter_via = '';
622
- }
623
- echo '<input type="text" name="shariff3UU_advanced[twitter_via]" value="' . $twitter_via . '" size="50" placeholder="' . __( 'username', 'shariff3UU' ) . '">';
624
- }
625
-
626
- // flattr username
627
- function shariff3UU_text_flattruser_render() {
628
- if ( isset($GLOBALS["shariff3UU_advanced"]["flattruser"]) ) {
629
- $flattruser = $GLOBALS["shariff3UU_advanced"]["flattruser"];
630
- }
631
- else {
632
- $flattruser = '';
633
- }
634
- echo '<input type="text" name="shariff3UU_advanced[flattruser]" value="'. $flattruser .'" size="50" placeholder="' . __( 'username', 'shariff3UU' ) . '">';
635
- }
636
-
637
- // patreon username
638
- function shariff3UU_text_patreonid_render() {
639
- if ( isset($GLOBALS["shariff3UU_advanced"]["patreonid"]) ) {
640
- $patreonid = $GLOBALS["shariff3UU_advanced"]["patreonid"];
641
- }
642
- else {
643
- $patreonid = '';
644
- }
645
- echo '<input type="text" name="shariff3UU_advanced[patreonid]" value="'. $patreonid .'" size="50" placeholder="' . __( 'username', 'shariff3UU' ) . '">';
646
- }
647
-
648
- // paypal button id
649
- function shariff3UU_text_paypalbuttonid_render() {
650
- if ( isset($GLOBALS["shariff3UU_advanced"]["paypalbuttonid"]) ) {
651
- $paypalbuttonid = $GLOBALS["shariff3UU_advanced"]["paypalbuttonid"];
652
- }
653
- else {
654
- $paypalbuttonid = '';
655
- }
656
- echo '<input type="text" name="shariff3UU_advanced[paypalbuttonid]" value="'. $paypalbuttonid .'" size="50" placeholder="' . __( '1ABCDEF23GH4I', 'shariff3UU' ) . '">';
657
- }
658
-
659
- // paypalme id
660
- function shariff3UU_text_paypalmeid_render() {
661
- if ( isset($GLOBALS["shariff3UU_advanced"]["paypalmeid"]) ) {
662
- $paypalmeid = $GLOBALS["shariff3UU_advanced"]["paypalmeid"];
663
- }
664
- else {
665
- $paypalmeid = '';
666
- }
667
- echo '<input type="text" name="shariff3UU_advanced[paypalmeid]" value="'. $paypalmeid .'" size="50" placeholder="' . __( 'name', 'shariff3UU' ) . '">';
668
- }
669
-
670
- // bitcoin address
671
- function shariff3UU_text_bitcoinaddress_render() {
672
- if ( isset($GLOBALS["shariff3UU_advanced"]["bitcoinaddress"]) ) {
673
- $bitcoinaddress = $GLOBALS["shariff3UU_advanced"]["bitcoinaddress"];
674
- }
675
- else {
676
- $bitcoinaddress = '';
677
- }
678
- echo '<input type="text" name="shariff3UU_advanced[bitcoinaddress]" value="'. $bitcoinaddress .'" size="50" placeholder="' . __( '1Ab2CdEfGhijKL34mnoPQRSTu5VwXYzaBcD', 'shariff3UU' ) . '">';
679
- }
680
-
681
- // rss feed
682
- function shariff3UU_text_rssfeed_render() {
683
- if ( isset($GLOBALS["shariff3UU_advanced"]["rssfeed"]) ) {
684
- $rssfeed = esc_url( $GLOBALS["shariff3UU_advanced"]["rssfeed"] );
685
- }
686
- else {
687
- $rssfeed = '';
688
- }
689
- $rssdefault = esc_url( get_bloginfo('rss_url') );
690
- echo '<input type="text" name="shariff3UU_advanced[rssfeed]" value="'. $rssfeed .'" size="50" placeholder="' . $rssdefault . '">';
691
- }
692
-
693
- // pinterest default image
694
- function shariff3UU_text_default_pinterest_render() {
695
- $options = $GLOBALS["shariff3UU_advanced"];
696
- if ( ! isset( $options["default_pinterest"] ) ) $options["default_pinterest"] = '';
697
- echo '<div><input type="text" name="shariff3UU_advanced[default_pinterest]" value="' . $options["default_pinterest"] . '" id="image_url" class="regular-text"><input type="button" name="upload-btn" id="upload-btn" class="button-secondary" value="' . __( 'Choose image', 'shariff3UU' ) . '"></div>';
698
- echo '<script type="text/javascript">
699
- jQuery(document).ready(function($){
700
- $("#upload-btn").click(function(e) {
701
- e.preventDefault();
702
- var image = wp.media({
703
- title: "Choose image",
704
- // mutiple: true if you want to upload multiple files at once
705
- multiple: false
706
- }).open()
707
- .on("select", function(e){
708
- // This will return the selected image from the Media Uploader, the result is an object
709
- var uploaded_image = image.state().get("selection").first();
710
- // We convert uploaded_image to a JSON object to make accessing it easier
711
- // Output to the console uploaded_image
712
- console.log(uploaded_image);
713
- var image_url = uploaded_image.toJSON().url;
714
- // Let"s assign the url value to the input field
715
- $("#image_url").val(image_url);
716
- });
717
- });
718
- });
719
- </script>';
720
- }
721
-
722
- // mailform options
723
-
724
- // description mailform options
725
- function shariff3UU_mailform_section_callback() {
726
- echo __( "The mail form can be completely disabled, if not needed. Otherwise, it is recommended to configure a default sender e-mail address from <u>your domain</u> that actually exists, to prevent spam filters from blocking the e-mails.", "shariff3UU" );
727
- }
728
-
729
- // disable mailform
730
- function shariff3UU_checkbox_disable_mailform_render() {
731
- echo '<input type="checkbox" name="shariff3UU_mailform[disable_mailform]" ';
732
- if ( isset( $GLOBALS["shariff3UU_mailform"]["disable_mailform"] ) ) echo checked( $GLOBALS["shariff3UU_mailform"]["disable_mailform"], 1, 0 );
733
- echo ' value="1">';
734
- }
735
-
736
- // require sender e-mail address
737
- function shariff3UU_checkbox_require_sender_render() {
738
- echo '<input type="checkbox" name="shariff3UU_mailform[require_sender]" ';
739
- if ( isset( $GLOBALS["shariff3UU_mailform"]["require_sender"] ) ) echo checked( $GLOBALS["shariff3UU_mailform"]["require_sender"], 1, 0 );
740
- echo ' value="1">';
741
- }
742
-
743
- // mailform language
744
- function shariff3UU_select_mailform_language_render() {
745
- $options = $GLOBALS["shariff3UU_mailform"];
746
- if ( ! isset( $options["mailform_language"] ) ) $options["mailform_language"] = 'auto';
747
- echo '<select name="shariff3UU_mailform[mailform_language]" style="min-width:110px">
748
- <option value="auto" ' . selected( $options["mailform_language"], "auto", 0 ) . '>' . __( "auto", "shariff3UU") . '</option>
749
- <option value="EN" ' . selected( $options["mailform_language"], "EN", 0 ) . '>English</option>
750
- <option value="DE" ' . selected( $options["mailform_language"], "DE", 0 ) . '>Deutsch</option>
751
- <option value="FR" ' . selected( $options["mailform_language"], "FR", 0 ) . '>Français</option>
752
- <option value="IT" ' . selected( $options["mailform_language"], "IT", 0 ) . '>Italiano</option>';
753
- }
754
-
755
- // add post content
756
- function shariff3UU_checkbox_mail_add_post_content_render() {
757
- echo '<input type="checkbox" name="shariff3UU_mailform[mail_add_post_content]" ';
758
- if ( isset( $GLOBALS["shariff3UU_mailform"]["mail_add_post_content"] ) ) echo checked( $GLOBALS["shariff3UU_mailform"]["mail_add_post_content"], 1, 0 );
759
- echo ' value="1">';
760
- }
761
-
762
- // sender name
763
- function shariff3UU_text_mail_sender_name_render() {
764
- if ( isset( $GLOBALS["shariff3UU_mailform"]["mail_sender_name"] ) ) {
765
- $mail_sender_name = $GLOBALS["shariff3UU_mailform"]["mail_sender_name"];
766
- }
767
- else {
768
- $mail_sender_name = "";
769
- }
770
- // get blog title
771
- $blog_title = get_bloginfo( 'name' );
772
- echo '<input type="text" name="shariff3UU_mailform[mail_sender_name]" value="' . esc_html($mail_sender_name) . '" size="50" placeholder="' . $blog_title . '">';
773
- }
774
-
775
- // sender address
776
- function shariff3UU_text_mail_sender_from_render() {
777
- if ( isset( $GLOBALS["shariff3UU_mailform"]["mail_sender_from"] ) ) {
778
- $mail_sender_from = $GLOBALS["shariff3UU_mailform"]["mail_sender_from"];
779
- }
780
- else {
781
- $mail_sender_from = "";
782
- }
783
- // get blog domain
784
- $blog_domain = get_bloginfo( 'url');
785
- // in case scheme relative URI is passed, e.g., //www.google.com/
786
- $input = trim($blog_domain, '/');
787
- // If scheme not included, prepend it
788
- if ( ! preg_match( '#^http(s)?://#', $input ) ) {
789
- $input = 'http://' . $input;
790
- }
791
- $urlParts = parse_url($input);
792
- // remove www
793
- $domain = preg_replace('/^www\./', '', $urlParts['host']);
794
- echo '<input type="email" name="shariff3UU_mailform[mail_sender_from]" value="' . esc_html($mail_sender_from) . '" size="50" placeholder="wordpress@' . $domain .'">';
795
- }
796
-
797
- // statistic section
798
-
799
- // description statistic options
800
- function shariff3UU_statistic_section_callback(){
801
- echo __( 'This determines how share counts are handled by Shariff.', 'shariff3UU' );
802
- if ( isset( $GLOBALS["shariff3UU_statistic"]["external_host"] ) ) {
803
- echo __( ' <span style="color: red; font-weight: bold;">Warning:</span> You entered an external host! Therefore most options on this page have no effect. You need to configure them on the external server. Remember: This feature is still experimental!', 'shariff3UU' );
804
- }
805
- }
806
-
807
- // share counts
808
- function shariff3UU_checkbox_backend_render() {
809
- // to check that the backend works
810
- // http://[your_host]/wp-content/plugins/shariff/backend/index.php?url=http%3A%2F%2F[your_host]
811
- // should give an array or "[ ]"
812
-
813
- // check PHP version
814
- if ( version_compare( PHP_VERSION, '5.4.0' ) < 1 ) {
815
- echo __( 'PHP-Version 5.4 or better is needed to enable the statistic functionality.', 'shariff3UU');
816
- }
817
- else {
818
- echo '<input type="checkbox" name="shariff3UU_statistic[backend]" ';
819
- if ( isset( $GLOBALS['shariff3UU_statistic']['backend'] ) ) {
820
- echo checked( $GLOBALS['shariff3UU_statistic']['backend'], 1, 0 );
821
- }
822
- echo ' value="1">';
823
- }
824
- }
825
-
826
- // Facebook App ID
827
- function shariff3UU_text_fb_id_render() {
828
- if ( isset($GLOBALS["shariff3UU_statistic"]["fb_id"]) ) {
829
- $fb_id = $GLOBALS["shariff3UU_statistic"]["fb_id"];
830
- }
831
- else {
832
- $fb_id = '';
833
- }
834
- echo '<input type="text" name="shariff3UU_statistic[fb_id]" value="'. $fb_id .'" size="50" placeholder="1234567891234567">';
835
- }
836
-
837
- // Facebook App Secret
838
- function shariff3UU_text_fb_secret_render() {
839
- if ( isset($GLOBALS["shariff3UU_statistic"]["fb_secret"]) ) {
840
- $fb_secret = $GLOBALS["shariff3UU_statistic"]["fb_secret"];
841
- }
842
- else {
843
- $fb_secret = '';
844
- }
845
- echo '<input type="text" name="shariff3UU_statistic[fb_secret]" value="'. $fb_secret .'" size="50" placeholder="123abc456def789123456789ghi12345">';
846
- }
847
-
848
- // ttl
849
- function shariff3UU_number_ttl_render() {
850
- if ( isset($GLOBALS["shariff3UU_statistic"]["ttl"]) ) {
851
- $ttl = $GLOBALS["shariff3UU_statistic"]["ttl"];
852
- }
853
- else {
854
- $ttl = '';
855
- }
856
- echo '<input type="number" name="shariff3UU_statistic[ttl]" value="'. $ttl .'" maxlength="4" min="60" max="7200" placeholder="60" style="width: 75px">';
857
- }
858
-
859
- // disable services
860
- function shariff3UU_multiplecheckbox_disable_services_render() {
861
- // Facebook
862
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][facebook]" ';
863
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['facebook'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['facebook'], 1, 0 );
864
- echo ' value="1">' . __('Facebook', 'shariff3UU') . '</p>';
865
-
866
- // Twitter
867
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][twitter]" ';
868
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['twitter'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['twitter'], 1, 0 );
869
- echo ' value="1">' . __('OpenShareCount (Twitter)', 'shariff3UU') . '</p>';
870
-
871
- // GooglePlus
872
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][googleplus]" ';
873
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['googleplus'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['googleplus'], 1, 0 );
874
- echo ' value="1">' . __('GooglePlus', 'shariff3UU') . '</p>';
875
-
876
- // Pinterest
877
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][pinterest]" ';
878
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['pinterest'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['pinterest'], 1, 0 );
879
- echo ' value="1">' . __('Pinterest', 'shariff3UU') . '</p>';
880
-
881
- // Xing
882
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][xing]" ';
883
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['xing'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['xing'], 1, 0 );
884
- echo ' value="1">' . __('Xing', 'shariff3UU') . '</p>';
885
-
886
- // LinkedIn
887
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][linkedin]" ';
888
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['linkedin'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['linkedin'], 1, 0 );
889
- echo ' value="1">' . __('LinkedIn', 'shariff3UU') . '</p>';
890
-
891
- // Tumblr
892
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][tumblr]" ';
893
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['tumblr'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['tumblr'], 1, 0 );
894
- echo ' value="1">' . __('Tumblr', 'shariff3UU') . '</p>';
895
-
896
- // VK
897
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][vk]" ';
898
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['vk'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['vk'], 1, 0 );
899
- echo ' value="1">' . __('VK', 'shariff3UU') . '</p>';
900
-
901
- // StumbleUpon
902
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][stumbleupon]" ';
903
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['stumbleupon'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['stumbleupon'], 1, 0 );
904
- echo ' value="1">' . __('StumbleUpon', 'shariff3UU') . '</p>';
905
-
906
- // Reddit
907
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][reddit]" ';
908
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['reddit'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['reddit'], 1, 0 );
909
- echo ' value="1">' . __('Reddit', 'shariff3UU') . '</p>';
910
-
911
- // AddThis
912
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][addthis]" ';
913
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['addthis'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['addthis'], 1, 0 );
914
- echo ' value="1">' . __('AddThis', 'shariff3UU') . '</p>';
915
-
916
- // Flattr
917
- echo '<p><input type="checkbox" name="shariff3UU_statistic[disable][flattr]" ';
918
- if ( isset( $GLOBALS['shariff3UU_statistic']['disable']['flattr'] ) ) echo checked( $GLOBALS['shariff3UU_statistic']['disable']['flattr'], 1, 0 );
919
- echo ' value="1">' . __('Flattr', 'shariff3UU') . '</p>';
920
- }
921
-
922
- // external host
923
- function shariff3UU_text_external_host_render(){
924
- if ( isset( $GLOBALS["shariff3UU_statistic"]["external_host"] ) ) {
925
- $external_host = $GLOBALS["shariff3UU_statistic"]["external_host"];
926
- }
927
- else {
928
- $external_host = '';
929
- }
930
- echo '<input type="text" name="shariff3UU_statistic[external_host]" value="' . esc_html( $external_host ) . '" size="50" placeholder="'. plugins_url() .'/shariff/">';
931
- echo '<p>' . __( 'Warning: This is an <strong>experimental</strong> feature. Please read the <a href="https://wordpress.org/plugins/shariff/faq/" target="_blank">Frequently Asked Questions (FAQ)</a>.', 'shariff3UU' ) . '</p>';
932
- echo '<p>' . __( 'Please check, if you have to add this domain to the array $SHARIFF_FRONTENDS on the external server.', 'shariff3UU' ) . '</p>';
933
- }
934
-
935
- // help section
936
-
937
- // description advanced options
938
- function shariff3UU_help_section_callback() {
939
- echo __( '<p>The WordPress plugin "Shariff Wrapper" has been developed by <a href="http://www.datenverwurstungszentrale.com" target="_blank">3UU</a> and <a href="https://www.jplambeck.de" target=_blank">JP</a> in order to help protect the privacy of your visitors. It is based on the original Shariff buttons developed by the German computer magazin <a href="http://ct.de/shariff" target="_blank">c\'t</a> that fullfill the strict data protection laws in Germany. If you need any help with the plugin, take a look at the <a href="https://wordpress.org/plugins/shariff/faq/" target="_blank">Frequently Asked Questions (FAQ)</a> and the <a href="https://wordpress.org/support/plugin/shariff" target="_blank">Support Forum</a>. For up to date news about the plugin you can also follow <a href="https://twitter.com/jplambeck" target=_blank">@jplambeck</a> on Twitter.</p>', 'shariff3UU' );
940
- echo __( '<p>If you contact us about a problem with the share counts, please <u>always</u> include the information provided in the', 'shariff3UU' );
941
- echo ' <a href="options-general.php?page=shariff3uu&tab=basic">';
942
- echo __( 'status section</a>! This will help to speed up the process.</p>', 'shariff3UU' );
943
- echo '<p>' . __( 'If you enjoy our plugin, please consider writing a review about it on ', 'shariff3UU' );
944
- echo '<a href="https://wordpress.org/support/view/plugin-reviews/shariff" target="_blank">wordpress.org</a>';
945
- echo __( '. If you want to support us financially, you can donate via ', 'shariff3UU' );
946
- echo '<a href="http://folge.link/?bitcoin=1Ritz1iUaLaxuYcXhUCoFhkVRH6GWiMTP" target="_blank">Bitcoin</a> ';
947
- echo __( 'and', 'shariff3UU' );
948
- echo ' <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5BASYVM96PZ3L" target="_blanK">PayPal</a>';
949
- echo __( '. Thank you!', 'shariff3UU' );
950
- echo '</p>';
951
-
952
- echo __( '<p>This is a list of all available options for the <code>[shariff]</code> shortcode:</p>', 'shariff3UU' );
953
- // shortcode table
954
- echo '<div class="shariff_shortcode_table">';
955
- // head
956
- echo '<div class="shariff_shortcode_row_head">';
957
- echo '<div class="shariff_shortcode_cell_name-option">' . __( 'Name', 'shariff3UU' ) . '</div>';
958
- echo '<div class="shariff_shortcode_cell_name-option">' . __( 'Options', 'shariff3UU' ) . '</div>';
959
- echo '<div class="shariff_shortcode_cell_default">' . __( 'Default', 'shariff3UU' ) . '</div>';
960
- echo '<div class="shariff_shortcode_cell_example">' . __( 'Example', 'shariff3UU' ) . '</div>';
961
- echo '<div class="shariff_shortcode_cell_description">' . __( 'Description', 'shariff3UU' ) . '</div>';
962
- echo '</div>';
963
- // services
964
- echo '<div class="shariff_shortcode_row">';
965
- echo '<div class="shariff_shortcode_cell">services</div>';
966
- echo '<div class="shariff_shortcode_cell">facebook<br>twitter<br>googleplus<br>whatsapp<br>threema<br>pinterest<br>linkedin<br>xing<br>reddit<br>stumbleupon<br>tumblr<br>vk<br>diaspora<br>addthis<br>flattr<br>patreon<br>paypal<br>paypalme<br>bitcoin<br>mailform<br>mailto<br>printer<br>info<br>rss</div>';
967
- echo '<div class="shariff_shortcode_cell">twitter|facebook|googleplus|info</div>';
968
- echo '<div class="shariff_shortcode_cell">[shariff services="facebook|twitter|mailform"]</div>';
969
- echo '<div class="shariff_shortcode_cell">' . __( 'Determines which buttons to show and in which order.', 'shariff3UU' ) . '</div>';
970
- echo '</div>';
971
- // backend
972
- echo '<div class="shariff_shortcode_row">';
973
- echo '<div class="shariff_shortcode_cell">backend</div>';
974
- echo '<div class="shariff_shortcode_cell">on<br>off</div>';
975
- echo '<div class="shariff_shortcode_cell">off</div>';
976
- echo '<div class="shariff_shortcode_cell">[shariff backend="on"]</div>';
977
- echo '<div class="shariff_shortcode_cell">' . __( 'Enables share counts on the buttons.', 'shariff3UU' ) . '</div>';
978
- echo '</div>';
979
- // theme
980
- echo '<div class="shariff_shortcode_row">';
981
- echo '<div class="shariff_shortcode_cell">theme</div>';
982
- echo '<div class="shariff_shortcode_cell">default<br>color<br>grey<br>white<br>round</div>';
983
- echo '<div class="shariff_shortcode_cell">default</div>';
984
- echo '<div class="shariff_shortcode_cell">[shariff theme="round"]</div>';
985
- echo '<div class="shariff_shortcode_cell">' . __( 'Determines the main design of the buttons.', 'shariff3UU' ) . '</div>';
986
- echo '</div>';
987
- // button size
988
- echo '<div class="shariff_shortcode_row">';
989
- echo '<div class="shariff_shortcode_cell">buttonsize</div>';
990
- echo '<div class="shariff_shortcode_cell">big<br>small</div>';
991
- echo '<div class="shariff_shortcode_cell">big</div>';
992
- echo '<div class="shariff_shortcode_cell">[shariff buttonsize="small"]</div>';
993
- echo '<div class="shariff_shortcode_cell">' . __( 'Small reduces the size of all buttons by 30%, regardless of theme.', 'shariff3UU' ) . '</div>';
994
- echo '</div>';
995
- // orientation
996
- echo '<div class="shariff_shortcode_row">';
997
- echo '<div class="shariff_shortcode_cell">orientation</div>';
998
- echo '<div class="shariff_shortcode_cell">horizontal<br>vertical</div>';
999
- echo '<div class="shariff_shortcode_cell">horizontal</div>';
1000
- echo '<div class="shariff_shortcode_cell">[shariff orientation="vertical"]</div>';
1001
- echo '<div class="shariff_shortcode_cell">' . __( 'Changes the orientation of the buttons.', 'shariff3UU' ) . '</div>';
1002
- echo '</div>';
1003
- // language
1004
- echo '<div class="shariff_shortcode_row">';
1005
- echo '<div class="shariff_shortcode_cell">language</div>';
1006
- echo '<div class="shariff_shortcode_cell">da, de, en, es, fi, fr, hr, hu, it, ja, ko, nl, no, pl, pt, ro, ru, sk, sl, sr, sv, tr, zh</div>';
1007
- echo '<div class="shariff_shortcode_cell">automatically selected by the browser</div>';
1008
- echo '<div class="shariff_shortcode_cell">[shariff lang="de"]</div>';
1009
- echo '<div class="shariff_shortcode_cell">' . __( 'Changes the language of the share buttons.', 'shariff3UU' ) . '</div>';
1010
- echo '</div>';
1011
- // headline
1012
- echo '<div class="shariff_shortcode_row">';
1013
- echo '<div class="shariff_shortcode_cell">headline</div>';
1014
- echo '<div class="shariff_shortcode_cell"></div>';
1015
- echo '<div class="shariff_shortcode_cell"></div>';
1016
- echo '<div class="shariff_shortcode_cell">[shariff headline="&lt;hr style=\'margin:20px 0\'&gt;&lt;p&gt;' . __( 'Please share this post:', 'shariff3UU' ) . '&lt;/p&gt;"]</div>';
1017
- echo '<div class="shariff_shortcode_cell">' . __( 'Adds a headline above the Shariff buttons. Basic HTML as well as style and class attributes can be used. To remove a headline set on the plugins options page use headline="".', 'shariff3UU' ) . '</div>';
1018
- echo '</div>';
1019
- // twitter_via
1020
- echo '<div class="shariff_shortcode_row">';
1021
- echo '<div class="shariff_shortcode_cell">twitter_via</div>';
1022
- echo '<div class="shariff_shortcode_cell"></div>';
1023
- echo '<div class="shariff_shortcode_cell"></div>';
1024
- echo '<div class="shariff_shortcode_cell">[shariff twitter_via="your_twittername"]</div>';
1025
- echo '<div class="shariff_shortcode_cell">' . __( 'Sets the Twitter via tag.', 'shariff3UU' ) . '</div>';
1026
- echo '</div>';
1027
- // flattruser
1028
- echo '<div class="shariff_shortcode_row">';
1029
- echo '<div class="shariff_shortcode_cell">flattruser</div>';
1030
- echo '<div class="shariff_shortcode_cell"></div>';
1031
- echo '<div class="shariff_shortcode_cell"></div>';
1032
- echo '<div class="shariff_shortcode_cell">[shariff flattruser="your_username"]</div>';
1033
- echo '<div class="shariff_shortcode_cell">' . __( 'Sets the Flattr username.', 'shariff3UU' ) . '</div>';
1034
- echo '</div>';
1035
- // patreonid
1036
- echo '<div class="shariff_shortcode_row">';
1037
- echo '<div class="shariff_shortcode_cell">patreonid</div>';
1038
- echo '<div class="shariff_shortcode_cell"></div>';
1039
- echo '<div class="shariff_shortcode_cell"></div>';
1040
- echo '<div class="shariff_shortcode_cell">[shariff patreonid="your_username"]</div>';
1041
- echo '<div class="shariff_shortcode_cell">' . __( 'Sets the Patreon username.', 'shariff3UU' ) . '</div>';
1042
- echo '</div>';
1043
- // paypalbuttonid
1044
- echo '<div class="shariff_shortcode_row">';
1045
- echo '<div class="shariff_shortcode_cell">paypalbuttonid</div>';
1046
- echo '<div class="shariff_shortcode_cell"></div>';
1047
- echo '<div class="shariff_shortcode_cell"></div>';
1048
- echo '<div class="shariff_shortcode_cell">[shariff paypalbuttonid="hosted_button_id"]</div>';
1049
- echo '<div class="shariff_shortcode_cell">' . __( 'Sets the PayPal hosted button ID.', 'shariff3UU' ) . '</div>';
1050
- echo '</div>';
1051
- // paypalmeid
1052
- echo '<div class="shariff_shortcode_row">';
1053
- echo '<div class="shariff_shortcode_cell">paypalmeid</div>';
1054
- echo '<div class="shariff_shortcode_cell"></div>';
1055
- echo '<div class="shariff_shortcode_cell"></div>';
1056
- echo '<div class="shariff_shortcode_cell">[shariff paypalmeid="name"]</div>';
1057
- echo '<div class="shariff_shortcode_cell">' . __( 'Sets the PayPal.Me ID. Default amount can be added with a / e.g. name/25.', 'shariff3UU' ) . '</div>';
1058
- echo '</div>';
1059
- // bitcoinaddress
1060
- echo '<div class="shariff_shortcode_row">';
1061
- echo '<div class="shariff_shortcode_cell">bitcoinaddress</div>';
1062
- echo '<div class="shariff_shortcode_cell"></div>';
1063
- echo '<div class="shariff_shortcode_cell"></div>';
1064
- echo '<div class="shariff_shortcode_cell">[shariff bitcoinaddress="bitcoin_address"]</div>';
1065
- echo '<div class="shariff_shortcode_cell">' . __( 'Sets the bitcoin address.', 'shariff3UU' ) . '</div>';
1066
- echo '</div>';
1067
- // media
1068
- echo '<div class="shariff_shortcode_row">';
1069
- echo '<div class="shariff_shortcode_cell">media</div>';
1070
- echo '<div class="shariff_shortcode_cell"></div>';
1071
- echo '<div class="shariff_shortcode_cell">' . __( 'The post featured image or the first image of the post.</div>', 'shariff3UU' );
1072
- echo '<div class="shariff_shortcode_cell">[shariff media="http://www.mydomain.com/image.jpg"]</div>';
1073
- echo '<div class="shariff_shortcode_cell">' . __( 'Determines the default image to share for Pinterest, if no other usable image is found.', 'shariff3UU' ) . '</div>';
1074
- echo '</div>';
1075
- // info_url
1076
- echo '<div class="shariff_shortcode_row">';
1077
- echo '<div class="shariff_shortcode_cell">info_url</div>';
1078
- echo '<div class="shariff_shortcode_cell"></div>';
1079
- echo '<div class="shariff_shortcode_cell">http://ct.de/-2467514</div>';
1080
- echo '<div class="shariff_shortcode_cell">[shariff info_url="http://www.mydomain.com/shariff-buttons"]</div>';
1081
- echo '<div class="shariff_shortcode_cell">' . __( 'Sets a custom link for the info button.', 'shariff3UU' ) . '</div>';
1082
- echo '</div>';
1083
- // url
1084
- echo '<div class="shariff_shortcode_row">';
1085
- echo '<div class="shariff_shortcode_cell">url</div>';
1086
- echo '<div class="shariff_shortcode_cell"></div>';
1087
- echo '<div class="shariff_shortcode_cell">' . __( 'The url of the current post or page.</div>', 'shariff3UU' );
1088
- echo '<div class="shariff_shortcode_cell">[shariff url="http://www.mydomain.com/somepost"]</div>';
1089
- echo '<div class="shariff_shortcode_cell">' . __( 'Changes the url to share. Only for special use cases.', 'shariff3UU' ) . '</div>';
1090
- echo '</div>';
1091
- // title
1092
- echo '<div class="shariff_shortcode_row">';
1093
- echo '<div class="shariff_shortcode_cell">title</div>';
1094
- echo '<div class="shariff_shortcode_cell"></div>';
1095
- echo '<div class="shariff_shortcode_cell">' . __( 'The title of the current post or page.</div>', 'shariff3UU' );
1096
- echo '<div class="shariff_shortcode_cell">' . __( '[shariff title="My Post Title"]</div>', 'shariff3UU' );
1097
- echo '<div class="shariff_shortcode_cell">' . __( 'Changes the title to share. Only for special use cases.', 'shariff3UU' ) . '</div>';
1098
- echo '</div>';
1099
- // rssfeed
1100
- echo '<div class="shariff_shortcode_row">';
1101
- echo '<div class="shariff_shortcode_cell">rssfeed</div>';
1102
- echo '<div class="shariff_shortcode_cell"></div>';
1103
- echo '<div class="shariff_shortcode_cell">' . __( 'http://www.mydomain.com/feed/rss/</div>', 'shariff3UU' );
1104
- echo '<div class="shariff_shortcode_cell">[shariff rssfeed="http://www.mydomain.com/feed/rss2/"]</div>';
1105
- echo '<div class="shariff_shortcode_cell">' . __( 'Changes the rss feed url to another feed.', 'shariff3UU' ) . '</div>';
1106
- echo '</div>';
1107
-
1108
- echo '</div>';
1109
- }
1110
-
1111
- // status section
1112
-
1113
- // check services
1114
- function shariff3UU_status_section_callback() {
1115
- // options
1116
- $shariff3UU_statistic = $GLOBALS["shariff3UU_statistic"];
1117
- // status table
1118
- echo '<div class="shariff_status-main-table">';
1119
- // statistic row
1120
- echo '<div class="shariff_status-row">';
1121
- echo '<div class="shariff_status-first-cell">' . __( 'Statistic:', 'shariff3UU' ) . '</div>';
1122
- // check if statistic is enabled
1123
- if( ! isset( $shariff3UU_statistic['backend'] ) ) {
1124
- // statistic disabled message
1125
- echo '<div class="shariff_status-table">';
1126
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-disabled">' . __( 'Disabled', 'shariff3UU' ) . '</span></div></div>';
1127
- echo '</div>';
1128
- // end statistic row, if statistic is disabled
1129
- echo '</div>';
1130
- }
1131
- else {
1132
- // check if services produce error messages
1133
- $post_url = urlencode( esc_url( get_bloginfo('url') ) );
1134
- $post_url2 = esc_url( get_bloginfo('url') );
1135
- $backend_services_url = substr( plugin_dir_path( __FILE__ ), 0, -6) . 'backend/services/';
1136
-
1137
- // temporarily removed flattr due to ongoing problems with the flattr api
1138
- $services = array( 'facebook', 'twitter', 'googleplus', 'pinterest', 'linkedin', 'xing', 'reddit', 'stumbleupon', 'tumblr', 'vk', 'addthis' );
1139
-
1140
- // start testing services
1141
- foreach ( $services as $service ) {
1142
- if ( ! isset ( $shariff3UU_statistic["disable"][ $service ] ) || ( isset ( $shariff3UU_statistic["disable"][ $service ] ) && $shariff3UU_statistic["disable"][ $service ] == 0 ) ) {
1143
- include ( $backend_services_url . $service . '.php' );
1144
- if ( ! isset ( $share_counts[ $service ] ) ) {
1145
- $service_errors[ $service ] = $$service;
1146
- }
1147
- }
1148
- }
1149
-
1150
- // status output
1151
- if ( ! isset( $service_errors ) ) {
1152
- // statistic working message
1153
- echo '<div class="shariff_status-cell">';
1154
- // working message table
1155
- echo '<div class="shariff_status-table">';
1156
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-ok">' . __( 'OK', 'shariff3UU' ) . '</span></div></div>';
1157
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'No error messages.', 'shariff3UU' ) . '</div></div>';
1158
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . '</div></div>';
1159
- echo '</div>';
1160
- echo '</div>';
1161
- // end statistic row, if working correctly
1162
- echo '</div>';
1163
- }
1164
- else {
1165
- // statistic error message
1166
- echo '<div style="display: table-cell">';
1167
- // error message table
1168
- echo '<div class="shariff_status-table">';
1169
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-error">' . __( 'Error', 'shariff3UU' ) . '</span></div></div>';
1170
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Backend error.', 'shariff3UU' ) . '</div></div>';
1171
- foreach( $service_errors as $service => $error ) {
1172
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">';
1173
- echo ucfirst( $service ) . '-Error! Message: ' . esc_html( $error );
1174
- echo '</div></div>';
1175
- }
1176
- echo '</div>';
1177
- echo '</div>';
1178
- // end statistic row, if not working correctly
1179
- echo '</div>';
1180
- }
1181
- // Facebook row
1182
- echo '<div class="shariff_status-row">';
1183
- echo '<div class="shariff_status-cell">' . __( 'Facebook:', 'shariff3UU' ) . '</div>';
1184
- // check if Facebook is responding correctly (no rate limits actice, etc.)
1185
- $blog_url = urlencode( esc_url( get_bloginfo('url') ) );
1186
- $facebook = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://graph.facebook.com/fql?q=SELECT%20total_count%20FROM%20link_stat%20WHERE%20url="' . $blog_url . '"' ) ) );
1187
- $facebook = json_decode( $facebook, true );
1188
- if ( isset( $facebook['data']['0']['total_count'] ) ) {
1189
- // Facebook working message
1190
- echo '<div class="shariff_status-cell">';
1191
- // working message table
1192
- echo '<div style="display: table">';
1193
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-ok">' . __( 'OK', 'shariff3UU' ) . '</span></div></div>';
1194
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Current share count for ', 'shariff3UU' ) . urldecode( $blog_url ) . ': ' . absint( $facebook['data']['0']['total_count'] ) . '</div></div>';
1195
- echo '</div>';
1196
- echo '</div>';
1197
- // end Facebook row, if working correctly
1198
- echo '</div>';
1199
- }
1200
- elseif ( isset( $facebook['error']['message'] ) ) {
1201
- // Facebook API error message
1202
- echo '<div class="shariff_status-cell">';
1203
- // error message table
1204
- echo '<div class="shariff_status-table">';
1205
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-error">' . __( 'Error', 'shariff3UU' ) . '</span></div></div>';
1206
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Message:', 'shariff3UU' ) . '</div><div style="display: table-cell">' . esc_html( $facebook['error']['message'] ) . '</div></div>';
1207
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Type:', 'shariff3UU' ) . '</div><div class="shariff_status-cell">' . esc_html( $facebook['error']['type'] ) . '</div></div>';
1208
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Code:', 'shariff3UU' ) . '</div><div class="shariff_status-cell">' . esc_html( $facebook['error']['code'] ) . '</div></div>';
1209
- echo '</div>';
1210
- echo '</div>';
1211
- // end Facebook row, if not working correctly
1212
- echo '</div>';
1213
- }
1214
- // Facebook Graph API ID row
1215
- echo '<div class="shariff_status-row">';
1216
- echo '<div class="shariff_status-cell">' . __( 'Facebook API (ID):', 'shariff3UU' ) . '</div>';
1217
- // credentials provided?
1218
- if ( ! isset( $GLOBALS['shariff3UU_statistic']['fb_id'] ) || ! isset( $GLOBALS['shariff3UU_statistic']['fb_secret'] ) ) {
1219
- // no credentials
1220
- echo '<div class="shariff_status-cell">';
1221
- echo '<div class="shariff_status-table">';
1222
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-disabled">' . __( 'Not configured', 'shariff3UU' ) . '</span></div></div>';
1223
- echo '</div>';
1224
- echo '</div>';
1225
- // end Graph API ID row, if not configured
1226
- echo '</div>';
1227
- }
1228
- else {
1229
- // app_id and secret
1230
- $fb_app_id = $shariff3UU_statistic['fb_id'];
1231
- $fb_app_secret = $shariff3UU_statistic['fb_secret'];
1232
- // check if Facebook Graph API ID is responding correctly (no rate limits actice, credentials ok, etc.)
1233
- $blog_url = urlencode( esc_url( get_bloginfo('url') ) );
1234
- // get fb access token
1235
- $fb_token = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://graph.facebook.com/oauth/access_token?client_id=' . $fb_app_id . '&client_secret=' . $fb_app_secret . '&grant_type=client_credentials' ) ) );
1236
- // use token to get share counts
1237
- $facebookID = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://graph.facebook.com/v2.2/?id=' . $blog_url . '&' . $fb_token ) ) );
1238
- $facebookID = json_decode( $facebookID, true );
1239
- $fb_token = json_decode( $fb_token, true );
1240
- // is it working?
1241
- if ( isset( $facebookID['share']['share_count'] ) ) {
1242
- // Facebook Graph API ID working message
1243
- echo '<div class="shariff_status-cell">';
1244
- // working message table
1245
- echo '<div style="display: table">';
1246
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-ok">' . __( 'OK', 'shariff3UU' ) . '</span></div></div>';
1247
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Current share count for ', 'shariff3UU' ) . urldecode( $blog_url ) . ': ' . absint( $facebookID['share']['share_count'] ) . '</div></div>';
1248
- echo '</div>';
1249
- echo '</div>';
1250
- // end Facebook Graph API ID row, if working correctly
1251
- echo '</div>';
1252
- }
1253
- elseif ( isset( $facebookID['error']['message'] ) ) {
1254
- // Facebook Graph API ID error message
1255
- echo '<div class="shariff_status-cell">';
1256
- // error message table
1257
- echo '<div class="shariff_status-table">';
1258
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-error">' . __( 'Error', 'shariff3UU' ) . '</span></div></div>';
1259
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Message:', 'shariff3UU' ) . '</div><div style="display: table-cell">' . esc_html( $facebookID['error']['message'] ) . '</div></div>';
1260
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Type:', 'shariff3UU' ) . '</div><div class="shariff_status-cell">' . esc_html( $facebookID['error']['type'] ) . '</div></div>';
1261
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Code:', 'shariff3UU' ) . '</div><div class="shariff_status-cell">' . esc_html( $facebookID['error']['code'] ) . '</div></div>';
1262
- echo '</div>';
1263
- echo '</div>';
1264
- // end Facebook Graph API ID row, if not working correctly
1265
- echo '</div>';
1266
- }
1267
- elseif ( isset( $fb_token['error']['message'] ) ) {
1268
- // Facebook Graph API ID auth error message
1269
- echo '<div class="shariff_status-cell">';
1270
- // error message table
1271
- echo '<div class="shariff_status-table">';
1272
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-error">' . __( 'Error', 'shariff3UU' ) . '</span></div></div>';
1273
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Message:', 'shariff3UU' ) . '</div><div style="display: table-cell">' . esc_html( $fb_token['error']['message'] ) . '</div></div>';
1274
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Type:', 'shariff3UU' ) . '</div><div class="shariff_status-cell">' . esc_html( $fb_token['error']['type'] ) . '</div></div>';
1275
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'Code:', 'shariff3UU' ) . '</div><div class="shariff_status-cell">' . esc_html( $fb_token['error']['code'] ) . '</div></div>';
1276
- echo '</div>';
1277
- echo '</div>';
1278
- // end Facebook Graph API ID row, if not working correctly bc of auth error
1279
- echo '</div>';
1280
- }
1281
- }
1282
- }
1283
-
1284
- // GD needed for QR codes of the Bitcoin links
1285
- echo '<div class="shariff_status-row">';
1286
- echo '<div class="shariff_status-cell">' . __( 'GD Library:', 'shariff3UU' ) . '</div>';
1287
- // working message
1288
- if ( function_exists( 'gd_info' ) ) {
1289
- $tmpGDinfo = gd_info();
1290
- echo '<div class="shariff_status-cell">';
1291
- echo '<div style="display: table">';
1292
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-ok">' . __( 'OK', 'shariff3UU' ) . '</span></div></div>';
1293
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">Version: ' . $tmpGDinfo["GD Version"] . '</div></div>';
1294
- echo '</div>';
1295
- echo '</div>';
1296
- }
1297
- else {
1298
- echo '<div class="shariff_status-cell">';
1299
- echo '<div style="display: table">';
1300
- echo '<div class="shariff_status-row"><div class="shariff_status-cell"><span class="shariff_status-error">' . __( 'Error', 'shariff3UU' ) . '</span></div></div>';
1301
- echo '<div class="shariff_status-row"><div class="shariff_status-cell">' . __( 'The GD Library is not installed on this server. This is only needed for the QR codes, if your are using the bitcoin button.', 'shariff3UU' ) . '</div></div>';
1302
- echo '</div>';
1303
- echo '</div>';
1304
- }
1305
- echo '</div>';
1306
-
1307
- // end status table
1308
- echo '</div>';
1309
- }
1310
-
1311
- // render the plugin option page
1312
- function shariff3UU_options_page() {
1313
- // the <div> with the class "wrap" makes sure that admin messages are displayed below the title and not above
1314
- echo '<div class="wrap">';
1315
-
1316
- // title
1317
- echo '<h2>Shariff ' . $GLOBALS["shariff3UU_basic"]["version"] . '</h2>';
1318
-
1319
- // start the form
1320
- echo '<form class="shariff" action="options.php" method="post">';
1321
-
1322
- // hidden version entry, so it will get saved upon updating the options
1323
- echo '<input type="hidden" name="shariff3UU_basic[version]" value="' . $GLOBALS["shariff3UU_basic"]["version"] . '">';
1324
-
1325
- // determine active tab
1326
- if ( isset( $_GET['tab'] ) ) {
1327
- $active_tab = $_GET['tab'];
1328
- }
1329
- else {
1330
- $active_tab = 'basic';
1331
- }
1332
-
1333
- // tabs
1334
- echo '<h2 class="nav-tab-wrapper">';
1335
- // basic
1336
- echo '<a href="?page=shariff3uu&tab=basic" class="nav-tab ';
1337
- if ( $active_tab == 'basic' ) echo 'nav-tab-active';
1338
- echo '">' . __( 'Basic', 'shariff3UU' ) . '</a>';
1339
- // design
1340
- echo '<a href="?page=shariff3uu&tab=design" class="nav-tab ';
1341
- if ( $active_tab == 'design' ) echo 'nav-tab-active';
1342
- echo '">' . __( 'Design', 'shariff3UU' ) . '</a>';
1343
- // advanced
1344
- echo '<a href="?page=shariff3uu&tab=advanced" class="nav-tab ';
1345
- if ( $active_tab == 'advanced' ) echo 'nav-tab-active';
1346
- echo '">' . __( 'Advanced', 'shariff3UU' ) . '</a>';
1347
- // mailform
1348
- echo '<a href="?page=shariff3uu&tab=mailform" class="nav-tab ';
1349
- if ( $active_tab == 'mailform' ) echo 'nav-tab-active';
1350
- echo '">' . __( 'Mail Form', 'shariff3UU' ) . '</a>';
1351
- // statistic
1352
- echo '<a href="?page=shariff3uu&tab=statistic" class="nav-tab ';
1353
- if ( $active_tab == 'statistic' ) echo 'nav-tab-active';
1354
- echo '">' . __( 'Statistic', 'shariff3UU' ) . '</a>';
1355
- // help
1356
- echo '<a href="?page=shariff3uu&tab=help" class="nav-tab ';
1357
- if ( $active_tab == 'help' ) echo 'nav-tab-active';
1358
- echo '">' . __( 'Help', 'shariff3UU' ) . '</a>';
1359
- // status
1360
- echo '<a href="?page=shariff3uu&tab=status" class="nav-tab ';
1361
- if ( $active_tab == 'status' ) echo 'nav-tab-active';
1362
- echo '">' . __( 'Status', 'shariff3UU' ) . '</a>';
1363
- echo '</h2>';
1364
-
1365
- // content of tabs
1366
- if ( $active_tab == 'basic' ) {
1367
- settings_fields( 'basic' );
1368
- do_settings_sections( 'basic' );
1369
- submit_button();
1370
- }
1371
- elseif ( $active_tab == 'design' ) {
1372
- settings_fields( 'design' );
1373
- do_settings_sections( 'design' );
1374
- submit_button();
1375
- }
1376
- elseif ( $active_tab == 'advanced' ) {
1377
- settings_fields( 'advanced' );
1378
- do_settings_sections( 'advanced' );
1379
- submit_button();
1380
- }
1381
- elseif ( $active_tab == 'mailform' ) {
1382
- settings_fields( 'mailform' );
1383
- do_settings_sections( 'mailform' );
1384
- submit_button();
1385
- }
1386
- elseif ( $active_tab == 'statistic' ) {
1387
- settings_fields( 'statistic' );
1388
- do_settings_sections( 'statistic' );
1389
- submit_button();
1390
- }
1391
- elseif ( $active_tab == 'help' ) {
1392
- settings_fields( 'help' );
1393
- do_settings_sections( 'help' );
1394
- }
1395
- elseif ( $active_tab == 'status' ) {
1396
- settings_fields( 'status' );
1397
- do_settings_sections( 'status' );
1398
- }
1399
-
1400
- // end of form
1401
- echo '</form>';
1402
- } // end of plugin option page
1403
-
1404
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/admin_notices.php DELETED
@@ -1,83 +0,0 @@
1
- <?php
2
- /**
3
- * Will be included in the shariff.php.
4
- * Update info currently active for release 3.3 due to OpenShareCount.com replacement for Twitter
5
- */
6
-
7
- // prevent direct calls to admin_notices.php
8
- if ( ! class_exists('WP') ) { die(); }
9
-
10
- // update info currently active for release 3.3 due to OpenShareCount replacement for Twitter
11
-
12
- // display an update notice that can be dismissed
13
- function shariff3UU_admin_notice() {
14
- global $current_user;
15
- $user_id = $current_user->ID;
16
- // check that the user hasn't already clicked to ignore the message and can access options
17
- if ( ! get_user_meta( $user_id, 'shariff3UU_ignore_notice' ) && current_user_can( 'manage_options' ) ) {
18
- $link = add_query_arg( 'shariff3UU_nag_ignore', '0', esc_url_raw( $_SERVER['REQUEST_URI'] ) );
19
- echo "<div class='updated'><a href='" . esc_url( $link ) . "' class='shariff_admininfo_cross'><div class='shariff_cross_icon'></div></a><p>" . __( 'Shariff Wrapper: Twitter has disabled share counts. Please read <a href="https://www.jplambeck.de/twitter-saveoursharecounts/" target="_blank"><strong>this post</strong></a> prior to activating the alternative via OpenShareCount.com!', 'shariff3UU' ) . "</span></p></div>";
20
- }
21
- }
22
- add_action( 'admin_notices', 'shariff3UU_admin_notice' );
23
-
24
- // helper function for shariff3UU_admin_notice()
25
- function shariff3UU_nag_ignore() {
26
- global $current_user;
27
- $user_id = $current_user->ID;
28
- // If user clicks to ignore the notice, add that to their user meta
29
- if ( isset( $_GET['shariff3UU_nag_ignore'] ) && sanitize_text_field($_GET['shariff3UU_nag_ignore'] ) == '0' ) {
30
- add_user_meta( $user_id, 'shariff3UU_ignore_notice', 'true', true );
31
- }
32
- }
33
- add_action('admin_init', 'shariff3UU_nag_ignore');
34
-
35
- // display an info notice if flattr is set as a service, but no username is entered
36
- function shariff3UU_flattr_notice() {
37
- if ( isset( $GLOBALS["shariff3UU"]["services"] ) && ( strpos( $GLOBALS["shariff3UU"]["services"], 'flattr' ) !== false ) && empty( $GLOBALS["shariff3UU"]["flattruser"] ) && current_user_can( 'manage_options' ) ) {
38
- echo "<div class='error'><p>" . __('Please check your ', 'shariff3UU') . "<a href='" . get_bloginfo('wpurl') . "/wp-admin/options-general.php?page=shariff3uu&tab=advanced'>" . __('Shariff-Settings</a> - Flattr was selected, but no username was provided! Please enter your <strong>Flattr username</strong> in the shariff options!', 'shariff3UU') . "</span></p></div>";
39
- }
40
- }
41
- add_action( 'admin_notices', 'shariff3UU_flattr_notice' );
42
-
43
- // display an info notice if patreon is set as a service, but no username is entered
44
- function shariff3UU_patreon_notice() {
45
- if ( isset( $GLOBALS["shariff3UU"]["services"] ) && ( strpos( $GLOBALS["shariff3UU"]["services"], 'patreon' ) !== false ) && empty( $GLOBALS["shariff3UU"]["patreonid"] ) && current_user_can( 'manage_options' ) ) {
46
- echo "<div class='error'><p>" . __('Please check your ', 'shariff3UU') . "<a href='" . get_bloginfo('wpurl') . "/wp-admin/options-general.php?page=shariff3uu&tab=advanced'>" . __('Shariff-Settings</a> - Patreon was selected, but no username was provided! Please enter your <strong>Patreon username</strong> in the shariff options!', 'shariff3UU') . "</span></p></div>";
47
- }
48
- }
49
- add_action( 'admin_notices', 'shariff3UU_patreon_notice' );
50
-
51
- // display an info notice if paypal is set as a service, but no button id is entered
52
- function shariff3UU_paypal_notice() {
53
- if ( isset( $GLOBALS["shariff3UU"]["services"] ) && ( strpos( $GLOBALS["shariff3UU"]["services"], 'paypal' ) !== false ) && ( strpos( $GLOBALS["shariff3UU"]["services"], 'paypalme' ) === false ) && empty( $GLOBALS["shariff3UU"]["paypalbuttonid"] ) && current_user_can( 'manage_options' ) ) {
54
- echo "<div class='error'><p>" . __('Please check your ', 'shariff3UU') . "<a href='" . get_bloginfo('wpurl') . "/wp-admin/options-general.php?page=shariff3uu&tab=advanced'>" . __('Shariff-Settings</a> - PayPal was selected, but no button ID was provided! Please enter your <strong>Hosted Button ID</strong> in the shariff options!', 'shariff3UU') . "</span></p></div>";
55
- }
56
- }
57
- add_action( 'admin_notices', 'shariff3UU_paypal_notice' );
58
-
59
- // display an info notice if paypalme is set as a service, but no paypal.me id is entered
60
- function shariff3UU_paypalme_notice() {
61
- if ( isset( $GLOBALS["shariff3UU"]["services"] ) && ( strpos( $GLOBALS["shariff3UU"]["services"], 'paypalme' ) !== false ) && empty( $GLOBALS["shariff3UU"]["paypalmeid"] ) && current_user_can( 'manage_options' ) ) {
62
- echo "<div class='error'><p>" . __('Please check your ', 'shariff3UU') . "<a href='" . get_bloginfo('wpurl') . "/wp-admin/options-general.php?page=shariff3uu&tab=advanced'>" . __('Shariff-Settings</a> - PayPal.Me was selected, but no ID was provided! Please enter your <strong>PayPal.Me ID</strong> in the shariff options!', 'shariff3UU') . "</span></p></div>";
63
- }
64
- }
65
- add_action( 'admin_notices', 'shariff3UU_paypalme_notice' );
66
-
67
- // display an info notice if bitcoin is set as a service, but no address is entered
68
- function shariff3UU_bitcoin_notice() {
69
- if ( isset( $GLOBALS["shariff3UU"]["services"] ) && ( strpos( $GLOBALS["shariff3UU"]["services"], 'bitcoin' ) !== false ) && empty( $GLOBALS["shariff3UU"]["bitcoinaddress"] ) && current_user_can( 'manage_options' ) ) {
70
- echo "<div class='error'><p>" . __('Please check your ', 'shariff3UU') . "<a href='" . get_bloginfo('wpurl') . "/wp-admin/options-general.php?page=shariff3uu&tab=advanced'>" . __('Shariff-Settings</a> - Bitcoin was selected, but no address was provided! Please enter your <strong>Bitcoin Address</strong> in the shariff options!', 'shariff3UU') . "</span></p></div>";
71
- }
72
- }
73
- add_action( 'admin_notices', 'shariff3UU_bitcoin_notice' );
74
-
75
- // display an info notice if mailform is set as a service, but mail form functionality has been disabled
76
- function shariff3UU_mail_notice() {
77
- if ( isset( $GLOBALS["shariff3UU_mailform"]["disable_mailform"] ) && ( strpos( $GLOBALS["shariff3UU_basic"]["services"], 'mailform' ) !== false ) && isset( $GLOBALS["shariff3UU"]["disable_mailform"] ) && $GLOBALS["shariff3UU"]["disable_mailform"] == '1' && current_user_can( 'manage_options' ) ) {
78
- echo "<div class='error'><p>" . __('Please check your ', 'shariff3UU') . "<a href='" . get_bloginfo('wpurl') . "/wp-admin/options-general.php?page=shariff3uu&tab=mailform'>" . __('Shariff-Settings</a> - Mailform has been selected as a service, but mail form functionality is disabled!', 'shariff3UU') . "</span></p></div>";
79
- }
80
- }
81
- add_action( 'admin_notices', 'shariff3UU_mail_notice' );
82
-
83
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/index.php CHANGED
@@ -1,222 +1,42 @@
1
  <?php
2
- // prevent caching
3
- header( "Expires: Sat, 24 Jan 1970 04:10:00 GMT" ); // date from the past
4
- header( "Last-Modified: " . gmdate("D, d M Y H:i:s" ) . " GMT" ); // always changed
5
- header( "Cache-Control: no-store, no-cache, must-revalidate" );
6
- header( "Cache-Control: post-check=0, pre-check=0", false ); // just for MSIE 5
7
- header( "Pragma: no-cache" );
8
 
9
- // send correct headers
10
- header('Content-type: application/json; charset=utf-8');
11
 
12
- // exit if no url is provided
13
- if ( ! isset( $_GET["url"] ) ) die('No URL provided!');
14
-
15
- // build the wp root path
16
- $wp_root_path = dirname( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) );
17
 
18
- // if wp-blog-header.php doesn't exist at $wp_root_path, then try the constant
19
- if( ! file_exists( $wp_root_path . '/wp-blog-header.php') ) {
20
- // get the shariff-config.php
21
- if( file_exists( 'shariff-config.php' ) ) {
22
- require ( 'shariff-config.php' );
23
- }
24
- // try the constant, if it was changed
25
- if ( defined( SHARIFF_WP_ROOT_PATH ) && ( SHARIFF_WP_ROOT_PATH != '/path/to/wordpress/' ) ) {
26
- $wp_root_path = SHARIFF_WP_ROOT_PATH;
27
- if( ! file_exists( $wp_root_path . '/wp-blog-header.php') ) {
28
- // search for it
29
- $wp_load = rsearch( $wp_root_path, '/wp-load.php/' );
30
- // set $wp_root_path to the location of wp-load.php
31
- $wp_root_path = $wp_load['path'];
32
- // save it to shariff-config.php
33
- configsave( $wp_root_path );
34
- }
35
- }
36
- else {
37
- // search for it
38
- $wp_load = rsearch( $wp_root_path, '/wp-load.php/' );
39
- // set $wp_root_path to the location of wp-load.php
40
- $wp_root_path = $wp_load['path'];
41
- // save it to shariff-config.php
42
- configsave( $wp_root_path );
43
- }
44
- }
45
-
46
- // search in the subfolders of $wp_root_path for a given file (regex)
47
- function rsearch( $folder, $pattern ) {
48
- $dir = new RecursiveDirectoryIterator( $folder );
49
- $iterator = new RecursiveIteratorIterator( $dir );
50
- $files = new RegexIterator( $iterator, $pattern, RegexIterator::GET_MATCH );
51
- $fileList = array();
52
- foreach( $files as $file ) {
53
- $fileList[] = array(
54
- 'file' => $file,
55
- 'path' => $iterator->getPath()
56
- );
57
- }
58
- // return only the first result
59
- return $fileList[0];
60
- }
61
 
62
- // save $wp_root_path in shariff-config.php
63
- function configsave( $wp_root_path ) {
64
- $shariffconfig = fopen( "shariff-config.php", "w") or die( "Unable to create or open the shariff-config.php!" );
65
- $txt = "<?php\n\n// Here you can define the path to your WordPress installation in case you have changed the default directory structure\n// Replace /www/htdocs/w00a94e9/social-emotions.de with the path to your wp-blog-header.php\n\ndefine( 'SHARIFF_WP_ROOT_PATH', '" . $wp_root_path . "' );\n\n?>\n";
66
- fwrite( $shariffconfig, $txt );
67
- fclose( $shariffconfig );
68
- }
69
 
70
- // fire up WordPress without theme support
71
- #rtz20161127: bloed, dass wir hier nicht dierekt nach der wp-config ansetzen und mit
72
- # if ( ! defined( 'WP_USE_THEMES' ) )
73
- # pruefen koennen. Klar brauchen wir im Backend kein Theme, aber so wirft es ggf errors
74
- define('WP_USE_THEMES', false);
75
- require ( $wp_root_path . '/wp-blog-header.php');
76
 
77
- // get shariff statistic options
78
- $shariff3UU_statistic = (array) get_option( 'shariff3UU_statistic' );
79
-
80
- // if we have an external backend make a redirect
81
- // usually on a well configured host this should not happen
82
- // but it is better to have a bad fallback than no fallback
83
- if ( isset( $shariff3UU_statistic["external_host"] ) && $shariff3UU_statistic["external_host"] != null ) {
84
- header( 'Location: ' . $shariff3UU_statistic["external_host"] . 'backend/?' . $_SERVER["QUERY_STRING"] );
85
- // nothing else we can do for the client
86
- die();
87
- }
88
 
89
- // if a custom permalink structure is used, WordPress throws a 404 in every ajax call
90
- header( "HTTP/1.1 200 OK" );
91
-
92
- // make sure that the provided url matches the WordPress domain
93
- $get_url = parse_url( esc_url( $_GET["url"] ) );
94
- $wp_url = parse_url( esc_url( get_bloginfo('url') ) );
95
- // on an external backend check allowed hosts
96
- if ( isset( $SHARIFF_FRONTENDS ) ) {
97
- if ( ! array_key_exists( $get_url['host'], $SHARIFF_FRONTENDS ) ) {
98
- die( 'Domain not allowed by this server!' );
99
  }
100
- }
101
- // else compare that domain is equal
102
- elseif ( $get_url['host'] != $wp_url['host'] ) {
103
- die( 'Wrong domain!' );
104
- }
105
 
106
- // get url
107
- $post_url = urlencode( esc_url( $_GET["url"] ) );
108
- $post_url2 = esc_url( $_GET["url"] );
109
 
110
- // set transient name
111
- // transient names can only contain 40 characters, therefore we use a hash (md5 always creeates a 32 character hash)
112
- // we need a prefix so we can clean up on deinstallation and updates
113
- $post_hash = 'shariff' . hash( "md5", $post_url );
114
-
115
- // check if transient exist and is valid
116
- if ( get_transient( $post_hash ) !== false ) {
117
- // use stored data
118
- $share_counts = get_transient( $post_hash );
119
- }
120
- // if transient doesn't exit or is outdated, we fetch all counts
121
- else {
122
- // if we have a constant for the ttl
123
- if ( defined( 'SHARIFF_BACKEND_TTL' ) ) $ttl = SHARIFF_BACKEND_TTL;
124
- // elseif check for option from the WordPress plugin, must be between 120 and 7200 seconds
125
- elseif ( isset( $shariff3UU_statistic['ttl'] ) ) {
126
- $ttl = absint( $shariff3UU_statistic['ttl'] );
127
- // make sure ttl is a reasonable number
128
- if ( $ttl < '61' ) $ttl = '60';
129
- elseif ( $ttl > '7200' ) $ttl = '7200';
130
- }
131
- // else set it to default (60 seconds)
132
- else {
133
- $ttl = '60';
134
- }
135
-
136
- // adjust ttl based on the post age
137
- if ( isset ( $_GET["timestamp"] ) ) {
138
- // the timestamp represents the last time the post or page was modfied
139
- $post_time = intval( $_GET["timestamp"] );
140
- $current_time = current_time( 'timestamp', true );
141
- $post_age = round( abs( $current_time - $post_time ) );
142
- if ( $post_age > '0' ) {
143
- $post_age_days = round( $post_age / 60 / 60 / 24 );
144
- // make sure ttl base is not getting too high
145
- if ( $ttl > '300' ) $ttl = '300';
146
- $ttl = round( ( $ttl + $post_age_days * 3 ) * ( $post_age_days * 2 ) );
147
- }
148
- // set minimum ttl to 60 seconds and maxium ttl to one week
149
- if ( $ttl < '60' ) {
150
- $ttl = '60';
151
- }
152
- elseif ( $ttl > '604800' ) {
153
- $ttl = '604800';
154
- }
155
- // in case we get a timestamp older than 01.01.2000 or for example a 0, use a reasonable default value of five minutes
156
- if ( $post_time < '946684800' ) {
157
- $ttl = '300';
158
- }
159
- }
160
-
161
- // Facebook
162
- if ( ! isset ( $shariff3UU_statistic["disable"]["facebook"] ) || ( isset ( $shariff3UU_statistic["disable"]["facebook"] ) && $shariff3UU_statistic["disable"]["facebook"] == 0 ) ) {
163
- include ( 'services/facebook.php' );
164
- }
165
- // Twitter - https://blog.twitter.com/2015/hard-decisions-for-a-sustainable-platform
166
- // replacement of some sort: http://opensharecount.com
167
- if ( ! isset ( $shariff3UU_statistic["disable"]["twitter"] ) || ( isset ( $shariff3UU_statistic["disable"]["twitter"] ) && $shariff3UU_statistic["disable"]["twitter"] == 0 ) ) {
168
- include ( 'services/twitter.php' );
169
- }
170
- // GooglePlus
171
- if ( ! isset ( $shariff3UU_statistic["disable"]["googleplus"] ) || ( isset ( $shariff3UU_statistic["disable"]["googleplus"] ) && $shariff3UU_statistic["disable"]["googleplus"] == 0 ) ) {
172
- include ( 'services/googleplus.php' );
173
- }
174
- // Xing
175
- if ( ! isset ( $shariff3UU_statistic["disable"]["xing"] ) || ( isset ( $shariff3UU_statistic["disable"]["xing"] ) && $shariff3UU_statistic["disable"]["xing"] == 0 ) ) {
176
- include ( 'services/xing.php' );
177
- }
178
- // LinkedIn
179
- if ( ! isset ( $shariff3UU_statistic["disable"]["linkedin"] ) || ( isset ( $shariff3UU_statistic["disable"]["linkedin"] ) && $shariff3UU_statistic["disable"]["linkedin"] == 0 ) ) {
180
- include ( 'services/linkedin.php' );
181
- }
182
- // Pinterest
183
- if ( ! isset ( $shariff3UU_statistic["disable"]["pinterest"] ) || ( isset ( $shariff3UU_statistic["disable"]["pinterest"] ) && $shariff3UU_statistic["disable"]["pinterest"] == 0 ) ) {
184
- include ( 'services/pinterest.php' );
185
- }
186
- // Flattr
187
- if ( ! isset ( $shariff3UU_statistic["disable"]["flattr"] ) || ( isset ( $shariff3UU_statistic["disable"]["flattr"] ) && $shariff3UU_statistic["disable"]["flattr"] == 0 ) ) {
188
- include ( 'services/flattr.php' );
189
- }
190
- // Reddit
191
- if ( ! isset ( $shariff3UU_statistic["disable"]["reddit"] ) || ( isset ( $shariff3UU_statistic["disable"]["reddit"] ) && $shariff3UU_statistic["disable"]["reddit"] == 0 ) ) {
192
- include ( 'services/reddit.php' );
193
- }
194
- // StumbleUpon
195
- if ( ! isset ( $shariff3UU_statistic["disable"]["stumbleupon"] ) || ( isset ( $shariff3UU_statistic["disable"]["stumbleupon"] ) && $shariff3UU_statistic["disable"]["stumbleupon"] == 0 ) ) {
196
- include ( 'services/stumbleupon.php' );
197
- }
198
- // Tumblr
199
- if ( ! isset ( $shariff3UU_statistic["disable"]["tumblr"] ) || ( isset ( $shariff3UU_statistic["disable"]["tumblr"] ) && $shariff3UU_statistic["disable"]["tumblr"] == 0 ) ) {
200
- include ( 'services/tumblr.php' );
201
- }
202
- // AddThis
203
- if ( ! isset ( $shariff3UU_statistic["disable"]["addthis"] ) || ( isset ( $shariff3UU_statistic["disable"]["addthis"] ) && $shariff3UU_statistic["disable"]["addthis"] == 0 ) ) {
204
- include ( 'services/addthis.php' );
205
- }
206
- // VK
207
- if ( ! isset ( $shariff3UU_statistic["disable"]["vk"] ) || ( isset ( $shariff3UU_statistic["disable"]["vk"] ) && $shariff3UU_statistic["disable"]["vk"] == 0 ) ) {
208
- include ( 'services/vk.php' );
209
- }
210
-
211
- // save transient, if we have counts
212
- if ( isset( $share_counts ) && $share_counts != null ) {
213
- set_transient( $post_hash, $share_counts, $ttl );
214
- }
215
- }
216
-
217
- // draw results, if we have some
218
- if ( isset( $share_counts ) && $share_counts != null ) {
219
- echo json_encode( $share_counts );
220
  }
221
 
222
- ?>
1
  <?php
2
+ require_once __DIR__.'/vendor/autoload.php';
 
 
 
 
 
3
 
4
+ use Heise\Shariff\Backend;
5
+ use Zend\Config\Reader\Json;
6
 
7
+ class Application
8
+ {
9
+ public static function run()
10
+ {
11
+ header('Content-type: application/json');
12
 
13
+ if (!isset($_GET["url"])) {
14
+ echo json_encode(null);
15
+ return;
16
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ $reader = new \Zend\Config\Reader\Json();
 
 
 
 
 
 
19
 
20
+ // Ritze: dynamisch fuer WP
21
+ // I know this looks stupid. But I need I for tests on command line. So plz dont blame me ;-)
22
+ $tmp=$reader->fromFile('shariff.json');
 
 
 
23
 
24
+ // check, if user has changed it to his domain
25
+ if($tmp[domain]=='www.example.com') $tmp[domain]=$_SERVER[HTTP_HOST];
 
 
 
 
 
 
 
 
 
26
 
27
+ // check, if user has set a tmp dir (backend use '/tmp' by default)
28
+ if( empty($tmp[cache][cacheDir]) && !is_writable('/tmp') ){
29
+ // than we us the $upload_tmp_dir
30
+ $upload_tmp_dir=ini_get('upload_tmp_dir');
31
+ if( !empty($upload_tmp_dir) && is_writable($upload_tmp_dir) ) $tmp[cache][cacheDir]=$upload_tmp_dir;
32
+ else die('No usable tmp dir found.');
 
 
 
 
33
  }
 
 
 
 
 
34
 
35
+ $shariff = new Backend($tmp);
36
+ // ENDERitze: dynamisch fuer WP
 
37
 
38
+ echo json_encode($shariff->get($_GET["url"]));
39
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
 
42
+ Application::run();
backend/services/addthis.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
-
3
- // AddThis
4
-
5
- // fetch counts
6
- $addthis = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'http://api-public.addthis.com/url/shares.json?url=' . $post_url ) ) );
7
- $addthis_json = json_decode( $addthis, true );
8
-
9
- // store results, if we have some
10
- if ( isset( $addthis_json['shares'] ) ) {
11
- $share_counts['addthis'] = intval( $addthis_json['shares'] );
12
- }
13
-
14
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/facebook.php DELETED
@@ -1,38 +0,0 @@
1
- <?php
2
-
3
- // Facebook
4
-
5
- // if we have a fb id and secret, use it
6
- if ( isset( $shariff3UU_statistic['fb_id'] ) && isset( $shariff3UU_statistic['fb_secret'] ) ) {
7
- // on 32-bit PHP the constant is 4 and we have to disable the check because the id is too long
8
- if ( ( defined( PHP_INT_SIZE ) && PHP_INT_SIZE === '4' ) || ! defined( PHP_INT_SIZE ) ) {
9
- $fb_app_id = $shariff3UU_statistic['fb_id'];
10
- }
11
- else {
12
- $fb_app_id = absint( $shariff3UU_statistic['fb_id'] );
13
- }
14
- $fb_app_secret = sanitize_text_field( $shariff3UU_statistic['fb_secret'] );
15
- // get fb access token
16
- $fb_token = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://graph.facebook.com/oauth/access_token?client_id=' . $fb_app_id . '&client_secret=' . $fb_app_secret . '&grant_type=client_credentials' ) ) );
17
- // use token to get share counts
18
- $facebook = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://graph.facebook.com/v2.2/?id=' . $post_url . '&' . $fb_token ) ) );
19
- $facebook_json = json_decode( $facebook, true );
20
- }
21
- // otherwise use the normal way
22
- else {
23
- $facebook = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://graph.facebook.com/fql?q=SELECT%20total_count%20FROM%20link_stat%20WHERE%20url="' . $post_url . '"' ) ) );
24
- $facebook_json = json_decode( $facebook, true );
25
- }
26
-
27
- // store results - use total_count if it exists, otherwise use share_count - ordered based on proximity of occurrence
28
- if ( isset( $facebook_json['data'] ) && isset( $facebook_json['data'][0] ) && isset( $facebook_json['data'][0]['total_count'] ) ) {
29
- $share_counts['facebook'] = intval( $facebook_json['data'][0]['total_count'] );
30
- }
31
- elseif ( isset($facebook_json['share'] ) && isset( $facebook_json['share']['share_count'] ) ) {
32
- $share_counts['facebook'] = intval( $facebook_json['share']['share_count'] );
33
- }
34
- elseif ( isset($facebook_json['data'] ) && isset( $facebook_json['data'][0] ) && isset( $facebook_json['data'][0]['share_count'] ) ) {
35
- $share_counts['facebook'] = intval( $facebook_json['data'][0]['share_count'] );
36
- }
37
-
38
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/flattr.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
-
3
- // Flattr
4
-
5
- // fetch counts
6
- $flattr = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://api.flattr.com/rest/v2/things/lookup/?url=' . $post_url ) ) );
7
- $flattr_json = json_decode( $flattr, true );
8
-
9
- // store results, if we have some
10
- if ( isset( $flattr_json['flattrs'] ) ) {
11
- $share_counts['flattr'] = intval( $flattr_json['flattrs'] );
12
- }
13
-
14
- // if no thing was found, set it to 0
15
- elseif ( isset( $flattr_json['description'] ) && $flattr_json['description'] == 'No thing was found' ) {
16
- $share_counts['flattr'] = 0;
17
- }
18
-
19
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/googleplus.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
-
3
- // GooglePlus
4
-
5
- // set google options
6
- $google_options = array(
7
- 'method' => 'pos.plusones.get',
8
- 'id' => 'p',
9
- 'params' => array(
10
- 'nolog' => 'true',
11
- 'id' => $post_url2,
12
- 'source' => 'widget',
13
- 'userId' => '@viewer',
14
- 'groupId' => '@self'
15
- ),
16
- 'jsonrpc' => '2.0',
17
- 'key' => 'p',
18
- 'apiVersion' => 'v1'
19
- );
20
-
21
- // set post options
22
- $google_post_options = array(
23
- 'method' => 'POST',
24
- 'timeout' => 5,
25
- 'redirection' => 5,
26
- 'httpversion' => '1.0',
27
- 'blocking' => true,
28
- 'headers' => array( 'content-type' => 'application/json' ),
29
- 'body' => json_encode( $google_options )
30
- );
31
-
32
- // fetch counts
33
- $googleplus = sanitize_text_field( wp_remote_retrieve_body( wp_remote_post( 'https://clients6.google.com/rpc?key=AIzaSyCKSbrvQasunBoV16zDH9R33D88CeLr9gQ', $google_post_options ) ) );
34
- $google_json = json_decode( $googleplus, true );
35
-
36
- // store results, if we have some
37
- if ( isset( $google_json['result']['metadata']['globalCounts']['count'] ) ) {
38
- $share_counts['googleplus'] = intval( $google_json['result']['metadata']['globalCounts']['count'] );
39
- }
40
-
41
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/linkedin.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
-
3
- // LinkedIn
4
-
5
- // fetch counts
6
- $linkedin = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://www.linkedin.com/countserv/count/share?url=' . $post_url . '&lang=de_DE&format=json' ) ) );
7
- $linkedin_json = json_decode( $linkedin, true );
8
-
9
- // store results, if we have some
10
- if ( isset( $linkedin_json['count'] ) ) {
11
- $share_counts['linkedin'] = intval( $linkedin_json['count'] );
12
- }
13
-
14
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/pinterest.php DELETED
@@ -1,15 +0,0 @@
1
- <?php
2
-
3
- // Pinterest
4
-
5
- // fetch counts
6
- $pinterest = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'http://api.pinterest.com/v1/urls/count.json?callback=x&url=' . $post_url ) ) );
7
- $pinterest_json = rtrim( substr( $pinterest, 2 ) , ")" );
8
- $pinterest_json = json_decode( $pinterest_json, true );
9
-
10
- // store results, if we have some
11
- if ( isset( $pinterest_json['count'] ) ) {
12
- $share_counts['pinterest'] = intval( $pinterest_json['count'] );
13
- }
14
-
15
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/reddit.php DELETED
@@ -1,18 +0,0 @@
1
- <?php
2
-
3
- // Reddit
4
-
5
- // fetch counts
6
- $reddit = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://www.reddit.com/api/info.json?url=' . $post_url ) ) );
7
- $reddit_json = json_decode( $reddit, true );
8
-
9
- // store results, if we have some
10
- if ( isset( $reddit_json['data']['children'] ) ) {
11
- $count = 0;
12
- foreach ( $reddit_json['data']['children'] as $child ) {
13
- $count += intval( $child['data']['score'] );
14
- }
15
- $share_counts['reddit'] = $count;
16
- }
17
-
18
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/stumbleupon.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
-
3
- // StumbleUpon
4
-
5
- // fetch counts
6
- $stumbleupon = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://www.stumbleupon.com/services/1.01/badge.getinfo?url=' . $post_url ) ) );
7
- $stumbleupon_json = json_decode( $stumbleupon, true );
8
-
9
- // store results, if we have some
10
- if ( isset( $stumbleupon_json['success'] ) && $stumbleupon_json['success'] == true ) {
11
- if ( isset( $stumbleupon_json['result']['views'] ) ) {
12
- $share_counts['stumbleupon'] = intval( $stumbleupon_json['result']['views'] );
13
- }
14
- else {
15
- $share_counts['stumbleupon'] = 0;
16
- }
17
- }
18
-
19
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/tumblr.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
-
3
- // Tumblr
4
-
5
- // fetch counts
6
- $tumblr = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'https://api.tumblr.com/v2/share/stats?url=' . $post_url ) ) );
7
- $tumblr_json = json_decode( $tumblr, true );
8
-
9
- // store results, if we have some
10
- if ( isset( $tumblr_json['response']['note_count'] ) ) {
11
- $share_counts['tumblr'] = intval( $tumblr_json['response']['note_count'] );
12
- }
13
-
14
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/twitter.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
-
3
- // Twitter
4
-
5
- // fetch counts
6
- $twitter = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'http://opensharecount.com/count.json?url=' . $post_url ) ) );
7
- $twitter_json = json_decode( $twitter, true );
8
-
9
- // store results, if we have some
10
- if ( isset( $twitter_json['count'] ) && ! isset( $twitter_json['error'] ) ) {
11
- $share_counts['twitter'] = intval( $twitter_json['count'] );
12
- }
13
-
14
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/vk.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
-
3
- // VK
4
-
5
- // fetch counts
6
- $vk = sanitize_text_field( wp_remote_retrieve_body( wp_remote_get( 'http://vk.com/share.php?act=count&url=' . $post_url ) ) );
7
- if ( isset( $vk ) ) {
8
- preg_match( '/^VK.Share.count\((\d+),\s+(\d+)\);$/i', $vk, $matches );
9
- $vk_count = intval( $matches[2] );
10
- }
11
-
12
- // store results, if we have some
13
- if ( isset( $vk_count ) ) {
14
- $share_counts['vk'] = $vk_count;
15
- }
16
-
17
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/services/xing.php DELETED
@@ -1,30 +0,0 @@
1
- <?php
2
-
3
- // Xing
4
-
5
- // set xing options
6
- $xing_json = array(
7
- 'url' => $post_url2
8
- );
9
-
10
- // set post options
11
- $xing_post_options = array(
12
- 'method' => 'POST',
13
- 'timeout' => 5,
14
- 'redirection' => 5,
15
- 'httpversion' => '1.0',
16
- 'blocking' => true,
17
- 'headers' => array( 'content-type' => 'application/json' ),
18
- 'body' => json_encode( $xing_json )
19
- );
20
-
21
- // fetch counts
22
- $xing = sanitize_text_field( wp_remote_retrieve_body( wp_remote_post( 'https://www.xing-share.com/spi/shares/statistics', $xing_post_options ) ) );
23
- $xing_json = json_decode( $xing, true );
24
-
25
- // store results, if we have some
26
- if ( isset( $xing_json['share_counter'] ) ) {
27
- $share_counts['xing'] = intval( $xing_json['share_counter'] );
28
- }
29
-
30
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/shariff.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cache": {
3
+ "ttl": 60
4
+ },
5
+ "domain": "www.example.com",
6
+ "services": [
7
+ "GooglePlus",
8
+ "Twitter",
9
+ "Facebook"
10
+ ]
11
+ }
backend/src/Backend.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Heise\Shariff;
3
+
4
+ use GuzzleHttp\Client;
5
+ use GuzzleHttp\Pool;
6
+ use Zend\Cache\Storage\Adapter\Filesystem;
7
+
8
+ class Backend
9
+ {
10
+
11
+ protected $cache;
12
+ protected $client;
13
+ protected $domain;
14
+ protected $services = [];
15
+
16
+ public function __construct($config)
17
+ {
18
+ $this->domain = $config["domain"];
19
+ $this->client = new Client();
20
+ $this->baseCacheKey = md5(json_encode($config));
21
+
22
+ $this->cache = new Filesystem();
23
+ $options = $this->cache->getOptions();
24
+ $options->setCacheDir(
25
+ array_key_exists("cacheDir", $config["cache"])
26
+ ? $config["cache"]["cacheDir"]
27
+ : sys_get_temp_dir()
28
+ );
29
+ $options->setNamespace('Shariff');
30
+ $options->setTtl($config["cache"]["ttl"]);
31
+
32
+ $this->services = $this->getServicesByName($config["services"]);
33
+ }
34
+
35
+ private function getServicesByName($serviceNames)
36
+ {
37
+ $services = [];
38
+ foreach ($serviceNames as $serviceName) {
39
+ $service = new \ReflectionClass("Heise\Shariff\Backend\\$serviceName");
40
+ foreach ($service->getInterfaceNames() as $interface) {
41
+ if ($interface === 'Heise\Shariff\Backend\ServiceInterface') {
42
+ $services[] = $service->newInstance();
43
+ }
44
+ }
45
+ }
46
+ return $services;
47
+ }
48
+
49
+ private function isValidDomain($url)
50
+ {
51
+ if ($this->domain) {
52
+ $parsed = parse_url($url);
53
+ if ($parsed["host"] != $this->domain) {
54
+ return false;
55
+ }
56
+ }
57
+ return true;
58
+ }
59
+
60
+ public function get($url)
61
+ {
62
+
63
+ // Aenderungen an der Konfiguration invalidieren den Cache
64
+ $cache_key = md5($url . $this->baseCacheKey);
65
+
66
+ if (!filter_var($url, FILTER_VALIDATE_URL)) {
67
+ return null;
68
+ }
69
+
70
+ if ($this->cache->hasItem($cache_key)) {
71
+ return json_decode($this->cache->getItem($cache_key), true);
72
+ }
73
+
74
+ if (!$this->isValidDomain($url)) {
75
+ return null;
76
+ }
77
+
78
+ $requests = array_map(
79
+ function ($service) use ($url) {
80
+ return $service->getRequest($url);
81
+ },
82
+ $this->services
83
+ );
84
+
85
+ $results = Pool::batch($this->client, $requests);
86
+
87
+ $counts = [];
88
+ $i = 0;
89
+ foreach ($this->services as $service) {
90
+ if (method_exists($results[$i], "json")) {
91
+ $count = $service->extractCount($results[$i]->json());
92
+ $counts[ $service->getName() ] = $count;
93
+ }
94
+ $i++;
95
+ }
96
+
97
+ $this->cache->setItem($cache_key, json_encode($counts));
98
+
99
+ return $counts;
100
+ }
101
+ }
backend/src/Backend/Facebook.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Heise\Shariff\Backend;
4
+
5
+ class Facebook extends Request implements ServiceInterface
6
+ {
7
+
8
+ public function getName()
9
+ {
10
+ return 'facebook';
11
+ }
12
+
13
+ public function getRequest($url)
14
+ {
15
+ $facebookURL = 'https://api.facebook.com/method/fql.query';
16
+ $facebookURL .= '?format=json';
17
+ $facebookURL .= '&query=select share_count from link_stat where url="' . $url . '"';
18
+ return $this->createRequest($facebookURL);
19
+ }
20
+
21
+ public function extractCount($data)
22
+ {
23
+ return $data[0]['share_count'];
24
+ }
25
+ }
backend/src/Backend/GooglePlus.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Heise\Shariff\Backend;
4
+
5
+ class GooglePlus extends Request implements ServiceInterface
6
+ {
7
+
8
+ public function getName()
9
+ {
10
+ return 'googleplus';
11
+ }
12
+
13
+ public function getRequest($url)
14
+ {
15
+ $gPlusUrl = 'https://clients6.google.com/rpc?key=AIzaSyCKSbrvQasunBoV16zDH9R33D88CeLr9gQ';
16
+ $json = [
17
+ 'method' => 'pos.plusones.get',
18
+ 'id' => 'p',
19
+ 'params' => [
20
+ 'nolog' => 'true',
21
+ 'id' => $url,
22
+ 'source' => 'widget',
23
+ 'userId' => '@viewer',
24
+ 'groupId' => '@self',
25
+ ],
26
+ 'jsonrpc' => '2.0',
27
+ 'key' => 'p',
28
+ 'apiVersion' => 'v1',
29
+ ];
30
+ return $this->createRequest($gPlusUrl, 'POST', ['json' => $json]);
31
+ }
32
+
33
+ public function extractCount($data)
34
+ {
35
+ return $data['result']['metadata']['globalCounts']['count'];
36
+ }
37
+ }
backend/src/Backend/Request.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Heise\Shariff\Backend;
3
+
4
+ abstract class Request
5
+ {
6
+
7
+ protected $client;
8
+
9
+ public function __construct()
10
+ {
11
+ $this->client = new \GuzzleHttp\Client();
12
+ }
13
+
14
+ protected function createRequest($url, $method = 'GET', $options = [])
15
+ {
16
+ // $defaults = ['future' => true, 'debug' => true];
17
+ $defaults = ['future' => true];
18
+
19
+ $req = $this->client->createRequest(
20
+ $method,
21
+ $url,
22
+ array_merge($defaults, $options)
23
+ );
24
+
25
+ return $req;
26
+ }
27
+ }
backend/src/Backend/ServiceInterface.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Heise\Shariff\Backend;
3
+
4
+ interface ServiceInterface
5
+ {
6
+ public function getRequest($url);
7
+ public function extractCount($data);
8
+ public function getName();
9
+ }
backend/src/Backend/Twitter.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Heise\Shariff\Backend;
3
+
4
+ class Twitter extends Request implements ServiceInterface
5
+ {
6
+
7
+ public function getName()
8
+ {
9
+ return 'twitter';
10
+ }
11
+
12
+ public function getRequest($url)
13
+ {
14
+ //$twitterUrl = 'http://urls.api.twitter.com/1/urls/count.json?url=' . $url;
15
+ $twitterUrl = 'https://cdn.api.twitter.com/1/urls/count.json?url=' . urlencode($url);
16
+ return $this->createRequest($twitterUrl);
17
+ }
18
+
19
+ public function extractCount($data)
20
+ {
21
+ return $data['count'];
22
+ }
23
+ }
backend/vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer' . '/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit41f83f65f066f47151be7379fbb2fc73::getLoader();
backend/vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0 class loader
17
+ *
18
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
19
+ *
20
+ * $loader = new \Composer\Autoload\ClassLoader();
21
+ *
22
+ * // register classes with namespaces
23
+ * $loader->add('Symfony\Component', __DIR__.'/component');
24
+ * $loader->add('Symfony', __DIR__.'/framework');
25
+ *
26
+ * // activate the autoloader
27
+ * $loader->register();
28
+ *
29
+ * // to enable searching the include path (eg. for PEAR packages)
30
+ * $loader->setUseIncludePath(true);
31
+ *
32
+ * In this example, if you try to use a class in the Symfony\Component
33
+ * namespace or one of its children (Symfony\Component\Console for instance),
34
+ * the autoloader will first look for the class under the component/
35
+ * directory, and it will then fallback to the framework/ directory if not
36
+ * found before giving up.
37
+ *
38
+ * This class is loosely based on the Symfony UniversalClassLoader.
39
+ *
40
+ * @author Fabien Potencier <fabien@symfony.com>
41
+ * @author Jordi Boggiano <j.boggiano@seld.be>
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+
57
+ public function getPrefixes()
58
+ {
59
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
60
+ }
61
+
62
+ public function getPrefixesPsr4()
63
+ {
64
+ return $this->prefixDirsPsr4;
65
+ }
66
+
67
+ public function getFallbackDirs()
68
+ {
69
+ return $this->fallbackDirsPsr0;
70
+ }
71
+
72
+ public function getFallbackDirsPsr4()
73
+ {
74
+ return $this->fallbackDirsPsr4;
75
+ }
76
+
77
+ public function getClassMap()
78
+ {
79
+ return $this->classMap;
80
+ }
81
+
82
+ /**
83
+ * @param array $classMap Class to filename map
84
+ */
85
+ public function addClassMap(array $classMap)
86
+ {
87
+ if ($this->classMap) {
88
+ $this->classMap = array_merge($this->classMap, $classMap);
89
+ } else {
90
+ $this->classMap = $classMap;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Registers a set of PSR-0 directories for a given prefix, either
96
+ * appending or prepending to the ones previously set for this prefix.
97
+ *
98
+ * @param string $prefix The prefix
99
+ * @param array|string $paths The PSR-0 root directories
100
+ * @param bool $prepend Whether to prepend the directories
101
+ */
102
+ public function add($prefix, $paths, $prepend = false)
103
+ {
104
+ if (!$prefix) {
105
+ if ($prepend) {
106
+ $this->fallbackDirsPsr0 = array_merge(
107
+ (array) $paths,
108
+ $this->fallbackDirsPsr0
109
+ );
110
+ } else {
111
+ $this->fallbackDirsPsr0 = array_merge(
112
+ $this->fallbackDirsPsr0,
113
+ (array) $paths
114
+ );
115
+ }
116
+
117
+ return;
118
+ }
119
+
120
+ $first = $prefix[0];
121
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
122
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
123
+
124
+ return;
125
+ }
126
+ if ($prepend) {
127
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
128
+ (array) $paths,
129
+ $this->prefixesPsr0[$first][$prefix]
130
+ );
131
+ } else {
132
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
133
+ $this->prefixesPsr0[$first][$prefix],
134
+ (array) $paths
135
+ );
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Registers a set of PSR-4 directories for a given namespace, either
141
+ * appending or prepending to the ones previously set for this namespace.
142
+ *
143
+ * @param string $prefix The prefix/namespace, with trailing '\\'
144
+ * @param array|string $paths The PSR-0 base directories
145
+ * @param bool $prepend Whether to prepend the directories
146
+ */
147
+ public function addPsr4($prefix, $paths, $prepend = false)
148
+ {
149
+ if (!$prefix) {
150
+ // Register directories for the root namespace.
151
+ if ($prepend) {
152
+ $this->fallbackDirsPsr4 = array_merge(
153
+ (array) $paths,
154
+ $this->fallbackDirsPsr4
155
+ );
156
+ } else {
157
+ $this->fallbackDirsPsr4 = array_merge(
158
+ $this->fallbackDirsPsr4,
159
+ (array) $paths
160
+ );
161
+ }
162
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
163
+ // Register directories for a new namespace.
164
+ $length = strlen($prefix);
165
+ if ('\\' !== $prefix[$length - 1]) {
166
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
167
+ }
168
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
169
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
170
+ } elseif ($prepend) {
171
+ // Prepend directories for an already registered namespace.
172
+ $this->prefixDirsPsr4[$prefix] = array_merge(
173
+ (array) $paths,
174
+ $this->prefixDirsPsr4[$prefix]
175
+ );
176
+ } else {
177
+ // Append directories for an already registered namespace.
178
+ $this->prefixDirsPsr4[$prefix] = array_merge(
179
+ $this->prefixDirsPsr4[$prefix],
180
+ (array) $paths
181
+ );
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Registers a set of PSR-0 directories for a given prefix,
187
+ * replacing any others previously set for this prefix.
188
+ *
189
+ * @param string $prefix The prefix
190
+ * @param array|string $paths The PSR-0 base directories
191
+ */
192
+ public function set($prefix, $paths)
193
+ {
194
+ if (!$prefix) {
195
+ $this->fallbackDirsPsr0 = (array) $paths;
196
+ } else {
197
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Registers a set of PSR-4 directories for a given namespace,
203
+ * replacing any others previously set for this namespace.
204
+ *
205
+ * @param string $prefix The prefix/namespace, with trailing '\\'
206
+ * @param array|string $paths The PSR-4 base directories
207
+ */
208
+ public function setPsr4($prefix, $paths) {
209
+ if (!$prefix) {
210
+ $this->fallbackDirsPsr4 = (array) $paths;
211
+ } else {
212
+ $length = strlen($prefix);
213
+ if ('\\' !== $prefix[$length - 1]) {
214
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
215
+ }
216
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
217
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Turns on searching the include path for class files.
223
+ *
224
+ * @param bool $useIncludePath
225
+ */
226
+ public function setUseIncludePath($useIncludePath)
227
+ {
228
+ $this->useIncludePath = $useIncludePath;
229
+ }
230
+
231
+ /**
232
+ * Can be used to check if the autoloader uses the include path to check
233
+ * for classes.
234
+ *
235
+ * @return bool
236
+ */
237
+ public function getUseIncludePath()
238
+ {
239
+ return $this->useIncludePath;
240
+ }
241
+
242
+ /**
243
+ * Registers this instance as an autoloader.
244
+ *
245
+ * @param bool $prepend Whether to prepend the autoloader or not
246
+ */
247
+ public function register($prepend = false)
248
+ {
249
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
250
+ }
251
+
252
+ /**
253
+ * Unregisters this instance as an autoloader.
254
+ */
255
+ public function unregister()
256
+ {
257
+ spl_autoload_unregister(array($this, 'loadClass'));
258
+ }
259
+
260
+ /**
261
+ * Loads the given class or interface.
262
+ *
263
+ * @param string $class The name of the class
264
+ * @return bool|null True if loaded, null otherwise
265
+ */
266
+ public function loadClass($class)
267
+ {
268
+ if ($file = $this->findFile($class)) {
269
+ include $file;
270
+
271
+ return true;
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Finds the path to the file where the class is defined.
277
+ *
278
+ * @param string $class The name of the class
279
+ *
280
+ * @return string|false The path if found, false otherwise
281
+ */
282
+ public function findFile($class)
283
+ {
284
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
285
+ if ('\\' == $class[0]) {
286
+ $class = substr($class, 1);
287
+ }
288
+
289
+ // class map lookup
290
+ if (isset($this->classMap[$class])) {
291
+ return $this->classMap[$class];
292
+ }
293
+
294
+ // PSR-4 lookup
295
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';
296
+
297
+ $first = $class[0];
298
+ if (isset($this->prefixLengthsPsr4[$first])) {
299
+ foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
300
+ if (0 === strpos($class, $prefix)) {
301
+ foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
302
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
303
+ return $file;
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+
310
+ // PSR-4 fallback dirs
311
+ foreach ($this->fallbackDirsPsr4 as $dir) {
312
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
313
+ return $file;
314
+ }
315
+ }
316
+
317
+ // PSR-0 lookup
318
+ if (false !== $pos = strrpos($class, '\\')) {
319
+ // namespaced class name
320
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
321
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
322
+ } else {
323
+ // PEAR-like class name
324
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . '.php';
325
+ }
326
+
327
+ if (isset($this->prefixesPsr0[$first])) {
328
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
329
+ if (0 === strpos($class, $prefix)) {
330
+ foreach ($dirs as $dir) {
331
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
332
+ return $file;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ }
338
+
339
+ // PSR-0 fallback dirs
340
+ foreach ($this->fallbackDirsPsr0 as $dir) {
341
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
342
+ return $file;
343
+ }
344
+ }
345
+
346
+ // PSR-0 include paths.
347
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
348
+ return $file;
349
+ }
350
+
351
+ // Remember that this class does not exist.
352
+ return $this->classMap[$class] = false;
353
+ }
354
+ }
backend/vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
backend/vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ $vendorDir . '/react/promise/src/functions.php',
10
+ );
backend/vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Zend\\Stdlib\\' => array($vendorDir . '/zendframework/zend-stdlib'),
10
+ 'Zend\\ServiceManager\\' => array($vendorDir . '/zendframework/zend-servicemanager'),
11
+ 'Zend\\Json\\' => array($vendorDir . '/zendframework/zend-json'),
12
+ 'Zend\\EventManager\\' => array($vendorDir . '/zendframework/zend-eventmanager'),
13
+ 'Zend\\Config\\' => array($vendorDir . '/zendframework/zend-config'),
14
+ 'Zend\\Cache\\' => array($vendorDir . '/zendframework/zend-cache'),
15
+ );
backend/vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
10
+ 'Heise\\Shariff\\' => array($baseDir . '/src'),
11
+ 'GuzzleHttp\\Stream\\' => array($vendorDir . '/guzzlehttp/streams/src'),
12
+ 'GuzzleHttp\\Ring\\' => array($vendorDir . '/guzzlehttp/ringphp/src'),
13
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
14
+ );
backend/vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit41f83f65f066f47151be7379fbb2fc73
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit41f83f65f066f47151be7379fbb2fc73', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit41f83f65f066f47151be7379fbb2fc73', 'loadClassLoader'));
25
+
26
+ $vendorDir = dirname(__DIR__);
27
+ $baseDir = dirname($vendorDir);
28
+
29
+ $map = require __DIR__ . '/autoload_namespaces.php';
30
+ foreach ($map as $namespace => $path) {
31
+ $loader->set($namespace, $path);
32
+ }
33
+
34
+ $map = require __DIR__ . '/autoload_psr4.php';
35
+ foreach ($map as $namespace => $path) {
36
+ $loader->setPsr4($namespace, $path);
37
+ }
38
+
39
+ $classMap = require __DIR__ . '/autoload_classmap.php';
40
+ if ($classMap) {
41
+ $loader->addClassMap($classMap);
42
+ }
43
+
44
+ $loader->register(true);
45
+
46
+ $includeFiles = require __DIR__ . '/autoload_files.php';
47
+ foreach ($includeFiles as $file) {
48
+ require $file;
49
+ }
50
+
51
+ return $loader;
52
+ }
53
+ }
backend/vendor/composer/installed.json ADDED
@@ -0,0 +1,527 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "react/promise",
4
+ "version": "v2.1.0",
5
+ "version_normalized": "2.1.0.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/reactphp/promise.git",
9
+ "reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/937b04f1b0ee8f6d180e75a0830aac778ca4bcd6",
14
+ "reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "php": ">=5.4.0"
19
+ },
20
+ "time": "2014-10-15 20:05:57",
21
+ "type": "library",
22
+ "extra": {
23
+ "branch-alias": {
24
+ "dev-master": "2.0-dev"
25
+ }
26
+ },
27
+ "installation-source": "dist",
28
+ "autoload": {
29
+ "psr-4": {
30
+ "React\\Promise\\": "src/"
31
+ },
32
+ "files": [
33
+ "src/functions.php"
34
+ ]
35
+ },
36
+ "notification-url": "https://packagist.org/downloads/",
37
+ "license": [
38
+ "MIT"
39
+ ],
40
+ "authors": [
41
+ {
42
+ "name": "Jan Sorgalla",
43
+ "email": "jsorgalla@googlemail.com"
44
+ }
45
+ ],
46
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP"
47
+ },
48
+ {
49
+ "name": "guzzlehttp/streams",
50
+ "version": "3.0.0",
51
+ "version_normalized": "3.0.0.0",
52
+ "source": {
53
+ "type": "git",
54
+ "url": "https://github.com/guzzle/streams.git",
55
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
56
+ },
57
+ "dist": {
58
+ "type": "zip",
59
+ "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
60
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
61
+ "shasum": ""
62
+ },
63
+ "require": {
64
+ "php": ">=5.4.0"
65
+ },
66
+ "require-dev": {
67
+ "phpunit/phpunit": "~4.0"
68
+ },
69
+ "time": "2014-10-12 19:18:40",
70
+ "type": "library",
71
+ "extra": {
72
+ "branch-alias": {
73
+ "dev-master": "3.0-dev"
74
+ }
75
+ },
76
+ "installation-source": "dist",
77
+ "autoload": {
78
+ "psr-4": {
79
+ "GuzzleHttp\\Stream\\": "src/"
80
+ }
81
+ },
82
+ "notification-url": "https://packagist.org/downloads/",
83
+ "license": [
84
+ "MIT"
85
+ ],
86
+ "authors": [
87
+ {
88
+ "name": "Michael Dowling",
89
+ "email": "mtdowling@gmail.com",
90
+ "homepage": "https://github.com/mtdowling"
91
+ }
92
+ ],
93
+ "description": "Provides a simple abstraction over streams of data",
94
+ "homepage": "http://guzzlephp.org/",
95
+ "keywords": [
96
+ "Guzzle",
97
+ "stream"
98
+ ]
99
+ },
100
+ {
101
+ "name": "zendframework/zend-stdlib",
102
+ "version": "2.3.3",
103
+ "version_normalized": "2.3.3.0",
104
+ "target-dir": "Zend/Stdlib",
105
+ "source": {
106
+ "type": "git",
107
+ "url": "https://github.com/zendframework/Component_ZendStdlib.git",
108
+ "reference": "fa33e6647f830d0d2a1cb451efcdfe1bb9a66c33"
109
+ },
110
+ "dist": {
111
+ "type": "zip",
112
+ "url": "https://api.github.com/repos/zendframework/Component_ZendStdlib/zipball/fa33e6647f830d0d2a1cb451efcdfe1bb9a66c33",
113
+ "reference": "fa33e6647f830d0d2a1cb451efcdfe1bb9a66c33",
114
+ "shasum": ""
115
+ },
116
+ "require": {
117
+ "php": ">=5.3.23"
118
+ },
119
+ "require-dev": {
120
+ "zendframework/zend-eventmanager": "self.version",
121
+ "zendframework/zend-serializer": "self.version",
122
+ "zendframework/zend-servicemanager": "self.version"
123
+ },
124
+ "suggest": {
125
+ "zendframework/zend-eventmanager": "To support aggregate hydrator usage",
126
+ "zendframework/zend-serializer": "Zend\\Serializer component",
127
+ "zendframework/zend-servicemanager": "To support hydrator plugin manager usage"
128
+ },
129
+ "time": "2014-09-16 22:58:11",
130
+ "type": "library",
131
+ "extra": {
132
+ "branch-alias": {
133
+ "dev-master": "2.3-dev",
134
+ "dev-develop": "2.4-dev"
135
+ }
136
+ },
137
+ "installation-source": "dist",
138
+ "autoload": {
139
+ "psr-0": {
140
+ "Zend\\Stdlib\\": ""
141
+ }
142
+ },
143
+ "notification-url": "https://packagist.org/downloads/",
144
+ "license": [
145
+ "BSD-3-Clause"
146
+ ],
147
+ "homepage": "https://github.com/zendframework/zf2",
148
+ "keywords": [
149
+ "stdlib",
150
+ "zf2"
151
+ ]
152
+ },
153
+ {
154
+ "name": "zendframework/zend-eventmanager",
155
+ "version": "2.3.3",
156
+ "version_normalized": "2.3.3.0",
157
+ "target-dir": "Zend/EventManager",
158
+ "source": {
159
+ "type": "git",
160
+ "url": "https://github.com/zendframework/Component_ZendEventManager.git",
161
+ "reference": "4110fe64b10616b9bb71429a206d8e9e6d99e3ba"
162
+ },
163
+ "dist": {
164
+ "type": "zip",
165
+ "url": "https://api.github.com/repos/zendframework/Component_ZendEventManager/zipball/4110fe64b10616b9bb71429a206d8e9e6d99e3ba",
166
+ "reference": "4110fe64b10616b9bb71429a206d8e9e6d99e3ba",
167
+ "shasum": ""
168
+ },
169
+ "require": {
170
+ "php": ">=5.3.23",
171
+ "zendframework/zend-stdlib": "self.version"
172
+ },
173
+ "time": "2014-09-16 22:58:11",
174
+ "type": "library",
175
+ "extra": {
176
+ "branch-alias": {
177
+ "dev-master": "2.3-dev",
178
+ "dev-develop": "2.4-dev"
179
+ }
180
+ },
181
+ "installation-source": "dist",
182
+ "autoload": {
183
+ "psr-0": {
184
+ "Zend\\EventManager\\": ""
185
+ }
186
+ },
187
+ "notification-url": "https://packagist.org/downloads/",
188
+ "license": [
189
+ "BSD-3-Clause"
190
+ ],
191
+ "homepage": "https://github.com/zendframework/zf2",
192
+ "keywords": [
193
+ "eventmanager",
194
+ "zf2"
195
+ ]
196
+ },
197
+ {
198
+ "name": "zendframework/zend-servicemanager",
199
+ "version": "2.3.3",
200
+ "version_normalized": "2.3.3.0",
201
+ "target-dir": "Zend/ServiceManager",
202
+ "source": {
203
+ "type": "git",
204
+ "url": "https://github.com/zendframework/Component_ZendServiceManager.git",
205
+ "reference": "559403e4fd10db2516641f20f129a568d7e6a993"
206
+ },
207
+ "dist": {
208
+ "type": "zip",
209
+ "url": "https://api.github.com/repos/zendframework/Component_ZendServiceManager/zipball/559403e4fd10db2516641f20f129a568d7e6a993",
210
+ "reference": "559403e4fd10db2516641f20f129a568d7e6a993",
211
+ "shasum": ""
212
+ },
213
+ "require": {
214
+ "php": ">=5.3.23"
215
+ },
216
+ "require-dev": {
217
+ "zendframework/zend-di": "self.version"
218
+ },
219
+ "suggest": {
220
+ "zendframework/zend-di": "Zend\\Di component"
221
+ },
222
+ "time": "2014-09-16 22:58:11",
223
+ "type": "library",
224
+ "extra": {
225
+ "branch-alias": {
226
+ "dev-master": "2.3-dev",
227
+ "dev-develop": "2.4-dev"
228
+ }
229
+ },
230
+ "installation-source": "dist",
231
+ "autoload": {
232
+ "psr-0": {
233
+ "Zend\\ServiceManager\\": ""
234
+ }
235
+ },
236
+ "notification-url": "https://packagist.org/downloads/",
237
+ "license": [
238
+ "BSD-3-Clause"
239
+ ],
240
+ "homepage": "https://github.com/zendframework/zf2",
241
+ "keywords": [
242
+ "servicemanager",
243
+ "zf2"
244
+ ]
245
+ },
246
+ {
247
+ "name": "zendframework/zend-cache",
248
+ "version": "2.3.3",
249
+ "version_normalized": "2.3.3.0",
250
+ "target-dir": "Zend/Cache",
251
+ "source": {
252
+ "type": "git",
253
+ "url": "https://github.com/zendframework/Component_ZendCache.git",
254
+ "reference": "1966038a1568ebeaeeeaa78ce27bc7b340e30747"
255
+ },
256
+ "dist": {
257
+ "type": "zip",
258
+ "url": "https://api.github.com/repos/zendframework/Component_ZendCache/zipball/1966038a1568ebeaeeeaa78ce27bc7b340e30747",
259
+ "reference": "1966038a1568ebeaeeeaa78ce27bc7b340e30747",
260
+ "shasum": ""
261
+ },
262
+ "require": {
263
+ "php": ">=5.3.23",
264
+ "zendframework/zend-eventmanager": "self.version",
265
+ "zendframework/zend-servicemanager": "self.version",
266
+ "zendframework/zend-stdlib": "self.version"
267
+ },
268
+ "require-dev": {
269
+ "zendframework/zend-serializer": "self.version",
270
+ "zendframework/zend-session": "self.version"
271
+ },
272
+ "suggest": {
273
+ "ext-apc": "APC >= 3.1.6 to use the APC storage adapter",
274
+ "ext-dba": "DBA, to use the DBA storage adapter",
275
+ "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter",
276
+ "ext-wincache": "WinCache, to use the WinCache storage adapter",
277
+ "zendframework/zend-serializer": "Zend\\Serializer component",
278
+ "zendframework/zend-session": "Zend\\Session component"
279
+ },
280
+ "time": "2014-09-16 22:58:11",
281
+ "type": "library",
282
+ "extra": {
283
+ "branch-alias": {
284
+ "dev-master": "2.3-dev",
285
+ "dev-develop": "2.4-dev"
286
+ }
287
+ },
288
+ "installation-source": "dist",
289
+ "autoload": {
290
+ "psr-0": {
291
+ "Zend\\Cache\\": ""
292
+ }
293
+ },
294
+ "notification-url": "https://packagist.org/downloads/",
295
+ "license": [
296
+ "BSD-3-Clause"
297
+ ],
298
+ "description": "provides a generic way to cache any data",
299
+ "homepage": "https://github.com/zendframework/zf2",
300
+ "keywords": [
301
+ "cache",
302
+ "zf2"
303
+ ]
304
+ },
305
+ {
306
+ "name": "zendframework/zend-config",
307
+ "version": "2.3.3",
308
+ "version_normalized": "2.3.3.0",
309
+ "target-dir": "Zend/Config",
310
+ "source": {
311
+ "type": "git",
312
+ "url": "https://github.com/zendframework/Component_ZendConfig.git",
313
+ "reference": "a9ad512e1482461a5b500ee3fcf2d06ec9c7c7e8"
314
+ },
315
+ "dist": {
316
+ "type": "zip",
317
+ "url": "https://api.github.com/repos/zendframework/Component_ZendConfig/zipball/a9ad512e1482461a5b500ee3fcf2d06ec9c7c7e8",
318
+ "reference": "a9ad512e1482461a5b500ee3fcf2d06ec9c7c7e8",
319
+ "shasum": ""
320
+ },
321
+ "require": {
322
+ "php": ">=5.3.23",
323
+ "zendframework/zend-stdlib": "self.version"
324
+ },
325
+ "require-dev": {
326
+ "zendframework/zend-filter": "self.version",
327
+ "zendframework/zend-i18n": "self.version",
328
+ "zendframework/zend-json": "self.version",
329
+ "zendframework/zend-servicemanager": "self.version"
330
+ },
331
+ "suggest": {
332
+ "zendframework/zend-filter": "Zend\\Filter component",
333
+ "zendframework/zend-i18n": "Zend\\I18n component",
334
+ "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes",
335
+ "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances"
336
+ },
337
+ "time": "2014-09-16 22:58:11",
338
+ "type": "library",
339
+ "extra": {
340
+ "branch-alias": {
341
+ "dev-master": "2.3-dev",
342
+ "dev-develop": "2.4-dev"
343
+ }
344
+ },
345
+ "installation-source": "dist",
346
+ "autoload": {
347
+ "psr-0": {
348
+ "Zend\\Config\\": ""
349
+ }
350
+ },
351
+ "notification-url": "https://packagist.org/downloads/",
352
+ "license": [
353
+ "BSD-3-Clause"
354
+ ],
355
+ "description": "provides a nested object property based user interface for accessing this configuration data within application code",
356
+ "homepage": "https://github.com/zendframework/zf2",
357
+ "keywords": [
358
+ "config",
359
+ "zf2"
360
+ ]
361
+ },
362
+ {
363
+ "name": "zendframework/zend-json",
364
+ "version": "2.3.3",
365
+ "version_normalized": "2.3.3.0",
366
+ "target-dir": "Zend/Json",
367
+ "source": {
368
+ "type": "git",
369
+ "url": "https://github.com/zendframework/Component_ZendJson.git",
370
+ "reference": "4093e5a0a166a5d02532bac6e5671a7b21d203b5"
371
+ },
372
+ "dist": {
373
+ "type": "zip",
374
+ "url": "https://api.github.com/repos/zendframework/Component_ZendJson/zipball/4093e5a0a166a5d02532bac6e5671a7b21d203b5",
375
+ "reference": "4093e5a0a166a5d02532bac6e5671a7b21d203b5",
376
+ "shasum": ""
377
+ },
378
+ "require": {
379
+ "php": ">=5.3.23",
380
+ "zendframework/zend-stdlib": "self.version"
381
+ },
382
+ "require-dev": {
383
+ "zendframework/zend-http": "self.version",
384
+ "zendframework/zend-server": "self.version"
385
+ },
386
+ "suggest": {
387
+ "zendframework/zend-http": "Zend\\Http component",
388
+ "zendframework/zend-server": "Zend\\Server component"
389
+ },
390
+ "time": "2014-09-16 22:58:11",
391
+ "type": "library",
392
+ "extra": {
393
+ "branch-alias": {
394
+ "dev-master": "2.3-dev",
395
+ "dev-develop": "2.4-dev"
396
+ }
397
+ },
398
+ "installation-source": "dist",
399
+ "autoload": {
400
+ "psr-0": {
401
+ "Zend\\Json\\": ""
402
+ }
403
+ },
404
+ "notification-url": "https://packagist.org/downloads/",
405
+ "license": [
406
+ "BSD-3-Clause"
407
+ ],
408
+ "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP",
409
+ "homepage": "https://github.com/zendframework/zf2",
410
+ "keywords": [
411
+ "json",
412
+ "zf2"
413
+ ]
414
+ },
415
+ {
416
+ "name": "guzzlehttp/ringphp",
417
+ "version": "1.0.3",
418
+ "version_normalized": "1.0.3.0",
419
+ "source": {
420
+ "type": "git",
421
+ "url": "https://github.com/guzzle/RingPHP.git",
422
+ "reference": "e7c28f96c5ac12ab0e63412cfc15989756fcb964"
423
+ },
424
+ "dist": {
425
+ "type": "zip",
426
+ "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/e7c28f96c5ac12ab0e63412cfc15989756fcb964",
427
+ "reference": "e7c28f96c5ac12ab0e63412cfc15989756fcb964",
428
+ "shasum": ""
429
+ },
430
+ "require": {
431
+ "guzzlehttp/streams": "~3.0",
432
+ "php": ">=5.4.0",
433
+ "react/promise": "~2.0"
434
+ },
435
+ "require-dev": {
436
+ "ext-curl": "*",
437
+ "phpunit/phpunit": "~4.0"
438
+ },
439
+ "suggest": {
440
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
441
+ },
442
+ "time": "2014-11-04 07:01:14",
443
+ "type": "library",
444
+ "extra": {
445
+ "branch-alias": {
446
+ "dev-master": "1.0-dev"
447
+ }
448
+ },
449
+ "installation-source": "dist",
450
+ "autoload": {
451
+ "psr-4": {
452
+ "GuzzleHttp\\Ring\\": "src/"
453
+ }
454
+ },
455
+ "notification-url": "https://packagist.org/downloads/",
456
+ "license": [
457
+ "MIT"
458
+ ],
459
+ "authors": [
460
+ {
461
+ "name": "Michael Dowling",
462
+ "email": "mtdowling@gmail.com",
463
+ "homepage": "https://github.com/mtdowling"
464
+ }
465
+ ]
466
+ },
467
+ {
468
+ "name": "guzzlehttp/guzzle",
469
+ "version": "5.0.3",
470
+ "version_normalized": "5.0.3.0",
471
+ "source": {
472
+ "type": "git",
473
+ "url": "https://github.com/guzzle/guzzle.git",
474
+ "reference": "6c72627de1d66832e4270e36e56acdb0d1d8f282"
475
+ },
476
+ "dist": {
477
+ "type": "zip",
478
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/6c72627de1d66832e4270e36e56acdb0d1d8f282",
479
+ "reference": "6c72627de1d66832e4270e36e56acdb0d1d8f282",
480
+ "shasum": ""
481
+ },
482
+ "require": {
483
+ "guzzlehttp/ringphp": "~1.0",
484
+ "php": ">=5.4.0"
485
+ },
486
+ "require-dev": {
487
+ "ext-curl": "*",
488
+ "phpunit/phpunit": "~4.0",
489
+ "psr/log": "~1.0"
490
+ },
491
+ "time": "2014-11-04 07:09:15",
492
+ "type": "library",
493
+ "extra": {
494
+ "branch-alias": {
495
+ "dev-master": "5.0-dev"
496
+ }
497
+ },
498
+ "installation-source": "dist",
499
+ "autoload": {
500
+ "psr-4": {
501
+ "GuzzleHttp\\": "src/"
502
+ }
503
+ },
504
+ "notification-url": "https://packagist.org/downloads/",
505
+ "license": [
506
+ "MIT"
507
+ ],
508
+ "authors": [
509
+ {
510
+ "name": "Michael Dowling",
511
+ "email": "mtdowling@gmail.com",
512
+ "homepage": "https://github.com/mtdowling"
513
+ }
514
+ ],
515
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
516
+ "homepage": "http://guzzlephp.org/",
517
+ "keywords": [
518
+ "client",
519
+ "curl",
520
+ "framework",
521
+ "http",
522
+ "http client",
523
+ "rest",
524
+ "web service"
525
+ ]
526
+ }
527
+ ]
backend/vendor/guzzlehttp/guzzle/.gitignore ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ phpunit.xml
2
+ composer.phar
3
+ composer.lock
4
+ composer-test.lock
5
+ vendor/
6
+ build/artifacts/
7
+ artifacts/
8
+ docs/_build
9
+ docs/*.pyc
10
+ .idea
11
+ .DS_STORE
backend/vendor/guzzlehttp/guzzle/.travis.yml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+
3
+ php:
4
+ - 5.4
5
+ - 5.5
6
+ - 5.6
7
+ - hhvm
8
+
9
+ before_script:
10
+ - curl --version
11
+ - pear config-set php_ini ~/.phpenv/versions/`php -r 'echo phpversion();'`/etc/php.ini || echo 'Error modifying PEAR'
12
+ - pecl install uri_template || echo 'Error installing uri_template'
13
+ - composer self-update
14
+ - composer install --no-interaction --prefer-source --dev
15
+ - ~/.nvm/nvm.sh install v0.6.14
16
+ - ~/.nvm/nvm.sh run v0.6.14
17
+
18
+ script: make test
19
+
20
+ matrix:
21
+ allow_failures:
22
+ - php: hhvm
23
+ fast_finish: true
24
+
25
+ before_deploy:
26
+ - make package
27
+
28
+ deploy:
29
+ provider: releases
30
+ api_key:
31
+ secure: UpypqlYgsU68QT/x40YzhHXvzWjFwCNo9d+G8KAdm7U9+blFfcWhV1aMdzugvPMl6woXgvJj7qHq5tAL4v6oswCORhpSBfLgOQVFaica5LiHsvWlAedOhxGmnJqMTwuepjBCxXhs3+I8Kof1n4oUL9gKytXjOVCX/f7XU1HiinU=
32
+ file:
33
+ - build/artifacts/guzzle.phar
34
+ - build/artifacts/guzzle.zip
35
+ on:
36
+ repo: guzzle/guzzle
37
+ tags: true
38
+ all_branches: true
39
+ php: 5.4
backend/vendor/guzzlehttp/guzzle/CHANGELOG.md ADDED
@@ -0,0 +1,1013 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CHANGELOG
2
+
3
+ ## 5.0.3 - 2014-11-03
4
+
5
+ This change updates query strings so that they are treated as un-encoded values
6
+ by default where the value represents an un-encoded value to send over the
7
+ wire. A Query object then encodes the value before sending over the wire. This
8
+ means that even value query string values (e.g., ":") are url encoded. This
9
+ makes the Query class match PHP's http_build_query function. However, if you
10
+ want to send requests over the wire using valid query string characters that do
11
+ not need to be encoded, then you can provide a string to Url::setQuery() and
12
+ pass true as the second argument to specify that the query string is a raw
13
+ string that should not be parsed or encoded (unless a call to getQuery() is
14
+ subsequently made, forcing the query-string to be converted into a Query
15
+ object).
16
+
17
+ ## 5.0.2 - 2014-10-30
18
+
19
+ * Added a trailing `\r\n` to multipart/form-data payloads. See
20
+ https://github.com/guzzle/guzzle/pull/871
21
+ * Added a `GuzzleHttp\Pool::send()` convenience method to match the docs.
22
+ * Status codes are now returned as integers. See
23
+ https://github.com/guzzle/guzzle/issues/881
24
+ * No longer overwriting an existing `application/x-www-form-urlencoded` header
25
+ when sending POST requests, allowing for customized headers. See
26
+ https://github.com/guzzle/guzzle/issues/877
27
+ * Improved path URL serialization.
28
+
29
+ * No longer double percent-encoding characters in the path or query string if
30
+ they are already encoded.
31
+ * Now properly encoding the supplied path to a URL object, instead of only
32
+ encoding ' ' and '?'.
33
+ * Note: This has been changed in 5.0.3 to now encode query string values by
34
+ default unless the `rawString` argument is provided when setting the query
35
+ string on a URL: Now allowing many more characters to be present in the
36
+ query string without being percent encoded. See http://tools.ietf.org/html/rfc3986#appendix-A
37
+
38
+ ## 5.0.1 - 2014-10-16
39
+
40
+ Bugfix release.
41
+
42
+ * Fixed an issue where connection errors still returned response object in
43
+ error and end events event though the response is unusable. This has been
44
+ corrected so that a response is not returned in the `getResponse` method of
45
+ these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867
46
+ * Fixed an issue where transfer statistics were not being populated in the
47
+ RingBridge. https://github.com/guzzle/guzzle/issues/866
48
+
49
+ ## 5.0.0 - 2014-10-12
50
+
51
+ Adding support for non-blocking responses and some minor API cleanup.
52
+
53
+ ### New Features
54
+
55
+ * Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`.
56
+ * Added a public API for creating a default HTTP adapter.
57
+ * Updated the redirect plugin to be non-blocking so that redirects are sent
58
+ concurrently. Other plugins like this can now be updated to be non-blocking.
59
+ * Added a "progress" event so that you can get upload and download progress
60
+ events.
61
+ * Added `GuzzleHttp\Pool` which implements FutureInterface and transfers
62
+ requests concurrently using a capped pool size as efficiently as possible.
63
+ * Added `hasListeners()` to EmitterInterface.
64
+ * Removed `GuzzleHttp\ClientInterface::sendAll` and marked
65
+ `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the
66
+ recommended way).
67
+
68
+ ### Breaking changes
69
+
70
+ The breaking changes in this release are relatively minor. The biggest thing to
71
+ look out for is that request and response objects no longer implement fluent
72
+ interfaces.
73
+
74
+ * Removed the fluent interfaces (i.e., ``return $this``) from requests,
75
+ responses, ``GuzzleHttp\Collection``, ``GuzzleHttp\Url``,
76
+ ``GuzzleHttp\Query``, ``GuzzleHttp\Post\PostBody``, and
77
+ ``GuzzleHttp\Cookie\SetCookie``. This blog post provides a good outline of
78
+ why I did this: http://ocramius.github.io/blog/fluent-interfaces-are-evil/.
79
+ This also makes the Guzzle message interfaces compatible with the current
80
+ PSR-7 message proposal.
81
+ * Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except
82
+ for the HTTP request functions from function.php, these functions are now
83
+ implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode`
84
+ moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to
85
+ `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to
86
+ `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be
87
+ `GuzzleHttp\Pool::batch`, which returns a bjectStorage`. Using functions.php
88
+ caused problems for many users: they aren't PSR-4 compliant, require an
89
+ explicit include, and needed an if-guard to ensure that the functions are not
90
+ declared multiple times.
91
+ * Rewrote adapter layer.
92
+ * Removing all classes from `GuzzleHttp\Adapter`, these are now
93
+ implemented as callables that are stored in `GuzzleHttp\Ring\Client`.
94
+ * Removed the concept of "parallel adapters". Sending requests serially or
95
+ concurrently is now handled using a single adapter.
96
+ * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The
97
+ Transaction object now exposes the request, response, and client as public
98
+ properties. The getters and setters have been removed.
99
+ * Removed the "headers" event. This event was only useful for changing the
100
+ body a response once the headers of the response were known. You can implement
101
+ a similar behavior in a number of ways. One example might be to use a
102
+ FnStream that has access to the transaction being sent. For example, when the
103
+ first byte is written, you could check if the response headers match your
104
+ expectations, and if so, change the actual stream body that is being
105
+ written to.
106
+ * Removed the `asArray` parameter from
107
+ `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
108
+ value as an array, then use the newly added ``getHeaderAsArray()`` method of
109
+ ``MessageInterface``. This change makes the Guzzle interfaces compatible with
110
+ the PSR-7 interfaces.
111
+ * ``GuzzleHttp\Message\MessageFactory`` no longer allows subclasses to add
112
+ custom request options using double-dispatch (this was an implementation
113
+ detail). Instead, you should now provide an associative array to the
114
+ constructor which is a mapping of the request option name mapping to a
115
+ function that applies the option value to a request.
116
+ * Removed the concept of "throwImmediately" from exceptions and error events.
117
+ This control mechanism was used to stop a transfer of concurrent requests
118
+ from completing. This can now be handled by throwing the exception or by
119
+ cancelling a pool of requests or each outstanding future request individually.
120
+ * Updated to "GuzzleHttp\Streams" 3.0.
121
+ * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a
122
+ `maxLen` parameter. This update makes the Guzzle streams project
123
+ compatible with the current PSR-7 proposal.
124
+ * ``GuzzleHttp\Stream\Stream::__construct``,
125
+ ``GuzzleHttp\Stream\Stream::factory``, and
126
+ ``GuzzleHttp\Stream\Utils::create`` no longer accept a size in the second
127
+ argument. They now accept an associative array of options, including the
128
+ "size" key and "metadata" key which can be used to provide custom metadata.
129
+
130
+ ## 4.2.2 - 2014-09-08
131
+
132
+ * Fixed a memory leak in the CurlAdapter when reusing cURL handles.
133
+ * No longer using `request_fulluri` in stream adapter proxies.
134
+ * Relative redirects are now based on the last response, not the first response.
135
+
136
+ ## 4.2.1 - 2014-08-19
137
+
138
+ * Ensuring that the StreamAdapter does not always add a Content-Type header
139
+ * Adding automated github releases with a phar and zip
140
+
141
+ ## 4.2.0 - 2014-08-17
142
+
143
+ * Now merging in default options using a case-insensitive comparison.
144
+ Closes https://github.com/guzzle/guzzle/issues/767
145
+ * Added the ability to automatically decode `Content-Encoding` response bodies
146
+ using the `decode_content` request option. This is set to `true` by default
147
+ to decode the response body if it comes over the wire with a
148
+ `Content-Encoding`. Set this value to `false` to disable decoding the
149
+ response content, and pass a string to provide a request `Accept-Encoding`
150
+ header and turn on automatic response decoding. This feature now allows you
151
+ to pass an `Accept-Encoding` header in the headers of a request but still
152
+ disable automatic response decoding.
153
+ Closes https://github.com/guzzle/guzzle/issues/764
154
+ * Added the ability to throw an exception immediately when transferring
155
+ requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760
156
+ * Updating guzzlehttp/streams dependency to ~2.1
157
+ * No longer utilizing the now deprecated namespaced methods from the stream
158
+ package.
159
+
160
+ ## 4.1.8 - 2014-08-14
161
+
162
+ * Fixed an issue in the CurlFactory that caused setting the `stream=false`
163
+ request option to throw an exception.
164
+ See: https://github.com/guzzle/guzzle/issues/769
165
+ * TransactionIterator now calls rewind on the inner iterator.
166
+ See: https://github.com/guzzle/guzzle/pull/765
167
+ * You can now set the `Content-Type` header to `multipart/form-data`
168
+ when creating POST requests to force multipart bodies.
169
+ See https://github.com/guzzle/guzzle/issues/768
170
+
171
+ ## 4.1.7 - 2014-08-07
172
+
173
+ * Fixed an error in the HistoryPlugin that caused the same request and response
174
+ to be logged multiple times when an HTTP protocol error occurs.
175
+ * Ensuring that cURL does not add a default Content-Type when no Content-Type
176
+ has been supplied by the user. This prevents the adapter layer from modifying
177
+ the request that is sent over the wire after any listeners may have already
178
+ put the request in a desired state (e.g., signed the request).
179
+ * Throwing an exception when you attempt to send requests that have the
180
+ "stream" set to true in parallel using the MultiAdapter.
181
+ * Only calling curl_multi_select when there are active cURL handles. This was
182
+ previously changed and caused performance problems on some systems due to PHP
183
+ always selecting until the maximum select timeout.
184
+ * Fixed a bug where multipart/form-data POST fields were not correctly
185
+ aggregated (e.g., values with "&").
186
+
187
+ ## 4.1.6 - 2014-08-03
188
+
189
+ * Added helper methods to make it easier to represent messages as strings,
190
+ including getting the start line and getting headers as a string.
191
+
192
+ ## 4.1.5 - 2014-08-02
193
+
194
+ * Automatically retrying cURL "Connection died, retrying a fresh connect"
195
+ errors when possible.
196
+ * cURL implementation cleanup
197
+ * Allowing multiple event subscriber listeners to be registered per event by
198
+ passing an array of arrays of listener configuration.
199
+
200
+ ## 4.1.4 - 2014-07-22
201
+
202
+ * Fixed a bug that caused multi-part POST requests with more than one field to
203
+ serialize incorrectly.
204
+ * Paths can now be set to "0"
205
+ * `ResponseInterface::xml` now accepts a `libxml_options` option and added a
206
+ missing default argument that was required when parsing XML response bodies.
207
+ * A `save_to` stream is now created lazily, which means that files are not
208
+ created on disk unless a request succeeds.
209
+
210
+ ## 4.1.3 - 2014-07-15
211
+
212
+ * Various fixes to multipart/form-data POST uploads
213
+ * Wrapping function.php in an if-statement to ensure Guzzle can be used
214
+ globally and in a Composer install
215
+ * Fixed an issue with generating and merging in events to an event array
216
+ * POST headers are only applied before sending a request to allow you to change
217
+ the query aggregator used before uploading
218
+ * Added much more robust query string parsing
219
+ * Fixed various parsing and normalization issues with URLs
220
+ * Fixing an issue where multi-valued headers were not being utilized correctly
221
+ in the StreamAdapter
222
+
223
+ ## 4.1.2 - 2014-06-18
224
+
225
+ * Added support for sending payloads with GET requests
226
+
227
+ ## 4.1.1 - 2014-06-08
228
+
229
+ * Fixed an issue related to using custom message factory options in subclasses
230
+ * Fixed an issue with nested form fields in a multi-part POST
231
+ * Fixed an issue with using the `json` request option for POST requests
232
+ * Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar`
233
+
234
+ ## 4.1.0 - 2014-05-27
235
+
236
+ * Added a `json` request option to easily serialize JSON payloads.
237
+ * Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON.
238
+ * Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`.
239
+ * Added the ability to provide an emitter to a client in the client constructor.
240
+ * Added the ability to persist a cookie session using $_SESSION.
241
+ * Added a trait that can be used to add event listeners to an iterator.
242
+ * Removed request method constants from RequestInterface.
243
+ * Fixed warning when invalid request start-lines are received.
244
+ * Updated MessageFactory to work with custom request option methods.
245
+ * Updated cacert bundle to latest build.
246
+
247
+ 4.0.2 (2014-04-16)
248
+ ------------------
249
+
250
+ * Proxy requests using the StreamAdapter now properly use request_fulluri (#632)
251
+ * Added the ability to set scalars as POST fields (#628)
252
+
253
+ ## 4.0.1 - 2014-04-04
254
+
255
+ * The HTTP status code of a response is now set as the exception code of
256
+ RequestException objects.
257
+ * 303 redirects will now correctly switch from POST to GET requests.
258
+ * The default parallel adapter of a client now correctly uses the MultiAdapter.
259
+ * HasDataTrait now initializes the internal data array as an empty array so
260
+ that the toArray() method always returns an array.
261
+
262
+ ## 4.0.0 - 2014-03-29
263
+
264
+ * For more information on the 4.0 transition, see:
265
+ http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/
266
+ * For information on changes and upgrading, see:
267
+ https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
268
+ * Added `GuzzleHttp\batch()` as a convenience function for sending requests in
269
+ parallel without needing to write asynchronous code.
270
+ * Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`.
271
+ You can now pass a callable or an array of associative arrays where each
272
+ associative array contains the "fn", "priority", and "once" keys.
273
+
274
+ ## 4.0.0.rc-2 - 2014-03-25
275
+
276
+ * Removed `getConfig()` and `setConfig()` from clients to avoid confusion
277
+ around whether things like base_url, message_factory, etc. should be able to
278
+ be retrieved or modified.
279
+ * Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface
280
+ * functions.php functions were renamed using snake_case to match PHP idioms
281
+ * Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and
282
+ `GUZZLE_CURL_SELECT_TIMEOUT` environment variables
283
+ * Added the ability to specify custom `sendAll()` event priorities
284
+ * Added the ability to specify custom stream context options to the stream
285
+ adapter.
286
+ * Added a functions.php function for `get_path()` and `set_path()`
287
+ * CurlAdapter and MultiAdapter now use a callable to generate curl resources
288
+ * MockAdapter now properly reads a body and emits a `headers` event
289
+ * Updated Url class to check if a scheme and host are set before adding ":"
290
+ and "//". This allows empty Url (e.g., "") to be serialized as "".
291
+ * Parsing invalid XML no longer emits warnings
292
+ * Curl classes now properly throw AdapterExceptions
293
+ * Various performance optimizations
294
+ * Streams are created with the faster `Stream\create()` function
295
+ * Marked deprecation_proxy() as internal
296
+ * Test server is now a collection of static methods on a class
297
+
298
+ ## 4.0.0-rc.1 - 2014-03-15
299
+
300
+ * See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
301
+
302
+ ## 3.8.1 - 2014-01-28
303
+
304
+ * Bug: Always using GET requests when redirecting from a 303 response
305
+ * Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in
306
+ `Guzzle\Http\ClientInterface::setSslVerification()`
307
+ * Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL
308
+ * Bug: The body of a request can now be set to `"0"`
309
+ * Sending PHP stream requests no longer forces `HTTP/1.0`
310
+ * Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of
311
+ each sub-exception
312
+ * Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than
313
+ clobbering everything).
314
+ * Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators)
315
+ * Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`.
316
+ For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`.
317
+ * Now properly escaping the regular expression delimiter when matching Cookie domains.
318
+ * Network access is now disabled when loading XML documents
319
+
320
+ ## 3.8.0 - 2013-12-05
321
+
322
+ * Added the ability to define a POST name for a file
323
+ * JSON response parsing now properly walks additionalProperties
324
+ * cURL error code 18 is now retried automatically in the BackoffPlugin
325
+ * Fixed a cURL error when URLs contain fragments
326
+ * Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were
327
+ CurlExceptions
328
+ * CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e)
329
+ * Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS`
330
+ * Fixed a bug that was encountered when parsing empty header parameters
331
+ * UriTemplate now has a `setRegex()` method to match the docs
332
+ * The `debug` request parameter now checks if it is truthy rather than if it exists
333
+ * Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin
334
+ * Added the ability to combine URLs using strict RFC 3986 compliance
335
+ * Command objects can now return the validation errors encountered by the command
336
+ * Various fixes to cache revalidation (#437 and 29797e5)
337
+ * Various fixes to the AsyncPlugin
338
+ * Cleaned up build scripts
339
+
340
+ ## 3.7.4 - 2013-10-02
341
+
342
+ * Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430)
343
+ * Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp
344
+ (see https://github.com/aws/aws-sdk-php/issues/147)
345
+ * Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots
346
+ * Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420)
347
+ * Updated the bundled cacert.pem (#419)
348
+ * OauthPlugin now supports adding authentication to headers or query string (#425)
349
+
350
+ ## 3.7.3 - 2013-09-08
351
+
352
+ * Added the ability to get the exception associated with a request/command when using `MultiTransferException` and
353
+ `CommandTransferException`.
354
+ * Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description
355
+ * Schemas are only injected into response models when explicitly configured.
356
+ * No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of
357
+ an EntityBody.
358
+ * Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator.
359
+ * Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`.
360
+ * Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody()
361
+ * Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin
362
+ * Bug fix: Visiting XML attributes first before visting XML children when serializing requests
363
+ * Bug fix: Properly parsing headers that contain commas contained in quotes
364
+ * Bug fix: mimetype guessing based on a filename is now case-insensitive
365
+
366
+ ## 3.7.2 - 2013-08-02
367
+
368
+ * Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander
369
+ See https://github.com/guzzle/guzzle/issues/371
370
+ * Bug fix: Cookie domains are now matched correctly according to RFC 6265
371
+ See https://github.com/guzzle/guzzle/issues/377
372
+ * Bug fix: GET parameters are now used when calculating an OAuth signature
373
+ * Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted
374
+ * `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched
375
+ * `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input.
376
+ See https://github.com/guzzle/guzzle/issues/379
377
+ * Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See
378
+ https://github.com/guzzle/guzzle/pull/380
379
+ * cURL multi cleanup and optimizations
380
+
381
+ ## 3.7.1 - 2013-07-05
382
+
383
+ * Bug fix: Setting default options on a client now works
384
+ * Bug fix: Setting options on HEAD requests now works. See #352
385
+ * Bug fix: Moving stream factory before send event to before building the stream. See #353
386
+ * Bug fix: Cookies no longer match on IP addresses per RFC 6265
387
+ * Bug fix: Correctly parsing header parameters that are in `<>` and quotes
388
+ * Added `cert` and `ssl_key` as request options
389
+ * `Host` header can now diverge from the host part of a URL if the header is set manually
390
+ * `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter
391
+ * OAuth parameters are only added via the plugin if they aren't already set
392
+ * Exceptions are now thrown when a URL cannot be parsed
393
+ * Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails
394
+ * Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin
395
+
396
+ ## 3.7.0 - 2013-06-10
397
+
398
+ * See UPGRADING.md for more information on how to upgrade.
399
+ * Requests now support the ability to specify an array of $options when creating a request to more easily modify a
400
+ request. You can pass a 'request.options' configuration setting to a client to apply default request options to
401
+ every request created by a client (e.g. default query string variables, headers, curl options, etc.).
402
+ * Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`.
403
+ See `Guzzle\Http\StaticClient::mount`.
404
+ * Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
405
+ created by a command (e.g. custom headers, query string variables, timeout settings, etc.).
406
+ * Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the
407
+ headers of a response
408
+ * Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key
409
+ (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)
410
+ * ServiceBuilders now support storing and retrieving arbitrary data
411
+ * CachePlugin can now purge all resources for a given URI
412
+ * CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource
413
+ * CachePlugin now uses the Vary header to determine if a resource is a cache hit
414
+ * `Guzzle\Http\Message\Response` now implements `\Serializable`
415
+ * Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
416
+ * `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
417
+ * Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()`
418
+ * Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size
419
+ * `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message
420
+ * Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older
421
+ Symfony users can still use the old version of Monolog.
422
+ * Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`.
423
+ Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`.
424
+ * Several performance improvements to `Guzzle\Common\Collection`
425
+ * Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
426
+ createRequest, head, delete, put, patch, post, options, prepareRequest
427
+ * Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
428
+ * Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
429
+ * Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
430
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
431
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
432
+ * Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
433
+ default `array()`
434
+ * Added `Guzzle\Stream\StreamInterface::isRepeatable`
435
+ * Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
436
+ $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
437
+ $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`.
438
+ * Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.
439
+ * Removed `Guzzle\Http\ClientInterface::expandTemplate()`
440
+ * Removed `Guzzle\Http\ClientInterface::setRequestFactory()`
441
+ * Removed `Guzzle\Http\ClientInterface::getCurlMulti()`
442
+ * Removed `Guzzle\Http\Message\RequestInterface::canCache`
443
+ * Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`
444
+ * Removed `Guzzle\Http\Message\RequestInterface::isRedirect`
445
+ * Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
446
+ * You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting
447
+ `Guzzle\Common\Version::$emitWarnings` to true.
448
+ * Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use
449
+ `$request->getResponseBody()->isRepeatable()` instead.
450
+ * Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
451
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
452
+ * Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
453
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
454
+ * Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
455
+ * Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
456
+ * Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
457
+ * Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand.
458
+ These will work through Guzzle 4.0
459
+ * Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use [request.options][params].
460
+ * Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
461
+ * Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`.
462
+ * Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`.
463
+ * Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
464
+ * Marked `Guzzle\Common\Collection::inject()` as deprecated.
465
+ * Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');`
466
+ * CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
467
+ CacheStorageInterface. These two objects and interface will be removed in a future version.
468
+ * Always setting X-cache headers on cached responses
469
+ * Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
470
+ * `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
471
+ $request, Response $response);`
472
+ * `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
473
+ * `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
474
+ * Added `CacheStorageInterface::purge($url)`
475
+ * `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
476
+ $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
477
+ CanCacheStrategyInterface $canCache = null)`
478
+ * Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
479
+
480
+ ## 3.6.0 - 2013-05-29
481
+
482
+ * ServiceDescription now implements ToArrayInterface
483
+ * Added command.hidden_params to blacklist certain headers from being treated as additionalParameters
484
+ * Guzzle can now correctly parse incomplete URLs
485
+ * Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
486
+ * Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
487
+ * Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
488
+ * Specific header implementations can be created for complex headers. When a message creates a header, it uses a
489
+ HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
490
+ CacheControl header implementation.
491
+ * Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
492
+ * Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
493
+ * Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
494
+ Guzzle\Http\Curl\RequestMediator
495
+ * Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
496
+ * Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
497
+ * Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
498
+ * Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
499
+ * Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
500
+ * All response header helper functions return a string rather than mixing Header objects and strings inconsistently
501
+ * Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
502
+ directly via interfaces
503
+ * Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
504
+ but are a no-op until removed.
505
+ * Most classes that used to require a ``Guzzle\Service\Command\CommandInterface` typehint now request a
506
+ `Guzzle\Service\Command\ArrayCommandInterface`.
507
+ * Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
508
+ on a request while the request is still being transferred
509
+ * The ability to case-insensitively search for header values
510
+ * Guzzle\Http\Message\Header::hasExactHeader
511
+ * Guzzle\Http\Message\Header::raw. Use getAll()
512
+ * Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
513
+ instead.
514
+ * `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
515
+ * Added the ability to cast Model objects to a string to view debug information.
516
+
517
+ ## 3.5.0 - 2013-05-13
518
+
519
+ * Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times
520
+ * Bug: Better cleanup of one-time events accross the board (when an event is meant to fire once, it will now remove
521
+ itself from the EventDispatcher)
522
+ * Bug: `Guzzle\Log\MessageFormatter` now properly writes "total_time" and "connect_time" values
523
+ * Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too
524
+ * Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a
525
+ non-existent key
526
+ * Bug: All __call() method arguments are now required (helps with mocking frameworks)
527
+ * Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference
528
+ to help with refcount based garbage collection of resources created by sending a request
529
+ * Deprecating ZF1 cache and log adapters. These will be removed in the next major version.
530
+ * Deprecating `Response::getPreviousResponse()` (method signature still exists, but it'sdeprecated). Use the
531
+ HistoryPlugin for a history.
532
+ * Added a `responseBody` alias for the `response_body` location
533
+ * Refactored internals to no longer rely on Response::getRequest()
534
+ * HistoryPlugin can now be cast to a string
535
+ * HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests
536
+ and responses that are sent over the wire
537
+ * Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects
538
+
539
+ ## 3.4.3 - 2013-04-30
540
+
541
+ * Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response
542
+ * Added a check to re-extract the temp cacert bundle from the phar before sending each request
543
+
544
+ ## 3.4.2 - 2013-04-29
545
+
546
+ * Bug fix: Stream objects now work correctly with "a" and "a+" modes
547
+ * Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present
548
+ * Bug fix: AsyncPlugin no longer forces HEAD requests
549
+ * Bug fix: DateTime timezones are now properly handled when using the service description schema formatter
550
+ * Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails
551
+ * Setting a response on a request will write to the custom request body from the response body if one is specified
552
+ * LogPlugin now writes to php://output when STDERR is undefined
553
+ * Added the ability to set multiple POST files for the same key in a single call
554
+ * application/x-www-form-urlencoded POSTs now use the utf-8 charset by default
555
+ * Added the ability to queue CurlExceptions to the MockPlugin
556
+ * Cleaned up how manual responses are queued on requests (removed "queued_response" and now using request.before_send)
557
+ * Configuration loading now allows remote files
558
+
559
+ ## 3.4.1 - 2013-04-16
560
+
561
+ * Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti
562
+ handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost.
563
+ * Exceptions are now properly grouped when sending requests in parallel
564
+ * Redirects are now properly aggregated when a multi transaction fails
565
+ * Redirects now set the response on the original object even in the event of a failure
566
+ * Bug fix: Model names are now properly set even when using $refs
567
+ * Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax
568
+ * Added support for oauth_callback in OAuth signatures
569
+ * Added support for oauth_verifier in OAuth signatures
570
+ * Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection
571
+
572
+ ## 3.4.0 - 2013-04-11
573
+
574
+ * Bug fix: URLs are now resolved correctly based on http://tools.ietf.org/html/rfc3986#section-5.2. #289
575
+ * Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289
576
+ * Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263
577
+ * Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264.
578
+ * Bug fix: Added `number` type to service descriptions.
579
+ * Bug fix: empty parameters are removed from an OAuth signature
580
+ * Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header
581
+ * Bug fix: Fixed "array to string" error when validating a union of types in a service description
582
+ * Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream
583
+ * Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin.
584
+ * Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs.
585
+ * The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections.
586
+ * Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if
587
+ the Content-Type can be determined based on the entity body or the path of the request.
588
+ * Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder.
589
+ * Added support for a PSR-3 LogAdapter.
590
+ * Added a `command.after_prepare` event
591
+ * Added `oauth_callback` parameter to the OauthPlugin
592
+ * Added the ability to create a custom stream class when using a stream factory
593
+ * Added a CachingEntityBody decorator
594
+ * Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized.
595
+ * The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar.
596
+ * You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies
597
+ * POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This
598
+ means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use
599
+ POST fields or files (the latter is only used when emulating a form POST in the browser).
600
+ * Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest
601
+
602
+ ## 3.3.1 - 2013-03-10
603
+
604
+ * Added the ability to create PHP streaming responses from HTTP requests
605
+ * Bug fix: Running any filters when parsing response headers with service descriptions
606
+ * Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing
607
+ * Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across
608
+ response location visitors.
609
+ * Bug fix: Removed the possibility of creating configuration files with circular dependencies
610
+ * RequestFactory::create() now uses the key of a POST file when setting the POST file name
611
+ * Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set
612
+
613
+ ## 3.3.0 - 2013-03-03
614
+
615
+ * A large number of performance optimizations have been made
616
+ * Bug fix: Added 'wb' as a valid write mode for streams
617
+ * Bug fix: `Guzzle\Http\Message\Response::json()` now allows scalar values to be returned
618
+ * Bug fix: Fixed bug in `Guzzle\Http\Message\Response` where wrapping quotes were stripped from `getEtag()`
619
+ * BC: Removed `Guzzle\Http\Utils` class
620
+ * BC: Setting a service description on a client will no longer modify the client's command factories.
621
+ * BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using
622
+ the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
623
+ * BC: `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getSteamType()` are no longer converted to
624
+ lowercase
625
+ * Operation parameter objects are now lazy loaded internally
626
+ * Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses
627
+ * Added support for instantiating responseType=class responseClass classes. Classes must implement
628
+ `Guzzle\Service\Command\ResponseClassInterface`
629
+ * Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These
630
+ additional properties also support locations and can be used to parse JSON responses where the outermost part of the
631
+ JSON is an array
632
+ * Added support for nested renaming of JSON models (rename sentAs to name)
633
+ * CachePlugin
634
+ * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error
635
+ * Debug headers can now added to cached response in the CachePlugin
636
+
637
+ ## 3.2.0 - 2013-02-14
638
+
639
+ * CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients.
640
+ * URLs with no path no longer contain a "/" by default
641
+ * Guzzle\Http\QueryString does no longer manages the leading "?". This is now handled in Guzzle\Http\Url.
642
+ * BadResponseException no longer includes the full request and response message
643
+ * Adding setData() to Guzzle\Service\Description\ServiceDescriptionInterface
644
+ * Adding getResponseBody() to Guzzle\Http\Message\RequestInterface
645
+ * Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription
646
+ * Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list
647
+ * xmlEncoding can now be customized for the XML declaration of a XML service description operation
648
+ * Guzzle\Http\QueryString now uses Guzzle\Http\QueryAggregator\QueryAggregatorInterface objects to add custom value
649
+ aggregation and no longer uses callbacks
650
+ * The URL encoding implementation of Guzzle\Http\QueryString can now be customized
651
+ * Bug fix: Filters were not always invoked for array service description parameters
652
+ * Bug fix: Redirects now use a target response body rather than a temporary response body
653
+ * Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded
654
+ * Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives
655
+
656
+ ## 3.1.2 - 2013-01-27
657
+
658
+ * Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the
659
+ response body. For example, the XmlVisitor now parses the XML response into an array in the before() method.
660
+ * Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent
661
+ * CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444)
662
+ * Fixed a bug where redirect responses were not chained correctly using getPreviousResponse()
663
+ * Setting default headers on a client after setting the user-agent will not erase the user-agent setting
664
+
665
+ ## 3.1.1 - 2013-01-20
666
+
667
+ * Adding wildcard support to Guzzle\Common\Collection::getPath()
668
+ * Adding alias support to ServiceBuilder configs
669
+ * Adding Guzzle\Service\Resource\CompositeResourceIteratorFactory and cleaning up factory interface
670
+
671
+ ## 3.1.0 - 2013-01-12
672
+
673
+ * BC: CurlException now extends from RequestException rather than BadResponseException
674
+ * BC: Renamed Guzzle\Plugin\Cache\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse()
675
+ * Added getData to ServiceDescriptionInterface
676
+ * Added context array to RequestInterface::setState()
677
+ * Bug: Removing hard dependency on the BackoffPlugin from Guzzle\Http
678
+ * Bug: Adding required content-type when JSON request visitor adds JSON to a command
679
+ * Bug: Fixing the serialization of a service description with custom data
680
+ * Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing
681
+ an array of successful and failed responses
682
+ * Moved getPath from Guzzle\Service\Resource\Model to Guzzle\Common\Collection
683
+ * Added Guzzle\Http\IoEmittingEntityBody
684
+ * Moved command filtration from validators to location visitors
685
+ * Added `extends` attributes to service description parameters
686
+ * Added getModels to ServiceDescriptionInterface
687
+
688
+ ## 3.0.7 - 2012-12-19
689
+
690
+ * Fixing phar detection when forcing a cacert to system if null or true
691
+ * Allowing filename to be passed to `Guzzle\Http\Message\Request::setResponseBody()`
692
+ * Cleaning up `Guzzle\Common\Collection::inject` method
693
+ * Adding a response_body location to service descriptions
694
+
695
+ ## 3.0.6 - 2012-12-09
696
+
697
+ * CurlMulti performance improvements
698
+ * Adding setErrorResponses() to Operation
699
+ * composer.json tweaks
700
+
701
+ ## 3.0.5 - 2012-11-18
702
+
703
+ * Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin
704
+ * Bug: Response body can now be a string containing "0"
705
+ * Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert
706
+ * Bug: QueryString::fromString now properly parses query string parameters that contain equal signs
707
+ * Added support for XML attributes in service description responses
708
+ * DefaultRequestSerializer now supports array URI parameter values for URI template expansion
709
+ * Added better mimetype guessing to requests and post files
710
+
711
+ ## 3.0.4 - 2012-11-11
712
+
713
+ * Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value
714
+ * Bug: Cookies can now be added that have a name, domain, or value set to "0"
715
+ * Bug: Using the system cacert bundle when using the Phar
716
+ * Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures
717
+ * Enhanced cookie jar de-duplication
718
+ * Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added
719
+ * Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies
720
+ * Added the ability to create any sort of hash for a stream rather than just an MD5 hash
721
+
722
+ ## 3.0.3 - 2012-11-04
723
+
724
+ * Implementing redirects in PHP rather than cURL
725
+ * Added PECL URI template extension and using as default parser if available
726
+ * Bug: Fixed Content-Length parsing of Response factory
727
+ * Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams.
728
+ * Adding ToArrayInterface throughout library
729
+ * Fixing OauthPlugin to create unique nonce values per request
730
+
731
+ ## 3.0.2 - 2012-10-25
732
+
733
+ * Magic methods are enabled by default on clients
734
+ * Magic methods return the result of a command
735
+ * Service clients no longer require a base_url option in the factory
736
+ * Bug: Fixed an issue with URI templates where null template variables were being expanded
737
+
738
+ ## 3.0.1 - 2012-10-22
739
+
740
+ * Models can now be used like regular collection objects by calling filter, map, etc.
741
+ * Models no longer require a Parameter structure or initial data in the constructor
742
+ * Added a custom AppendIterator to get around a PHP bug with the `\AppendIterator`
743
+
744
+ ## 3.0.0 - 2012-10-15
745
+
746
+ * Rewrote service description format to be based on Swagger
747
+ * Now based on JSON schema
748
+ * Added nested input structures and nested response models
749
+ * Support for JSON and XML input and output models
750
+ * Renamed `commands` to `operations`
751
+ * Removed dot class notation
752
+ * Removed custom types
753
+ * Broke the project into smaller top-level namespaces to be more component friendly
754
+ * Removed support for XML configs and descriptions. Use arrays or JSON files.
755
+ * Removed the Validation component and Inspector
756
+ * Moved all cookie code to Guzzle\Plugin\Cookie
757
+ * Magic methods on a Guzzle\Service\Client now return the command un-executed.
758
+ * Calling getResult() or getResponse() on a command will lazily execute the command if needed.
759
+ * Now shipping with cURL's CA certs and using it by default
760
+ * Added previousResponse() method to response objects
761
+ * No longer sending Accept and Accept-Encoding headers on every request
762
+ * Only sending an Expect header by default when a payload is greater than 1MB
763
+ * Added/moved client options:
764
+ * curl.blacklist to curl.option.blacklist
765
+ * Added ssl.certificate_authority
766
+ * Added a Guzzle\Iterator component
767
+ * Moved plugins from Guzzle\Http\Plugin to Guzzle\Plugin
768
+ * Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin)
769
+ * Added a more robust caching plugin
770
+ * Added setBody to response objects
771
+ * Updating LogPlugin to use a more flexible MessageFormatter
772
+ * Added a completely revamped build process
773
+ * Cleaning up Collection class and removing default values from the get method
774
+ * Fixed ZF2 cache adapters
775
+
776
+ ## 2.8.8 - 2012-10-15
777
+
778
+ * Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did
779
+
780
+ ## 2.8.7 - 2012-09-30
781
+
782
+ * Bug: Fixed config file aliases for JSON includes
783
+ * Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests
784
+ * Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload
785
+ * Bug: Hardening request and response parsing to account for missing parts
786
+ * Bug: Fixed PEAR packaging
787
+ * Bug: Fixed Request::getInfo
788
+ * Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail
789
+ * Adding the ability for the namespace Iterator factory to look in multiple directories
790
+ * Added more getters/setters/removers from service descriptions
791
+ * Added the ability to remove POST fields from OAuth signatures
792
+ * OAuth plugin now supports 2-legged OAuth
793
+
794
+ ## 2.8.6 - 2012-09-05
795
+
796
+ * Added the ability to modify and build service descriptions
797
+ * Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command
798
+ * Added a `json` parameter location
799
+ * Now allowing dot notation for classes in the CacheAdapterFactory
800
+ * Using the union of two arrays rather than an array_merge when extending service builder services and service params
801
+ * Ensuring that a service is a string before doing strpos() checks on it when substituting services for references
802
+ in service builder config files.
803
+ * Services defined in two different config files that include one another will by default replace the previously
804
+ defined service, but you can now create services that extend themselves and merge their settings over the previous
805
+ * The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like
806
+ '_default' with a default JSON configuration file.
807
+
808
+ ## 2.8.5 - 2012-08-29
809
+
810
+ * Bug: Suppressed empty arrays from URI templates
811
+ * Bug: Added the missing $options argument from ServiceDescription::factory to enable caching
812
+ * Added support for HTTP responses that do not contain a reason phrase in the start-line
813
+ * AbstractCommand commands are now invokable
814
+ * Added a way to get the data used when signing an Oauth request before a request is sent
815
+
816
+ ## 2.8.4 - 2012-08-15
817
+
818
+ * Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin
819
+ * 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.
820
+ * Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\Common\Stream
821
+ * Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream
822
+ * Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5())
823
+ * Added additional response status codes
824
+ * Removed SSL information from the default User-Agent header
825
+ * DELETE requests can now send an entity body
826
+ * Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries
827
+ * Added the ability of the MockPlugin to consume mocked request bodies
828
+ * LogPlugin now exposes request and response objects in the extras array
829
+
830
+ ## 2.8.3 - 2012-07-30
831
+
832
+ * Bug: Fixed a case where empty POST requests were sent as GET requests
833
+ * Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body
834
+ * Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new
835
+ * Added multiple inheritance to service description commands
836
+ * Added an ApiCommandInterface and added ``getParamNames()`` and ``hasParam()``
837
+ * Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything
838
+ * Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles
839
+
840
+ ## 2.8.2 - 2012-07-24
841
+
842
+ * Bug: Query string values set to 0 are no longer dropped from the query string
843
+ * Bug: A Collection object is no longer created each time a call is made to ``Guzzle\Service\Command\AbstractCommand::getRequestHeaders()``
844
+ * Bug: ``+`` is now treated as an encoded space when parsing query strings
845
+ * QueryString and Collection performance improvements
846
+ * Allowing dot notation for class paths in filters attribute of a service descriptions
847
+
848
+ ## 2.8.1 - 2012-07-16
849
+
850
+ * Loosening Event Dispatcher dependency
851
+ * POST redirects can now be customized using CURLOPT_POSTREDIR
852
+
853
+ ## 2.8.0 - 2012-07-15
854
+
855
+ * BC: Guzzle\Http\Query
856
+ * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl)
857
+ * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding()
858
+ * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool)
859
+ * Changed the aggregation functions of QueryString to be static methods
860
+ * Can now use fromString() with querystrings that have a leading ?
861
+ * cURL configuration values can be specified in service descriptions using ``curl.`` prefixed parameters
862
+ * Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body
863
+ * Cookies are no longer URL decoded by default
864
+ * Bug: URI template variables set to null are no longer expanded
865
+
866
+ ## 2.7.2 - 2012-07-02
867
+
868
+ * BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\Http\Parser to Guzzle\Parser.
869
+ * BC: Removing Guzzle\Common\Batch\Batch::count() and replacing it with isEmpty()
870
+ * CachePlugin now allows for a custom request parameter function to check if a request can be cached
871
+ * Bug fix: CachePlugin now only caches GET and HEAD requests by default
872
+ * Bug fix: Using header glue when transferring headers over the wire
873
+ * Allowing deeply nested arrays for composite variables in URI templates
874
+ * Batch divisors can now return iterators or arrays
875
+
876
+ ## 2.7.1 - 2012-06-26
877
+
878
+ * Minor patch to update version number in UA string
879
+ * Updating build process
880
+
881
+ ## 2.7.0 - 2012-06-25
882
+
883
+ * BC: Inflection classes moved to Guzzle\Inflection. No longer static methods. Can now inject custom inflectors into classes.
884
+ * BC: Removed magic setX methods from commands
885
+ * BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method
886
+ * Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable.
887
+ * Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity)
888
+ * Guzzle\Service\Resource\ResourceIteratorApplyBatched now internally uses the Guzzle\Common\Batch namespace
889
+ * Added Guzzle\Service\Plugin namespace and a PluginCollectionPlugin
890
+ * Added the ability to set POST fields and files in a service description
891
+ * Guzzle\Http\EntityBody::factory() now accepts objects with a __toString() method
892
+ * Adding a command.before_prepare event to clients
893
+ * Added BatchClosureTransfer and BatchClosureDivisor
894
+ * BatchTransferException now includes references to the batch divisor and transfer strategies
895
+ * Fixed some tests so that they pass more reliably
896
+ * Added Guzzle\Common\Log\ArrayLogAdapter
897
+
898
+ ## 2.6.6 - 2012-06-10
899
+
900
+ * BC: Removing Guzzle\Http\Plugin\BatchQueuePlugin
901
+ * BC: Removing Guzzle\Service\Command\CommandSet
902
+ * Adding generic batching system (replaces the batch queue plugin and command set)
903
+ * Updating ZF cache and log adapters and now using ZF's composer repository
904
+ * Bug: Setting the name of each ApiParam when creating through an ApiCommand
905
+ * Adding result_type, result_doc, deprecated, and doc_url to service descriptions
906
+ * Bug: Changed the default cookie header casing back to 'Cookie'
907
+
908
+ ## 2.6.5 - 2012-06-03
909
+
910
+ * BC: Renaming Guzzle\Http\Message\RequestInterface::getResourceUri() to getResource()
911
+ * BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from
912
+ * BC: Guzzle\Http\Cookie is now used to manage Set-Cookie data, not Cookie data
913
+ * BC: Renaming methods in the CookieJarInterface
914
+ * Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations
915
+ * Making the default glue for HTTP headers ';' instead of ','
916
+ * Adding a removeValue to Guzzle\Http\Message\Header
917
+ * Adding getCookies() to request interface.
918
+ * Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber()
919
+
920
+ ## 2.6.4 - 2012-05-30
921
+
922
+ * BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class.
923
+ * BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand
924
+ * Bug: Fixing magic method command calls on clients
925
+ * Bug: Email constraint only validates strings
926
+ * Bug: Aggregate POST fields when POST files are present in curl handle
927
+ * Bug: Fixing default User-Agent header
928
+ * Bug: Only appending or prepending parameters in commands if they are specified
929
+ * Bug: Not requiring response reason phrases or status codes to match a predefined list of codes
930
+ * Allowing the use of dot notation for class namespaces when using instance_of constraint
931
+ * Added any_match validation constraint
932
+ * Added an AsyncPlugin
933
+ * Passing request object to the calculateWait method of the ExponentialBackoffPlugin
934
+ * Allowing the result of a command object to be changed
935
+ * Parsing location and type sub values when instantiating a service description rather than over and over at runtime
936
+
937
+ ## 2.6.3 - 2012-05-23
938
+
939
+ * [BC] Guzzle\Common\FromConfigInterface no longer requires any config options.
940
+ * [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields.
941
+ * You can now use an array of data when creating PUT request bodies in the request factory.
942
+ * Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable.
943
+ * [Http] Adding support for Content-Type in multipart POST uploads per upload
944
+ * [Http] Added support for uploading multiple files using the same name (foo[0], foo[1])
945
+ * Adding more POST data operations for easier manipulation of POST data.
946
+ * You can now set empty POST fields.
947
+ * The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files.
948
+ * Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate.
949
+ * CS updates
950
+
951
+ ## 2.6.2 - 2012-05-19
952
+
953
+ * [Http] Better handling of nested scope requests in CurlMulti. Requests are now always prepares in the send() method rather than the addRequest() method.
954
+
955
+ ## 2.6.1 - 2012-05-19
956
+
957
+ * [BC] Removing 'path' support in service descriptions. Use 'uri'.
958
+ * [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache.
959
+ * [BC] Removing Guzzle\Common\NullObject. Use https://github.com/mtdowling/NullObject if you need it.
960
+ * [BC] Removing Guzzle\Common\XmlElement.
961
+ * All commands, both dynamic and concrete, have ApiCommand objects.
962
+ * Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits.
963
+ * Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored.
964
+ * Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible.
965
+
966
+ ## 2.6.0 - 2012-05-15
967
+
968
+ * [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder
969
+ * [BC] Executing a Command returns the result of the command rather than the command
970
+ * [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed.
971
+ * [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args.
972
+ * [BC] Moving ResourceIterator* to Guzzle\Service\Resource
973
+ * [BC] Completely refactored ResourceIterators to iterate over a cloned command object
974
+ * [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate
975
+ * [BC] Guzzle\Guzzle is now deprecated
976
+ * Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject
977
+ * Adding Guzzle\Version class to give version information about Guzzle
978
+ * Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate()
979
+ * Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data
980
+ * ServiceDescription and ServiceBuilder are now cacheable using similar configs
981
+ * Changing the format of XML and JSON service builder configs. Backwards compatible.
982
+ * Cleaned up Cookie parsing
983
+ * Trimming the default Guzzle User-Agent header
984
+ * Adding a setOnComplete() method to Commands that is called when a command completes
985
+ * Keeping track of requests that were mocked in the MockPlugin
986
+ * Fixed a caching bug in the CacheAdapterFactory
987
+ * Inspector objects can be injected into a Command object
988
+ * Refactoring a lot of code and tests to be case insensitive when dealing with headers
989
+ * Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL
990
+ * Adding the ability to set global option overrides to service builder configs
991
+ * Adding the ability to include other service builder config files from within XML and JSON files
992
+ * Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method.
993
+
994
+ ## 2.5.0 - 2012-05-08
995
+
996
+ * Major performance improvements
997
+ * [BC] Simplifying Guzzle\Common\Collection. Please check to see if you are using features that are now deprecated.
998
+ * [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component.
999
+ * [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates. Use "{}"
1000
+ * Added the ability to passed parameters to all requests created by a client
1001
+ * Added callback functionality to the ExponentialBackoffPlugin
1002
+ * Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies.
1003
+ * Rewinding request stream bodies when retrying requests
1004
+ * Exception is thrown when JSON response body cannot be decoded
1005
+ * Added configurable magic method calls to clients and commands. This is off by default.
1006
+ * Fixed a defect that added a hash to every parsed URL part
1007
+ * Fixed duplicate none generation for OauthPlugin.
1008
+ * Emitting an event each time a client is generated by a ServiceBuilder
1009
+ * Using an ApiParams object instead of a Collection for parameters of an ApiCommand
1010
+ * cache.* request parameters should be renamed to params.cache.*
1011
+ * Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle.
1012
+ * Added the ability to disable type validation of service descriptions
1013
+ * ServiceDescriptions and ServiceBuilders are now Serializable
backend/vendor/guzzlehttp/guzzle/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.
backend/vendor/guzzlehttp/guzzle/Makefile ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ all: clean coverage docs
2
+
3
+ start-server:
4
+ cd vendor/guzzlehttp/ringphp && make start-server
5
+
6
+ stop-server:
7
+ cd vendor/guzzlehttp/ringphp && make stop-server
8
+
9
+ test: start-server
10
+ vendor/bin/phpunit
11
+ $(MAKE) stop-server
12
+
13
+ coverage: start-server
14
+ vendor/bin/phpunit --coverage-html=artifacts/coverage
15
+ $(MAKE) stop-server
16
+
17
+ view-coverage:
18
+ open artifacts/coverage/index.html
19
+
20
+ clean:
21
+ rm -rf artifacts/*
22
+
23
+ docs:
24
+ cd docs && make html && cd ..
25
+
26
+ view-docs:
27
+ open docs/_build/html/index.html
28
+
29
+ tag:
30
+ $(if $(TAG),,$(error TAG is not defined. Pass via "make tag TAG=4.2.1"))
31
+ @echo Tagging $(TAG)
32
+ chag update $(TAG)
33
+ sed -i '' -e "s/VERSION = '.*'/VERSION = '$(TAG)'/" src/ClientInterface.php
34
+ php -l src/ClientInterface.php
35
+ git add -A
36
+ git commit -m '$(TAG) release'
37
+ chag tag
38
+
39
+ perf: start-server
40
+ php tests/perf.php
41
+ $(MAKE) stop-server
42
+
43
+ package: burgomaster
44
+ php build/packager.php
45
+
46
+ burgomaster:
47
+ mkdir -p build/artifacts
48
+ curl -s https://raw.githubusercontent.com/mtdowling/Burgomaster/0.0.2/src/Burgomaster.php > build/artifacts/Burgomaster.php
49
+
50
+ .PHONY: docs burgomaster
backend/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.png?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 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/.
backend/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 `GuzzleHttl\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 additonal 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.
backend/vendor/guzzlehttp/guzzle/build/packager.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require __DIR__ . '/artifacts/Burgomaster.php';
3
+
4
+ $stageDirectory = __DIR__ . '/artifacts/staging';
5
+ $projectRoot = __DIR__ . '/../';
6
+ $packager = new \Burgomaster($stageDirectory, $projectRoot);
7
+
8
+ // Copy basic files to the stage directory. Note that we have chdir'd onto
9
+ // the $projectRoot directory, so use relative paths.
10
+ foreach (['README.md', 'LICENSE'] as $file) {
11
+ $packager->deepCopy($file, $file);
12
+ }
13
+
14
+ // Copy each dependency to the staging directory. Copy *.php and *.pem files.
15
+ $packager->recursiveCopy('src', 'GuzzleHttp', ['php']);
16
+ $packager->recursiveCopy('vendor/react/promise/src', '');
17
+ $packager->recursiveCopy('vendor/guzzlehttp/ringphp/src', 'GuzzleHttp/Ring');
18
+ $packager->recursiveCopy('vendor/guzzlehttp/streams/src', 'GuzzleHttp/Stream');
19
+ $packager->createAutoloader(['React/Promise/functions.php']);
20
+ $packager->createPhar(__DIR__ . '/artifacts/guzzle.phar');
21
+ $packager->createZip(__DIR__ . '/artifacts/guzzle.zip');
backend/vendor/guzzlehttp/guzzle/composer.json ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.0"
18
+ },
19
+ "require-dev": {
20
+ "ext-curl": "*",
21
+ "psr/log": "~1.0",
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
+ "extra": {
35
+ "branch-alias": {
36
+ "dev-master": "5.0-dev"
37
+ }
38
+ }
39
+ }
backend/vendor/guzzlehttp/guzzle/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/Guzzle.qhcp"
81
+ @echo "To view the help file:"
82
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Guzzle.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/Guzzle"
90
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Guzzle"
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."
backend/vendor/guzzlehttp/guzzle/docs/_static/guzzle-icon.png ADDED
Binary file
backend/vendor/guzzlehttp/guzzle/docs/_static/logo.png ADDED
Binary file
backend/vendor/guzzlehttp/guzzle/docs/_templates/nav_links.html ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <li><a href="https://github.com/guzzle/guzzle">GitHub</a></li>
2
+ <li><a href="https://groups.google.com/forum/?hl=en#!forum/guzzle">Forum</a></li>
3
+ <li><a href="irc:irc.freenode.com/#guzzlephp">IRC</a></li>
backend/vendor/guzzlehttp/guzzle/docs/clients.rst ADDED
@@ -0,0 +1,1298 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =======
2
+ Clients
3
+ =======
4
+
5
+ Clients are used to create requests, create transactions, send requests
6
+ through an HTTP handler, and return a response. You can add default request
7
+ options to a client that are applied to every request (e.g., default headers,
8
+ default query string parameters, etc.), and you can add event listeners and
9
+ subscribers to every request created by a client.
10
+
11
+ Creating a client
12
+ =================
13
+
14
+ The constructor of a client accepts an associative array of configuration
15
+ options.
16
+
17
+ base_url
18
+ Configures a base URL for the client so that requests created
19
+ using a relative URL are combined with the ``base_url`` of the client
20
+ according to section `5.2 of RFC 3986 <http://tools.ietf.org/html/rfc3986#section-5.2>`_.
21
+
22
+ .. code-block:: php
23
+
24
+ // Create a client with a base URL
25
+ $client = new GuzzleHttp\Client(['base_url' => 'https://github.com']);
26
+ // Send a request to https://github.com/notifications
27
+ $response = $client->get('/notifications');
28
+
29
+ `Absolute URLs <http://tools.ietf.org/html/rfc3986#section-4.3>`_ sent
30
+ through a client will not use the base URL of the client.
31
+
32
+ handler
33
+ Configures the `RingPHP handler <http://ringphp.readthedocs.org>`_
34
+ used to transfer the HTTP requests of a client. Guzzle will, by default,
35
+ utilize a stacked handlers that chooses the best handler to use based on the
36
+ provided request options and based on the extensions available in the
37
+ environment.
38
+
39
+ message_factory
40
+ Specifies the factory used to create HTTP requests and responses
41
+ (``GuzzleHttp\Message\MessageFactoryInterface``).
42
+
43
+ defaults
44
+ Associative array of :ref:`request-options` that are applied to every
45
+ request created by the client. This allows you to specify things like
46
+ default headers (e.g., User-Agent), default query string parameters, SSL
47
+ configurations, and any other supported request options.
48
+
49
+ emitter
50
+ Specifies an event emitter (``GuzzleHttp\Event\EmitterInterface``) instance
51
+ to be used by the client to emit request events. This option is useful if
52
+ you need to inject an emitter with listeners/subscribers already attached.
53
+
54
+ Here's an example of creating a client with various options.
55
+
56
+ .. code-block:: php
57
+
58
+ use GuzzleHttp\Client;
59
+
60
+ $client = new Client([
61
+ 'base_url' => ['https://api.twitter.com/{version}/', ['version' => 'v1.1']],
62
+ 'defaults' => [
63
+ 'headers' => ['Foo' => 'Bar'],
64
+ 'query' => ['testing' => '123'],
65
+ 'auth' => ['username', 'password'],
66
+ 'proxy' => 'tcp://localhost:80'
67
+ ]
68
+ ]);
69
+
70
+ Sending Requests
71
+ ================
72
+
73
+ Requests can be created using various methods of a client. You can create
74
+ **and** send requests using one of the following methods:
75
+
76
+ - ``GuzzleHttp\Client::get``: Sends a GET request.
77
+ - ``GuzzleHttp\Client::head``: Sends a HEAD request
78
+ - ``GuzzleHttp\Client::post``: Sends a POST request
79
+ - ``GuzzleHttp\Client::put``: Sends a PUT request
80
+ - ``GuzzleHttp\Client::delete``: Sends a DELETE request
81
+ - ``GuzzleHttp\Client::options``: Sends an OPTIONS request
82
+
83
+ Each of the above methods accepts a URL as the first argument and an optional
84
+ associative array of :ref:`request-options` as the second argument.
85
+
86
+ Synchronous Requests
87
+ --------------------
88
+
89
+ Guzzle sends synchronous (blocking) requests when the ``future`` request option
90
+ is not specified. This means that the request will complete immediately, and if
91
+ an error is encountered, a ``GuzzleHttp\Exception\RequestException`` will be
92
+ thrown.
93
+
94
+ .. code-block:: php
95
+
96
+ $client = new GuzzleHttp\Client();
97
+
98
+ $client->put('http://httpbin.org', [
99
+ 'headers' => ['X-Foo' => 'Bar'],
100
+ 'body' => 'this is the body!',
101
+ 'save_to' => '/path/to/local/file',
102
+ 'allow_redirects' => false,
103
+ 'timeout' => 5
104
+ ]);
105
+
106
+ Synchronous Error Handling
107
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
108
+
109
+ When a recoverable error is encountered while calling the ``send()`` method of
110
+ a client, a ``GuzzleHttp\Exception\RequestException`` is thrown.
111
+
112
+ .. code-block:: php
113
+
114
+ use GuzzleHttp\Client;
115
+ use GuzzleHttp\Exception\RequestException;
116
+
117
+ $client = new Client();
118
+
119
+ try {
120
+ $client->get('http://httpbin.org');
121
+ } catch (RequestException $e) {
122
+ echo $e->getRequest() . "\n";
123
+ if ($e->hasResponse()) {
124
+ echo $e->getResponse() . "\n";
125
+ }
126
+ }
127
+
128
+ ``GuzzleHttp\Exception\RequestException`` always contains a
129
+ ``GuzzleHttp\Message\RequestInterface`` object that can be accessed using the
130
+ exception's ``getRequest()`` method.
131
+
132
+ A response might be present in the exception. In the event of a networking
133
+ error, no response will be received. You can check if a ``RequestException``
134
+ has a response using the ``hasResponse()`` method. If the exception has a
135
+ response, then you can access the associated
136
+ ``GuzzleHttp\Message\ResponseInterface`` using the ``getResponse()`` method of
137
+ the exception.
138
+
139
+ Asynchronous Requests
140
+ ---------------------
141
+
142
+ You can send asynchronous requests by setting the ``future`` request option
143
+ to ``true`` (or a string that your handler understands). This creates a
144
+ ``GuzzleHttp\Message\FutureResponse`` object that has not yet completed. Once
145
+ you have a future response, you can use a promise object obtained by calling
146
+ the ``then`` method of the response to take an action when the response has
147
+ completed or encounters an error.
148
+
149
+ .. code-block:: php
150
+
151
+ $response = $client->put('http://httpbin.org/get', ['future' => true]);
152
+
153
+ // Call the function when the response completes
154
+ $response->then(function ($response) {
155
+ echo $response->getStatusCode();
156
+ });
157
+
158
+ You can call the ``wait()`` method of a future response to block until it has
159
+ completed. You also use a future response object just like a normal response
160
+ object by accessing the methods of the response. Using a future response like a
161
+ normal response object, also known as *dereferencing*, will block until the
162
+ response has completed.
163
+
164
+ .. code-block:: php
165
+
166
+ $response = $client->put('http://httpbin.org/get', ['future' => true]);
167
+
168
+ // Block until the response has completed
169
+ echo $response->getStatusCode();
170
+
171
+ .. important::
172
+
173
+ If an exception occurred while transferring the future response, then the
174
+ exception encountered will be thrown when dereferencing.
175
+
176
+ Asynchronous Error Handling
177
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
178
+
179
+ Handling errors with future response object promises is a bit different. When
180
+ using a promise, exceptions are forwarded to the ``$onError`` function provided
181
+ to the second argument of the ``then()`` function.
182
+
183
+ .. code-block:: php
184
+
185
+ $response = $client->put('http://httpbin.org/get', ['future' => true]);
186
+
187
+ $response
188
+ ->then(
189
+ function ($response) {
190
+ // This is called when the request succeeded
191
+ echo 'Success: ' . $response->getStatusCode();
192
+ // Returning a value will forward the value to the next promise
193
+ // in the chain.
194
+ return $response;
195
+ },
196
+ function ($error) {
197
+ // This is called when the exception failed.
198
+ echo 'Exception: ' . $error->getMessage();
199
+ // Throwing will "forward" the exception to the next promise
200
+ // in the chain.
201
+ throw $error;
202
+ }
203
+ )
204
+ ->then(
205
+ function($response) {
206
+ // This is called after the first promise in the chain. It
207
+ // receives the value returned from the first promise.
208
+ echo $response->getReasonPhrase();
209
+ },
210
+ function ($error) {
211
+ // This is called if the first promise error handler in the
212
+ // chain rethrows the exception.
213
+ echo 'Error: ' . $error->getMessage();
214
+ }
215
+ );
216
+
217
+ Please see the `React/Promises project documentation <https://github.com/reactphp/promise>`_
218
+ for more information on how promise resolution and rejection forwarding works.
219
+
220
+ HTTP Errors
221
+ -----------
222
+
223
+ If the ``exceptions`` request option is not set to ``false``, then exceptions
224
+ are thrown for HTTP protocol errors as well:
225
+ ``GuzzleHttp\Exception\ClientErrorResponseException`` for 4xx level HTTP
226
+ responses and ``GuzzleHttp\Exception\ServerException`` for 5xx level responses,
227
+ both of which extend from ``GuzzleHttp\Exception\BadResponseException``.
228
+
229
+ Creating Requests
230
+ -----------------
231
+
232
+ You can create a request without sending it. This is useful for building up
233
+ requests over time or sending requests in concurrently.
234
+
235
+ .. code-block:: php
236
+
237
+ $request = $client->createRequest('GET', 'http://httpbin.org', [
238
+ 'headers' => ['X-Foo' => 'Bar']
239
+ ]);
240
+
241
+ // Modify the request as needed
242
+ $request->setHeader('Baz', 'bar');
243
+
244
+ After creating a request, you can send it with the client's ``send()`` method.
245
+
246
+ .. code-block:: php
247
+
248
+ $response = $client->send($request);
249
+
250
+ Sending Requests With a Pool
251
+ ============================
252
+
253
+ You can send requests concurrently using a fixed size pool via the
254
+ ``GuzzleHttp\Pool`` class. The Pool class is an implementation of
255
+ ``GuzzleHttp\Ring\Future\FutureInterface``, meaning it can be dereferenced at a
256
+ later time or cancelled before sending. The Pool constructor accepts a client
257
+ object, iterator or array that yields ``GuzzleHttp\Message\RequestInterface``
258
+ objects, and an optional associative array of options that can be used to
259
+ affect the transfer.
260
+
261
+ .. code-block:: php
262
+
263
+ use GuzzleHttp\Pool;
264
+
265
+ $requests = [
266
+ $client->createRequest('GET', 'http://httpbin.org'),
267
+ $client->createRequest('DELETE', 'http://httpbin.org/delete'),
268
+ $client->createRequest('PUT', 'http://httpbin.org/put', ['body' => 'test'])
269
+ ];
270
+
271
+ $options = [];
272
+
273
+ // Create a pool. Note: the options array is optional.
274
+ $pool = new Pool($client, $requests, $options);
275
+
276
+ // Send the requests
277
+ $pool->wait();
278
+
279
+ The Pool constructor accepts the following associative array of options:
280
+
281
+ - **pool_size**: Integer representing the maximum number of requests that are
282
+ allowed to be sent concurrently.
283
+ - **before**: Callable or array representing the event listeners to add to
284
+ each request's :ref:`before_event` event.
285
+ - **complete**: Callable or array representing the event listeners to add to
286
+ each request's :ref:`complete_event` event.
287
+ - **error**: Callable or array representing the event listeners to add to
288
+ each request's :ref:`error_event` event.
289
+ - **end**: Callable or array representing the event listeners to add to
290
+ each request's :ref:`end_event` event.
291
+
292
+ The "before", "complete", "error", and "end" event options accept a callable or
293
+ an array of associative arrays where each associative array contains a "fn" key
294
+ with a callable value, an optional "priority" key representing the event
295
+ priority (with a default value of 0), and an optional "once" key that can be
296
+ set to true so that the event listener will be removed from the request after
297
+ it is first triggered.
298
+
299
+ .. code-block:: php
300
+
301
+ use GuzzleHttp\Pool;
302
+ use GuzzleHttp\Event\CompleteEvent;
303
+
304
+ // Add a single event listener using a callable.
305
+ Pool::send($client, $requests, [
306
+ 'complete' => function (CompleteEvent $event) {
307
+ echo 'Completed request to ' . $event->getRequest()->getUrl() . "\n";
308
+ echo 'Response: ' . $event->getResponse()->getBody() . "\n\n";
309
+ }
310
+ ]);
311
+
312
+ // The above is equivalent to the following, but the following structure
313
+ // allows you to add multiple event listeners to the same event name.
314
+ Pool::send($client, $requests, [
315
+ 'complete' => [
316
+ [
317
+ 'fn' => function (CompleteEvent $event) { /* ... */ },
318
+ 'priority' => 0, // Optional
319
+ 'once' => false // Optional
320
+ ]
321
+ ]
322
+ ]);
323
+
324
+ Asynchronous Response Handling
325
+ ------------------------------
326
+
327
+ When sending requests concurrently using a pool, the request/response/error
328
+ lifecycle must be handled asynchronously. This means that you give the Pool
329
+ multiple requests and handle the response or errors that is associated with the
330
+ request using event callbacks.
331
+
332
+ .. code-block:: php
333
+
334
+ use GuzzleHttp\Pool;
335
+ use GuzzleHttp\Event\ErrorEvent;
336
+
337
+ Pool::send($client, $requests, [
338
+ 'complete' => function (CompleteEvent $event) {
339
+ echo 'Completed request to ' . $event->getRequest()->getUrl() . "\n";
340
+ echo 'Response: ' . $event->getResponse()->getBody() . "\n\n";
341
+ // Do something with the completion of the request...
342
+ },
343
+ 'error' => function (ErrorEvent $event) {
344
+ echo 'Request failed: ' . $event->getRequest()->getUrl() . "\n";
345
+ echo $event->getException();
346
+ // Do something to handle the error...
347
+ }
348
+ ]);
349
+
350
+ The ``GuzzleHttp\Event\ErrorEvent`` event object is emitted when an error
351
+ occurs during a transfer. With this event, you have access to the request that
352
+ was sent, the response that was received (if one was received), access to
353
+ transfer statistics, and the ability to intercept the exception with a
354
+ different ``GuzzleHttp\Message\ResponseInterface`` object. See :doc:`events`
355
+ for more information.
356
+
357
+ Handling Errors After Transferring
358
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
359
+
360
+ It sometimes might be easier to handle all of the errors that occurred during a
361
+ transfer after all of the requests have been sent. Here we are adding each
362
+ failed request to an array that we can use to process errors later.
363
+
364
+ .. code-block:: php
365
+
366
+ use GuzzleHttp\Pool;
367
+ use GuzzleHttp\Event\ErrorEvent;
368
+
369
+ $errors = [];
370
+ Pool::send($client, $requests, [
371
+ 'error' => function (ErrorEvent $event) use (&$errors) {
372
+ $errors[] = $event;
373
+ }
374
+ ]);
375
+
376
+ foreach ($errors as $error) {
377
+ // Handle the error...
378
+ }
379
+
380
+ .. _batch-requests:
381
+
382
+ Batching Requests
383
+ -----------------
384
+
385
+ Sometimes you just want to send a few requests concurrently and then process
386
+ the results all at once after they've been sent. Guzzle provides a convenience
387
+ function ``GuzzleHttp\Pool::batch()`` that makes this very simple:
388
+
389
+ .. code-block:: php
390
+
391
+ use GuzzleHttp\Pool;
392
+ use GuzzleHttp\Client;
393
+
394
+ $client = new Client();
395
+
396
+ $requests = [
397
+ $client->createRequest('GET', 'http://httpbin.org/get'),
398
+ $client->createRequest('HEAD', 'http://httpbin.org/get'),
399
+ $client->createRequest('PUT', 'http://httpbin.org/put'),
400
+ ];
401
+
402
+ // Results is a GuzzleHttp\BatchResults object.
403
+ $results = Pool::batch($client, $requests);
404
+
405
+ // Can be accessed by index.
406
+ echo $results[0]->getStatusCode();
407
+
408
+ // Can be accessed by request.
409
+ echo $results->getResult($requests[0])->getStatusCode();
410
+
411
+ // Retrieve all successful responses
412
+ foreach ($results->getSuccessful() as $response) {
413
+ echo $response->getStatusCode() . "\n";
414
+ }
415
+
416
+ // Retrieve all failures.
417
+ foreach ($results->getFailures() as $requestException) {
418
+ echo $requestException->getMessage() . "\n";
419
+ }
420
+
421
+ ``GuzzleHttp\Pool::batch()`` accepts an optional associative array of options
422
+ in the third argument that allows you to specify the 'before', 'complete',
423
+ 'error', and 'end' events as well as specify the maximum number of requests to
424
+ send concurrently using the 'pool_size' option key.
425
+
426
+ .. _request-options:
427
+
428
+ Request Options
429
+ ===============
430
+
431
+ You can customize requests created by a client using **request options**.
432
+ Request options control various aspects of a request including, headers,
433
+ query string parameters, timeout settings, the body of a request, and much
434
+ more.
435
+
436
+ All of the following examples use the following client:
437
+
438
+ .. code-block:: php
439
+
440
+ $client = new GuzzleHttp\Client(['base_url' => 'http://httpbin.org']);
441
+
442
+ headers
443
+ -------
444
+
445
+ :Summary: Associative array of headers to add to the request. Each key is the
446
+ name of a header, and each value is a string or array of strings
447
+ representing the header field values.
448
+ :Types: array
449
+ :Defaults: None
450
+
451
+ .. code-block:: php
452
+
453
+ // Set various headers on a request
454
+ $client->get('/get', [
455
+ 'headers' => [
456
+ 'User-Agent' => 'testing/1.0',
457
+ 'Accept' => 'application/json',
458
+ 'X-Foo' => ['Bar', 'Baz']
459
+ ]
460
+ ]);
461
+
462
+ body
463
+ ----
464
+
465
+ :Summary: The ``body`` option is used to control the body of an entity
466
+ enclosing request (e.g., PUT, POST, PATCH).
467
+ :Types:
468
+ - string
469
+ - ``fopen()`` resource
470
+ - ``GuzzleHttp\Stream\StreamInterface``
471
+ - ``GuzzleHttp\Post\PostBodyInterface``
472
+ :Default: None
473
+
474
+ This setting can be set to any of the following types:
475
+
476
+ - string
477
+
478
+ .. code-block:: php
479
+
480
+ // You can send requests that use a string as the message body.
481
+ $client->put('/put', ['body' => 'foo']);
482
+
483
+ - resource returned from ``fopen()``
484
+
485
+ .. code-block:: php
486
+
487
+ // You can send requests that use a stream resource as the body.
488
+ $resource = fopen('http://httpbin.org', 'r');
489
+ $client->put('/put', ['body' => $resource]);
490
+
491
+ - Array
492
+
493
+ Use an array to send POST style requests that use a
494
+ ``GuzzleHttp\Post\PostBodyInterface`` object as the body.
495
+
496
+ .. code-block:: php
497
+
498
+ // You can send requests that use a POST body containing fields & files.
499
+ $client->post('/post', [
500
+ 'body' => [
501
+ 'field' => 'abc',
502
+ 'other_field' => '123',
503
+ 'file_name' => fopen('/path/to/file', 'r')
504
+ ]
505
+ ]);
506
+
507
+ - ``GuzzleHttp\Stream\StreamInterface``
508
+
509
+ .. code-block:: php
510
+
511
+ // You can send requests that use a Guzzle stream object as the body
512
+ $stream = GuzzleHttp\Stream\Stream::factory('contents...');
513
+ $client->post('/post', ['body' => $stream]);
514
+
515
+ json
516
+ ----
517
+
518
+ :Summary: The ``json`` option is used to easily upload JSON encoded data as the
519
+ body of a request. A Content-Type header of ``application/json`` will be
520
+ added if no Content-Type header is already present on the message.
521
+ :Types:
522
+ Any PHP type that can be operated on by PHP's ``json_encode()`` function.
523
+ :Default: None
524
+
525
+ .. code-block:: php
526
+
527
+ $request = $client->createRequest('/put', ['json' => ['foo' => 'bar']]);
528
+ echo $request->getHeader('Content-Type');
529
+ // application/json
530
+ echo $request->getBody();
531
+ // {"foo":"bar"}
532
+
533
+ .. note::
534
+
535
+ This request option does not support customizing the Content-Type header
536
+ or any of the options from PHP's `json_encode() <http://www.php.net/manual/en/function.json-encode.php>`_
537
+ function. If you need to customize these settings, then you must pass the
538
+ JSON encoded data into the request yourself using the ``body`` request
539
+ option and you must specify the correct Content-Type header using the
540
+ ``headers`` request option.
541
+
542
+ query
543
+ -----
544
+
545
+ :Summary: Associative array of query string values to add to the request.
546
+ :Types:
547
+ - array
548
+ - ``GuzzleHttp\Query``
549
+ :Default: None
550
+
551
+ .. code-block:: php
552
+
553
+ // Send a GET request to /get?foo=bar
554
+ $client->get('/get', ['query' => ['foo' => 'bar']]);
555
+
556
+ Query strings specified in the ``query`` option are combined with any query
557
+ string values that are parsed from the URL.
558
+
559
+ .. code-block:: php
560
+
561
+ // Send a GET request to /get?abc=123&foo=bar
562
+ $client->get('/get?abc=123', ['query' => ['foo' => 'bar']]);
563
+
564
+ auth
565
+ ----
566
+
567
+ :Summary: Pass an array of HTTP authentication parameters to use with the
568
+ request. The array must contain the username in index [0], the password in
569
+ index [1], and you can optionally provide a built-in authentication type in
570
+ index [2]. Pass ``null`` to disable authentication for a request.
571
+ :Types:
572
+ - array
573
+ - string
574
+ - null
575
+ :Default: None
576
+
577
+ The built-in authentication types are as follows:
578
+
579
+ basic
580
+ Use `basic HTTP authentication <http://www.ietf.org/rfc/rfc2069.txt>`_ in
581
+ the ``Authorization`` header (the default setting used if none is
582
+ specified).
583
+
584
+ .. code-block:: php
585
+
586
+ $client->get('/get', ['auth' => ['username', 'password']]);
587
+
588
+ digest
589
+ Use `digest authentication <http://www.ietf.org/rfc/rfc2069.txt>`_ (must be
590
+ supported by the HTTP handler).
591
+
592
+ .. code-block:: php
593
+
594
+ $client->get('/get', ['auth' => ['username', 'password', 'digest']]);
595
+
596
+ *This is currently only supported when using the cURL handler, but creating
597
+ a replacement that can be used with any HTTP handler is planned.*
598
+
599
+ .. important::
600
+
601
+ The authentication type (whether it's provided as a string or as the third
602
+ option in an array) is always converted to a lowercase string. Take this
603
+ into account when implementing custom authentication types and when
604
+ implementing custom message factories.
605
+
606
+ Custom Authentication Schemes
607
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
608
+
609
+ You can also provide a string representing a custom authentication type name.
610
+ When using a custom authentication type string, you will need to implement
611
+ the authentication method in an event listener that checks the ``auth`` request
612
+ option of a request before it is sent. Authentication listeners that require
613
+ a request is not modified after they are signed should have a very low priority
614
+ to ensure that they are fired last or near last in the event chain.
615
+
616
+ .. code-block:: php
617
+
618
+ use GuzzleHttp\Event\BeforeEvent;
619
+ use GuzzleHttp\Event\RequestEvents;
620
+
621
+ /**
622
+ * Custom authentication listener that handles the "foo" auth type.
623
+ *
624
+ * Listens to the "before" event of a request and only modifies the request
625
+ * when the "auth" config setting of the request is "foo".
626
+ */
627
+ class FooAuth implements GuzzleHttp\Event\SubscriberInterface
628
+ {
629
+ private $password;
630
+
631
+ public function __construct($password)
632
+ {
633
+ $this->password = $password;
634
+ }
635
+
636
+ public function getEvents()
637
+ {
638
+ return ['before' => ['sign', RequestEvents::SIGN_REQUEST]];
639
+ }
640
+
641
+ public function sign(BeforeEvent $e)
642
+ {
643
+ if ($e->getRequest()->getConfig()['auth'] == 'foo') {
644
+ $e->getRequest()->setHeader('X-Foo', 'Foo ' . $this->password);
645
+ }
646
+ }
647
+ }
648
+
649
+ $client->getEmitter()->attach(new FooAuth('password'));
650
+ $client->get('/', ['auth' => 'foo']);
651
+
652
+ Adapter Specific Authentication Schemes
653
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
654
+
655
+ If you need to use authentication methods provided by cURL (e.g., NTLM, GSS,
656
+ etc.), then you need to specify a curl handler option in the ``options``
657
+ request option array. See :ref:`config-option` for more information.
658
+
659
+ .. _cookies-option:
660
+
661
+ cookies
662
+ -------
663
+
664
+ :Summary: Specifies whether or not cookies are used in a request or what cookie
665
+ jar to use or what cookies to send.
666
+ :Types:
667
+ - bool
668
+ - array
669
+ - ``GuzzleHttp\Cookie\CookieJarInterface``
670
+ :Default: None
671
+
672
+ Set to ``true`` to use a shared cookie session associated with the client.
673
+
674
+ .. code-block:: php
675
+
676
+ // Enable cookies using the shared cookie jar of the client.
677
+ $client->get('/get', ['cookies' => true]);
678
+
679
+ Pass an associative array containing cookies to send in the request and start a
680
+ new cookie session.
681
+
682
+ .. code-block:: php
683
+
684
+ // Enable cookies and send specific cookies
685
+ $client->get('/get', ['cookies' => ['foo' => 'bar']]);
686
+
687
+ Set to a ``GuzzleHttp\Cookie\CookieJarInterface`` object to use an existing
688
+ cookie jar.
689
+
690
+ .. code-block:: php
691
+
692
+ $jar = new GuzzleHttp\Cookie\CookieJar();
693
+ $client->get('/get', ['cookies' => $jar]);
694
+
695
+ .. _allow_redirects-option:
696
+
697
+ allow_redirects
698
+ ---------------
699
+
700
+ :Summary: Describes the redirect behavior of a request
701
+ :Types:
702
+ - bool
703
+ - array
704
+ :Default: ``['max' => 5, 'strict' => false, 'referer' => true]``
705
+
706
+ Set to ``false`` to disable redirects.
707
+
708
+ .. code-block:: php
709
+
710
+ $res = $client->get('/redirect/3', ['allow_redirects' => false]);
711
+ echo $res->getStatusCode();
712
+ // 302
713
+
714
+ Set to ``true`` (the default setting) to enable normal redirects with a maximum
715
+ number of 5 redirects.
716
+
717
+ .. code-block:: php
718
+
719
+ $res = $client->get('/redirect/3');
720
+ echo $res->getStatusCode();
721
+ // 200
722
+
723
+ Pass an associative array containing the 'max' key to specify the maximum
724
+ number of redirects, optionally provide a 'strict' key value to specify
725
+ whether or not to use strict RFC compliant redirects (meaning redirect POST
726
+ requests with POST requests vs. doing what most browsers do which is redirect
727
+ POST requests with GET requests), and optionally provide a 'referer' key to
728
+ specify whether or not the "Referer" header should be added when redirecting.
729
+
730
+ .. code-block:: php
731
+
732
+ $res = $client->get('/redirect/3', [
733
+ 'allow_redirects' => [
734
+ 'max' => 10,
735
+ 'strict' => true,
736
+ 'referer' => true
737
+ ]
738
+ ]);
739
+ echo $res->getStatusCode();
740
+ // 200
741
+
742
+ decode_content
743
+ --------------
744
+
745
+ :Summary: Specify whether or not ``Content-Encoding`` responses (gzip,
746
+ deflate, etc.) are automatically decoded.
747
+ :Types:
748
+ - string
749
+ - bool
750
+ :Default: ``true``
751
+
752
+ This option can be used to control how content-encoded response bodies are
753
+ handled. By default, ``decode_content`` is set to true, meaning any gzipped
754
+ or deflated response will be decoded by Guzzle.
755
+
756
+ When set to ``false``, the body of a response is never decoded, meaning the
757
+ bytes pass through the handler unchanged.
758
+
759
+ .. code-block:: php
760
+
761
+ // Request gzipped data, but do not decode it while downloading
762
+ $client->get('/foo.js', [
763
+ 'headers' => ['Accept-Encoding' => 'gzip'],
764
+ 'decode_content' => false
765
+ ]);
766
+
767
+ When set to a string, the bytes of a response are decoded and the string value
768
+ provided to the ``decode_content`` option is passed as the ``Accept-Encoding``
769
+ header of the request.
770
+
771
+ .. code-block:: php
772
+
773
+ // Pass "gzip" as the Accept-Encoding header.
774
+ $client->get('/foo.js', ['decode_content' => 'gzip']);
775
+
776
+ .. _save_to-option:
777
+
778
+ save_to
779
+ -------
780
+
781
+ :Summary: Specify where the body of a response will be saved.
782
+ :Types:
783
+ - string
784
+ - ``fopen()`` resource
785
+ - ``GuzzleHttp\Stream\StreamInterface``
786
+ :Default: PHP temp stream
787
+
788
+ Pass a string to specify the path to a file that will store the contents of the
789
+ response body:
790
+
791
+ .. code-block:: php
792
+
793
+ $client->get('/stream/20', ['save_to' => '/path/to/file']);
794
+
795
+ Pass a resource returned from ``fopen()`` to write the response to a PHP stream:
796
+
797
+ .. code-block:: php
798
+
799
+ $resource = fopen('/path/to/file', 'w');
800
+ $client->get('/stream/20', ['save_to' => $resource]);
801
+
802
+ Pass a ``GuzzleHttp\Stream\StreamInterface`` object to stream the response body
803
+ to an open Guzzle stream:
804
+
805
+ .. code-block:: php
806
+
807
+ $resource = fopen('/path/to/file', 'w');
808
+ $stream = GuzzleHttp\Stream\Stream::factory($resource);
809
+ $client->get('/stream/20', ['save_to' => $stream]);
810
+
811
+ .. _events-option:
812
+
813
+ events
814
+ ------
815
+
816
+ :Summary: An associative array mapping event names to a callable. Or an
817
+ associative array containing the 'fn' key that maps to a callable, an
818
+ optional 'priority' key used to specify the event priority, and an optional
819
+ 'once' key used to specify if the event should remove itself the first time
820
+ it is triggered.
821
+ :Types: array
822
+ :Default: None
823
+
824
+ .. code-block:: php
825
+
826
+ use GuzzleHttp\Event\BeforeEvent;
827
+ use GuzzleHttp\Event\HeadersEvent;
828
+ use GuzzleHttp\Event\CompleteEvent;
829
+ use GuzzleHttp\Event\ErrorEvent;
830
+
831
+ $client->get('/', [
832
+ 'events' => [
833
+ 'before' => function (BeforeEvent $e) { echo 'Before'; },
834
+ 'complete' => function (CompleteEvent $e) { echo 'Complete'; },
835
+ 'error' => function (ErrorEvent $e) { echo 'Error'; },
836
+ ]
837
+ ]);
838
+
839
+ Here's an example of using the associative array format for control over the
840
+ priority and whether or not an event should be triggered more than once.
841
+
842
+ .. code-block:: php
843
+
844
+ $client->get('/', [
845
+ 'events' => [
846
+ 'before' => [
847
+ 'fn' => function (BeforeEvent $e) { echo 'Before'; },
848
+ 'priority' => 100,
849
+ 'once' => true
850
+ ]
851
+ ]
852
+ ]);
853
+
854
+ .. _subscribers-option:
855
+
856
+ subscribers
857
+ -----------
858
+
859
+ :Summary: Array of event subscribers to add to the request. Each value in the
860
+ array must be an instance of ``GuzzleHttp\Event\SubscriberInterface``.
861
+ :Types: array
862
+ :Default: None
863
+
864
+ .. code-block:: php
865
+
866
+ use GuzzleHttp\Subscriber\History;
867
+ use GuzzleHttp\Subscriber\Mock;
868
+ use GuzzleHttp\Message\Response;
869
+
870
+ $history = new History();
871
+ $mock = new Mock([new Response(200)]);
872
+ $client->get('/', ['subscribers' => [$history, $mock]]);
873
+
874
+ echo $history;
875
+ // Outputs the request and response history
876
+
877
+ .. _exceptions-option:
878
+
879
+ exceptions
880
+ ----------
881
+
882
+ :Summary: Set to ``false`` to disable throwing exceptions on an HTTP protocol
883
+ errors (i.e., 4xx and 5xx responses). Exceptions are thrown by default when
884
+ HTTP protocol errors are encountered.
885
+ :Types: bool
886
+ :Default: ``true``
887
+
888
+ .. code-block:: php
889
+
890
+ $client->get('/status/500');
891
+ // Throws a GuzzleHttp\Exception\ServerException
892
+
893
+ $res = $client->get('/status/500', ['exceptions' => false]);
894
+ echo $res->getStatusCode();
895
+ // 500
896
+
897
+ .. _timeout-option:
898
+
899
+ timeout
900
+ -------
901
+
902
+ :Summary: Float describing the timeout of the request in seconds. Use ``0``
903
+ to wait indefinitely (the default behavior).
904
+ :Types: float
905
+ :Default: ``0``
906
+
907
+ .. code-block:: php
908
+
909
+ // Timeout if a server does not return a response in 3.14 seconds.
910
+ $client->get('/delay/5', ['timeout' => 3.14]);
911
+ // PHP Fatal error: Uncaught exception 'GuzzleHttp\Exception\RequestException'
912
+
913
+ .. _connect_timeout-option:
914
+
915
+ connect_timeout
916
+ ---------------
917
+
918
+ :Summary: Float describing the number of seconds to wait while trying to connect
919
+ to a server. Use ``0`` to wait indefinitely (the default behavior).
920
+ :Types: float
921
+ :Default: ``0``
922
+
923
+ .. code-block:: php
924
+
925
+ // Timeout if the client fails to connect to the server in 3.14 seconds.
926
+ $client->get('/delay/5', ['connect_timeout' => 3.14]);
927
+
928
+ .. note::
929
+
930
+ This setting must be supported by the HTTP handler used to send a request.
931
+ ``connect_timeout`` is currently only supported by the built-in cURL
932
+ handler.
933
+
934
+ .. _verify-option:
935
+
936
+ verify
937
+ ------
938
+
939
+ :Summary: Describes the SSL certificate verification behavior of a request.
940
+
941
+ - Set to ``true`` to enable SSL certificate verification and use the default
942
+ CA bundle provided by operating system.
943
+ - Set to ``false`` to disable certificate verification (this is insecure!).
944
+ - Set to a string to provide the path to a CA bundle to enable verification
945
+ using a custom certificate.
946
+ :Types:
947
+ - bool
948
+ - string
949
+ :Default: ``true``
950
+
951
+ .. code-block:: php
952
+
953
+ // Use the system's CA bundle (this is the default setting)
954
+ $client->get('/', ['verify' => true]);
955
+
956
+ // Use a custom SSL certificate on disk.
957
+ $client->get('/', ['verify' => '/path/to/cert.pem']);
958
+
959
+ // Disable validation entirely (don't do this!).
960
+ $client->get('/', ['verify' => false]);
961
+
962
+ Not all system's have a known CA bundle on disk. For example, Windows and
963
+ OS X do not have a single common location for CA bundles. When setting
964
+ "verify" to ``true``, Guzzle will do its best to find the most appropriate
965
+ CA bundle on your system. When using cURL or the PHP stream wrapper on PHP
966
+ versions >= 5.6, this happens by default. When using the PHP stream
967
+ wrapper on versions < 5.6, Guzzle tries to find your CA bundle in the
968
+ following order:
969
+
970
+ 1. Check if ``openssl.cafile`` is set in your php.ini file.
971
+ 2. Check if ``curl.cainfo`` is set in your php.ini file.
972
+ 3. Check if ``/etc/pki/tls/certs/ca-bundle.crt`` exists (Red Hat, CentOS,
973
+ Fedora; provided by the ca-certificates package)
974
+ 4. Check if ``/etc/ssl/certs/ca-certificates.crt`` exists (Ubuntu, Debian;
975
+ provided by the ca-certificates package)
976
+ 5. Check if ``/usr/local/share/certs/ca-root-nss.crt`` exists (FreeBSD;
977
+ provided by the ca_root_nss package)
978
+ 6. Check if ``/usr/local/etc/openssl/cert.pem`` (OS X; provided by homebrew)
979
+ 7. Check if ``C:\windows\system32\curl-ca-bundle.crt`` exists (Windows)
980
+ 8. Check if ``C:\windows\curl-ca-bundle.crt`` exists (Windows)
981
+
982
+ The result of this lookup is cached in memory so that subsequent calls
983
+ in the same process will return very quickly. However, when sending only
984
+ a single request per-process in something like Apache, you should consider
985
+ setting the ``openssl.cafile`` environment variable to the path on disk
986
+ to the file so that this entire process is skipped.
987
+
988
+ If you do not need a specific certificate bundle, then Mozilla provides a
989
+ commonly used CA bundle which can be downloaded
990
+ `here <https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt>`_
991
+ (provided by the maintainer of cURL). Once you have a CA bundle available on
992
+ disk, you can set the "openssl.cafile" PHP ini setting to point to the path to
993
+ the file, allowing you to omit the "verify" request option. Much more detail on
994
+ SSL certificates can be found on the
995
+ `cURL website <http://curl.haxx.se/docs/sslcerts.html>`_.
996
+
997
+ .. _cert-option:
998
+
999
+ cert
1000
+ ----
1001
+
1002
+ :Summary: Set to a string to specify the path to a file containing a PEM
1003
+ formatted client side certificate. If a password is required, then set to
1004
+ an array containing the path to the PEM file in the first array element
1005
+ followed by the password required for the certificate in the second array
1006
+ element.
1007
+ :Types:
1008
+ - string
1009
+ - array
1010
+ :Default: None
1011
+
1012
+ .. code-block:: php
1013
+
1014
+ $client->get('/', ['cert' => ['/path/server.pem', 'password']]);
1015
+
1016
+ .. _ssl_key-option:
1017
+
1018
+ ssl_key
1019
+ -------
1020
+
1021
+ :Summary: Specify the path to a file containing a private SSL key in PEM
1022
+ format. If a password is required, then set to an array containing the path
1023
+ to the SSL key in the first array element followed by the password required
1024
+ for the certificate in the second element.
1025
+ :Types:
1026
+ - string
1027
+ - array
1028
+ :Default: None
1029
+
1030
+ .. note::
1031
+
1032
+ ``ssl_key`` is implemented by HTTP handlers. This is currently only
1033
+ supported by the cURL handler, but might be supported by other third-part
1034
+ handlers.
1035
+
1036
+ .. _proxy-option:
1037
+
1038
+ proxy
1039
+ -----
1040
+
1041
+ :Summary: Pass a string to specify an HTTP proxy, or an array to specify
1042
+ different proxies for different protocols.
1043
+ :Types:
1044
+ - string
1045
+ - array
1046
+ :Default: None
1047
+
1048
+ Pass a string to specify a proxy for all protocols.
1049
+
1050
+ .. code-block:: php
1051
+
1052
+ $client->get('/', ['proxy' => 'tcp://localhost:8125']);
1053
+
1054
+ Pass an associative array to specify HTTP proxies for specific URI schemes
1055
+ (i.e., "http", "https").
1056
+
1057
+ .. code-block:: php
1058
+
1059
+ $client->get('/', [
1060
+ 'proxy' => [
1061
+ 'http' => 'tcp://localhost:8125', // Use this proxy with "http"
1062
+ 'https' => 'tcp://localhost:9124' // Use this proxy with "https"
1063
+ ]
1064
+ ]);
1065
+
1066
+ .. note::
1067
+
1068
+ You can provide proxy URLs that contain a scheme, username, and password.
1069
+ For example, ``"http://username:password@192.168.16.1:10"``.
1070
+
1071
+ .. _debug-option:
1072
+
1073
+ debug
1074
+ -----
1075
+
1076
+ :Summary: Set to ``true`` or set to a PHP stream returned by ``fopen()`` to
1077
+ enable debug output with the handler used to send a request. For example,
1078
+ when using cURL to transfer requests, cURL's verbose of ``CURLOPT_VERBOSE``
1079
+ will be emitted. When using the PHP stream wrapper, stream wrapper
1080
+ notifications will be emitted. If set to true, the output is written to
1081
+ PHP's STDOUT. If a PHP stream is provided, output is written to the stream.
1082
+ :Types:
1083
+ - bool
1084
+ - ``fopen()`` resource
1085
+ :Default: None
1086
+
1087
+ .. code-block:: php
1088
+
1089
+ $client->get('/get', ['debug' => true]);
1090
+
1091
+ Running the above example would output something like the following:
1092
+
1093
+ ::
1094
+
1095
+ * About to connect() to httpbin.org port 80 (#0)
1096
+ * Trying 107.21.213.98... * Connected to httpbin.org (107.21.213.98) port 80 (#0)
1097
+ > GET /get HTTP/1.1
1098
+ Host: httpbin.org
1099
+ User-Agent: Guzzle/4.0 curl/7.21.4 PHP/5.5.7
1100
+
1101
+ < HTTP/1.1 200 OK
1102
+ < Access-Control-Allow-Origin: *
1103
+ < Content-Type: application/json
1104
+ < Date: Sun, 16 Feb 2014 06:50:09 GMT
1105
+ < Server: gunicorn/0.17.4
1106
+ < Content-Length: 335
1107
+ < Connection: keep-alive
1108
+ <
1109
+ * Connection #0 to host httpbin.org left intact
1110
+
1111
+ .. _stream-option:
1112
+
1113
+ stream
1114
+ ------
1115
+
1116
+ :Summary: Set to ``true`` to stream a response rather than download it all
1117
+ up-front.
1118
+ :Types: bool
1119
+ :Default: ``false``
1120
+
1121
+ .. code-block:: php
1122
+
1123
+ $response = $client->get('/stream/20', ['stream' => true]);
1124
+ // Read bytes off of the stream until the end of the stream is reached
1125
+ $body = $response->getBody();
1126
+ while (!$body->eof()) {
1127
+ echo $body->read(1024);
1128
+ }
1129
+
1130
+ .. note::
1131
+
1132
+ Streaming response support must be implemented by the HTTP handler used by
1133
+ a client. This option might not be supported by every HTTP handler, but the
1134
+ interface of the response object remains the same regardless of whether or
1135
+ not it is supported by the handler.
1136
+
1137
+ .. _expect-option:
1138
+
1139
+ expect
1140
+ ------
1141
+
1142
+ :Summary: Controls the behavior of the "Expect: 100-Continue" header.
1143
+ :Types:
1144
+ - bool
1145
+ - integer
1146
+ :Default: ``1048576``
1147
+
1148
+ Set to ``true`` to enable the "Expect: 100-Continue" header for all requests
1149
+ that sends a body. Set to ``false`` to disable the "Expect: 100-Continue"
1150
+ header for all requests. Set to a number so that the size of the payload must
1151
+ be greater than the number in order to send the Expect header. Setting to a
1152
+ number will send the Expect header for all requests in which the size of the
1153
+ payload cannot be determined or where the body is not rewindable.
1154
+
1155
+ By default, Guzzle will add the "Expect: 100-Continue" header when the size of
1156
+ the body of a request is greater than 1 MB and a request is using HTTP/1.1.
1157
+
1158
+ .. note::
1159
+
1160
+ This option only takes effect when using HTTP/1.1. The HTTP/1.0 and
1161
+ HTTP/2.0 protocols do not support the "Expect: 100-Continue" header.
1162
+ Support for handling the "Expect: 100-Continue" workflow must be
1163
+ implemented by Guzzle HTTP handlers used by a client.
1164
+
1165
+ .. _version-option:
1166
+
1167
+ version
1168
+ -------
1169
+
1170
+ :Summary: Protocol version to use with the request.
1171
+ :Types: string, float
1172
+ :Default: ``1.1``
1173
+
1174
+ .. code-block:: php
1175
+
1176
+ // Force HTTP/1.0
1177
+ $request = $client->createRequest('GET', '/get', ['version' => 1.0]);
1178
+ echo $request->getProtocolVersion();
1179
+ // 1.0
1180
+
1181
+ .. _config-option:
1182
+
1183
+ config
1184
+ ------
1185
+
1186
+ :Summary: Associative array of config options that are forwarded to a request's
1187
+ configuration collection. These values are used as configuration options
1188
+ that can be consumed by plugins and handlers.
1189
+ :Types: array
1190
+ :Default: None
1191
+
1192
+ .. code-block:: php
1193
+
1194
+ $request = $client->createRequest('GET', '/get', ['config' => ['foo' => 'bar']]);
1195
+ echo $request->getConfig('foo');
1196
+ // 'bar'
1197
+
1198
+ Some HTTP handlers allow you to specify custom handler-specific settings. For
1199
+ example, you can pass custom cURL options to requests by passing an associative
1200
+ array in the ``config`` request option under the ``curl`` key.
1201
+
1202
+ .. code-block:: php
1203
+
1204
+ // Use custom cURL options with the request. This example uses NTLM auth
1205
+ // to authenticate with a server.
1206
+ $client->get('/', [
1207
+ 'config' => [
1208
+ 'curl' => [
1209
+ CURLOPT_HTTPAUTH => CURLAUTH_NTLM,
1210
+ CURLOPT_USERPWD => 'username:password'
1211
+ ]
1212
+ ]
1213
+ ]);
1214
+
1215
+ future
1216
+ ------
1217
+
1218
+ :Summary: Specifies whether or not a response SHOULD be an instance of a
1219
+ ``GuzzleHttp\Message\FutureResponse`` object.
1220
+ :Types:
1221
+ - bool
1222
+ - string
1223
+ :Default: ``false``
1224
+
1225
+ By default, Guzzle requests should be synchronous. You can create asynchronous
1226
+ future responses by passing the ``future`` request option as ``true``. The
1227
+ response will only be executed when it is used like a normal response, the
1228
+ ``wait()`` method of the response is called, or the corresponding handler that
1229
+ created the response is destructing and there are futures that have not been
1230
+ resolved.
1231
+
1232
+ .. important::
1233
+
1234
+ This option only has an effect if your handler can create and return future
1235
+ responses. However, even if a response is completed synchronously, Guzzle
1236
+ will ensure that a FutureResponse object is returned for API consistency.
1237
+
1238
+ .. code-block:: php
1239
+
1240
+ $response = $client->get('/foo', ['future' => true])
1241
+ ->then(function ($response) {
1242
+ echo 'I got a response! ' . $response;
1243
+ });
1244
+
1245
+ Event Subscribers
1246
+ =================
1247
+
1248
+ Requests emit lifecycle events when they are transferred. A client object has a
1249
+ ``GuzzleHttp\Common\EventEmitter`` object that can be used to add event
1250
+ *listeners* and event *subscribers* to all requests created by the client.
1251
+
1252
+ .. important::
1253
+
1254
+ **Every** event listener or subscriber added to a client will be added to
1255
+ every request created by the client.
1256
+
1257
+ .. code-block:: php
1258
+
1259
+ use GuzzleHttp\Client;
1260
+ use GuzzleHttp\Event\BeforeEvent;
1261
+
1262
+ $client = new Client();
1263
+
1264
+ // Add a listener that will echo out requests before they are sent
1265
+ $client->getEmitter()->on('before', function (BeforeEvent $e) {
1266
+ echo 'About to send request: ' . $e->getRequest();
1267
+ });
1268
+
1269
+ $client->get('http://httpbin.org/get');
1270
+ // Outputs the request as a string because of the event
1271
+
1272
+ See :doc:`events` for more information on the event system used in Guzzle.
1273
+
1274
+ Environment Variables
1275
+ =====================
1276
+
1277
+ Guzzle exposes a few environment variables that can be used to customize the
1278
+ behavior of the library.
1279
+
1280
+ ``GUZZLE_CURL_SELECT_TIMEOUT``
1281
+ Controls the duration in seconds that a curl_multi_* handler will use when
1282
+ selecting on curl handles using ``curl_multi_select()``. Some systems
1283
+ have issues with PHP's implementation of ``curl_multi_select()`` where
1284
+ calling this function always results in waiting for the maximum duration of
1285
+ the timeout.
1286
+ ``HTTP_PROXY``
1287
+ Defines the proxy to use when sending requests using the "http" protocol.
1288
+ ``HTTPS_PROXY``
1289
+ Defines the proxy to use when sending requests using the "https" protocol.
1290
+
1291
+ Relevant ini Settings
1292
+ ---------------------
1293
+
1294
+ Guzzle can utilize PHP ini settings when configuring clients.
1295
+
1296
+ ``openssl.cafile``
1297
+ Specifies the path on disk to a CA file in PEM format to use when sending
1298
+ requests over "https". See: https://wiki.php.net/rfc/tls-peer-verification#phpini_defaults
backend/vendor/guzzlehttp/guzzle/docs/conf.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys, os
2
+ from sphinx.highlighting import lexers
3
+ from pygments.lexers.web import PhpLexer
4
+
5
+
6
+ lexers['php'] = PhpLexer(startinline=True, linenos=1)
7
+ lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
8
+ primary_domain = 'php'
9
+
10
+ extensions = []
11
+ templates_path = ['_templates']
12
+ source_suffix = '.rst'
13
+ master_doc = 'index'
14
+ project = u'Guzzle'
15
+ copyright = u'2014, Michael Dowling'
16
+ version = '5.0.0'
17
+ html_title = "Guzzle Documentation"
18
+ html_short_title = "Guzzle"
19
+
20
+ exclude_patterns = ['_build']
21
+ html_static_path = ['_static']
22
+
23
+ on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
24
+
25
+ if not on_rtd: # only import and set the theme if we're building docs locally
26
+ import sphinx_rtd_theme
27
+ html_theme = 'sphinx_rtd_theme'
28
+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
backend/vendor/guzzlehttp/guzzle/docs/events.rst ADDED
@@ -0,0 +1,508 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ============
2
+ Event System
3
+ ============
4
+
5
+ Guzzle uses an event emitter to allow you to easily extend the behavior of a
6
+ request, change the response associated with a request, and implement custom
7
+ error handling. All events in Guzzle are managed and emitted by an
8
+ **event emitter**.
9
+
10
+ Event Emitters
11
+ ==============
12
+
13
+ Clients, requests, and any other class that implements the
14
+ ``GuzzleHttp\Common\HasEmitterInterface`` interface have a
15
+ ``GuzzleHttp\Common\EventEmitter`` object. You can add event *listeners* and
16
+ event *subscribers* to an event *emitter*.
17
+
18
+ emitter
19
+ An object that implements ``GuzzleHttp\Common\EventEmitterInterface``. This
20
+ object emits named events to event listeners. You may register event
21
+ listeners on subscribers on an emitter.
22
+
23
+ event listeners
24
+ Callable functions that are registered on an event emitter for specific
25
+ events. Event listeners are registered on an emitter with a *priority*
26
+ setting. If no priority is provided, ``0`` is used by default.
27
+
28
+ event subscribers
29
+ Classes that tell an event emitter what methods to listen to and what
30
+ functions on the class to invoke when the event is triggered. Event
31
+ subscribers subscribe event listeners to an event emitter. They should be
32
+ used when creating more complex event based logic in applications (i.e.,
33
+ cookie handling is implemented using an event subscriber because it's
34
+ easier to share a subscriber than an anonymous function and because
35
+ handling cookies is a complex process).
36
+
37
+ priority
38
+ Describes the order in which event listeners are invoked when an event is
39
+ emitted. The higher a priority value, the earlier the event listener will
40
+ be invoked (a higher priority means the listener is more important). If
41
+ no priority is provided, the priority is assumed to be ``0``.
42
+
43
+ When specifying an event priority, you can pass ``"first"`` or ``"last"`` to
44
+ dynamically specify the priority based on the current event priorities
45
+ associated with the given event name in the emitter. Use ``"first"`` to set
46
+ the priority to the current highest priority plus one. Use ``"last"`` to
47
+ set the priority to the current lowest event priority minus one. It is
48
+ important to remember that these dynamic priorities are calculated only at
49
+ the point of insertion into the emitter and they are not rearranged after
50
+ subsequent listeners are added to an emitter.
51
+
52
+ propagation
53
+ Describes whether or not other event listeners are triggered. Event
54
+ emitters will trigger every event listener registered to a specific event
55
+ in priority order until all of the listeners have been triggered **or**
56
+ until the propagation of an event is stopped.
57
+
58
+ Getting an EventEmitter
59
+ -----------------------
60
+
61
+ You can get the event emitter of ``GuzzleHttp\Common\HasEmitterInterface``
62
+ object using the the ``getEmitter()`` method. Here's an example of getting a
63
+ client object's event emitter.
64
+
65
+ .. code-block:: php
66
+
67
+ $client = new GuzzleHttp\Client();
68
+ $emitter = $client->getEmitter();
69
+
70
+ .. note::
71
+
72
+ You'll notice that the event emitter used in Guzzle is very similar to the
73
+ `Symfony2 EventDispatcher component <https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher>`_.
74
+ This is because the Guzzle event system is based on the Symfony2 event
75
+ system with several changes. Guzzle uses its own event emitter to improve
76
+ performance, isolate Guzzle from changes to the Symfony, and provide a few
77
+ improvements that make it easier to use for an HTTP client (e.g., the
78
+ addition of the ``once()`` method).
79
+
80
+ Adding Event Listeners
81
+ ----------------------
82
+
83
+ After you have the emitter, you can register event listeners that listen to
84
+ specific events using the ``on()`` method. When registering an event listener,
85
+ you must tell the emitter what event to listen to (e.g., "before", "after",
86
+ "progress", "complete", "error", etc.), what callable to invoke when the
87
+ event is triggered, and optionally provide a priority.
88
+
89
+ .. code-block:: php
90
+
91
+ use GuzzleHttp\Event\BeforeEvent;
92
+
93
+ $emitter->on('before', function (BeforeEvent $event) {
94
+ echo $event->getRequest();
95
+ });
96
+
97
+ When a listener is triggered, it is passed an event that implements the
98
+ ``GuzzleHttp\Common\EventInterface`` interface, the name of the event, and the
99
+ event emitter itself. The above example could more verbosely be written as
100
+ follows:
101
+
102
+ .. code-block:: php
103
+
104
+ use GuzzleHttp\Event\BeforeEvent;
105
+
106
+ $emitter->on('before', function (
107
+ BeforeEvent $event,
108
+ $name,
109
+ EmitterInterface $emitter
110
+ ) {
111
+ echo $event->getRequest();
112
+ });
113
+
114
+ You can add an event listener that automatically removes itself after it is
115
+ triggered using the ``once()`` method of an event emitter.
116
+
117
+ .. code-block:: php
118
+
119
+ $client = new GuzzleHttp\Client();
120
+ $client->getEmitter()->once('before', function () {
121
+ echo 'This will only happen once... per request!';
122
+ });
123
+
124
+ Event Propagation
125
+ -----------------
126
+
127
+ Event listeners can prevent other event listeners from being triggered by
128
+ stopping an event's propagation.
129
+
130
+ Stopping event propagation can be useful, for example, if an event listener has
131
+ changed the state of the subject to such an extent that allowing subsequent
132
+ event listeners to be triggered could place the subject in an inconsistent
133
+ state. This technique is used in Guzzle extensively when intercepting error
134
+ events with responses.
135
+
136
+ You can stop the propagation of an event using the ``stopPropagation()`` method
137
+ of a ``GuzzleHttp\Common\EventInterface`` object:
138
+
139
+ .. code-block:: php
140
+
141
+ use GuzzleHttp\Event\ErrorEvent;
142
+
143
+ $emitter->on('error', function (ErrorEvent $event) {
144
+ $event->stopPropagation();
145
+ });
146
+
147
+ After stopping the propagation of an event, any subsequent event listeners that
148
+ have not yet been triggered will not be triggered. You can check to see if the
149
+ propagation of an event was stopped using the ``isPropagationStopped()`` method
150
+ of the event.
151
+
152
+ .. code-block:: php
153
+
154
+ $client = new GuzzleHttp\Client();
155
+ $emitter = $client->getEmitter();
156
+ // Note: assume that the $errorEvent was created
157
+ if ($emitter->emit('error', $errorEvent)->isPropagationStopped()) {
158
+ echo 'It was stopped!';
159
+ }
160
+
161
+ .. hint::
162
+
163
+ When emitting events, the event that was emitted is returned from the
164
+ emitter. This allows you to easily chain calls as shown in the above
165
+ example.
166
+
167
+ Event Subscribers
168
+ -----------------
169
+
170
+ Event subscribers are classes that implement the
171
+ ``GuzzleHttp\Common\EventSubscriberInterface`` object. They are used to register
172
+ one or more event listeners to methods of the class. Event subscribers tell
173
+ event emitters exactly which events to listen to and what method to invoke on
174
+ the class when the event is triggered by called the ``getEvents()`` method of
175
+ a subscriber.
176
+
177
+ The following example registers event listeners to the ``before`` and
178
+ ``complete`` event of a request. When the ``before`` event is emitted, the
179
+ ``onBefore`` instance method of the subscriber is invoked. When the
180
+ ``complete`` event is emitted, the ``onComplete`` event of the subscriber is
181
+ invoked. Each array value in the ``getEvents()`` return value MUST
182
+ contain the name of the method to invoke and can optionally contain the
183
+ priority of the listener (as shown in the ``before`` listener in the example).
184
+
185
+ .. code-block:: php
186
+
187
+ use GuzzleHttp\Event\EmitterInterface;
188
+ use GuzzleHttp\Event\SubscriberInterface;
189
+ use GuzzleHttp\Event\BeforeEvent;
190
+ use GuzzleHttp\Event\CompleteEvent;
191
+
192
+ class SimpleSubscriber implements SubscriberInterface
193
+ {
194
+ public function getEvents()
195
+ {
196
+ return [
197
+ // Provide name and optional priority
198
+ 'before' => ['onBefore', 100],
199
+ 'complete' => ['onComplete'],
200
+ // You can pass a list of listeners with different priorities
201
+ 'error' => [['beforeError', 'first'], ['afterError', 'last']]
202
+ ];
203
+ }
204
+
205
+ public function onBefore(BeforeEvent $event, $name)
206
+ {
207
+ echo 'Before!';
208
+ }
209
+
210
+ public function onComplete(CompleteEvent $event, $name)
211
+ {
212
+ echo 'Complete!';
213
+ }
214
+ }
215
+
216
+ .. note::
217
+
218
+ You can specify event priorities using integers or ``"first"`` and
219
+ ``"last"`` to dynamically determine the priority.
220
+
221
+ Event Priorities
222
+ ================
223
+
224
+ When adding event listeners or subscribers, you can provide an optional event
225
+ priority. This priority is used to determine how early or late a listener is
226
+ triggered. Specifying the correct priority is an important aspect of ensuring
227
+ a listener behaves as expected. For example, if you wanted to ensure that
228
+ cookies associated with a redirect were added to a cookie jar, you'd need to
229
+ make sure that the listener that collects the cookies is triggered before the
230
+ listener that performs the redirect.
231
+
232
+ In order to help make the process of determining the correct event priority of
233
+ a listener easier, Guzzle provides several pre-determined named event
234
+ priorities. These priorities are exposed as constants on the
235
+ ``GuzzleHttp\Event\RequestEvents`` object.
236
+
237
+ last
238
+ Use ``"last"`` as an event priority to set the priority to the current
239
+ lowest event priority minus one.
240
+
241
+ first
242
+ Use ``"first"`` as an event priority to set the priority to the current
243
+ highest priority plus one.
244
+
245
+ ``GuzzleHttp\Event\RequestEvents::EARLY``
246
+ Used when you want a listener to be triggered as early as possible in the
247
+ event chain.
248
+
249
+ ``GuzzleHttp\Event\RequestEvents::LATE``
250
+ Used when you want a listener to be to be triggered as late as possible in
251
+ the event chain.
252
+
253
+ ``GuzzleHttp\Event\RequestEvents::PREPARE_REQUEST``
254
+ Used when you want a listener to be trigger while a request is being
255
+ prepared during the ``before`` event. This event priority is used by the
256
+ ``GuzzleHttp\Subscriber\Prepare`` event subscriber which is responsible for
257
+ guessing a Content-Type, Content-Length, and Expect header of a request.
258
+ You should subscribe after this event is triggered if you want to ensure
259
+ that this subscriber has already been triggered.
260
+
261
+ ``GuzzleHttp\Event\RequestEvents::SIGN_REQUEST``
262
+ Used when you want a listener to be triggered when a request is about to be
263
+ signed. Any listener triggered at this point should expect that the request
264
+ object will no longer be mutated. If you are implementing a custom
265
+ signature subscriber, then you should use this event priority to sign
266
+ requests.
267
+
268
+ ``GuzzleHttp\Event\RequestEvents::VERIFY_RESPONSE``
269
+ Used when you want a listener to be triggered when a response is being
270
+ validated during the ``complete`` event. The
271
+ ``GuzzleHttp\Subscriber\HttpError`` event subscriber uses this event
272
+ priority to check if an exception should be thrown due to a 4xx or 5xx
273
+ level response status code. If you are doing any kind of verification of a
274
+ response during the complete event, it should happen at this priority.
275
+
276
+ ``GuzzleHttp\Event\RequestEvents::REDIRECT_RESPONSE``
277
+ Used when you want a listener to be triggered when a response is being
278
+ redirected during the ``complete`` event. The
279
+ ``GuzzleHttp\Subscriber\Redirect`` event subscriber uses this event
280
+ priority when performing redirects.
281
+
282
+ You can use the above event priorities as a guideline for determining the
283
+ priority of you event listeners. You can use these constants and add to or
284
+ subtract from them to ensure that a listener happens before or after the named
285
+ priority.
286
+
287
+ .. note::
288
+
289
+ "first" and "last" priorities are not adjusted after they added to an
290
+ emitter. For example, if you add a listener with a priority of "first",
291
+ you can still add subsequent listeners with a higher priority which would
292
+ be triggered before the listener added with a priority of "first".
293
+
294
+ Working With Request Events
295
+ ===========================
296
+
297
+ Requests emit lifecycle events when they are transferred.
298
+
299
+ .. important::
300
+
301
+ Excluding the ``end`` event, request lifecycle events may be triggered
302
+ multiple times due to redirects, retries, or reusing a request multiple
303
+ times. Use the ``once()`` method want the event to be triggered once. You
304
+ can also remove an event listener from an emitter by using the emitter which
305
+ is provided to the listener.
306
+
307
+ .. _before_event:
308
+
309
+ before
310
+ ------
311
+
312
+ The ``before`` event is emitted before a request is sent. The event emitted is
313
+ a ``GuzzleHttp\Event\BeforeEvent``.
314
+
315
+ .. code-block:: php
316
+
317
+ use GuzzleHttp\Client;
318
+ use GuzzleHttp\Common\EmitterInterface;
319
+ use GuzzleHttp\Event\BeforeEvent;
320
+
321
+ $client = new Client(['base_url' => 'http://httpbin.org']);
322
+ $request = $client->createRequest('GET', '/');
323
+ $request->getEmitter()->on(
324
+ 'before',
325
+ function (BeforeEvent $e, $name, EmitterInterface $emitter) {
326
+ echo $name . "\n";
327
+ // "before"
328
+ echo $e->getRequest()->getMethod() . "\n";
329
+ // "GET" / "POST" / "PUT" / etc.
330
+ echo get_class($e->getClient());
331
+ // "GuzzleHttp\Client"
332
+ }
333
+ );
334
+
335
+ You can intercept a request with a response before the request is sent over the
336
+ wire. The ``intercept()`` method of the ``BeforeEvent`` accepts a
337
+ ``GuzzleHttp\Message\ResponseInterface``. Intercepting the event will prevent
338
+ the request from being sent over the wire and stops the propagation of the
339
+ ``before`` event, preventing subsequent event listeners from being invoked.
340
+
341
+ .. code-block:: php
342
+
343
+ use GuzzleHttp\Client;
344
+ use GuzzleHttp\Event\BeforeEvent;
345
+ use GuzzleHttp\Message\Response;
346
+
347
+ $client = new Client(['base_url' => 'http://httpbin.org']);
348
+ $request = $client->createRequest('GET', '/status/500');
349
+ $request->getEmitter()->on('before', function (BeforeEvent $e) {
350
+ $response = new Response(200);
351
+ $e->intercept($response);
352
+ });
353
+
354
+ $response = $client->send($request);
355
+ echo $response->getStatusCode();
356
+ // 200
357
+
358
+ .. attention::
359
+
360
+ Any exception encountered while executing the ``before`` event will trigger
361
+ the ``error`` event of a request.
362
+
363
+ .. _complete_event:
364
+
365
+ complete
366
+ --------
367
+
368
+ The ``complete`` event is emitted after a transaction completes and an entire
369
+ response has been received. The event is a ``GuzzleHttp\Event\CompleteEvent``.
370
+
371
+ You can intercept the ``complete`` event with a different response if needed
372
+ using the ``intercept()`` method of the event. This can be useful, for example,
373
+ for changing the response for caching.
374
+
375
+ .. code-block:: php
376
+
377
+ use GuzzleHttp\Client;
378
+ use GuzzleHttp\Event\CompleteEvent;
379
+ use GuzzleHttp\Message\Response;
380
+
381
+ $client = new Client(['base_url' => 'http://httpbin.org']);
382
+ $request = $client->createRequest('GET', '/status/302');
383
+ $cachedResponse = new Response(200);
384
+
385
+ $request->getEmitter()->on(
386
+ 'complete',
387
+ function (CompleteEvent $e) use ($cachedResponse) {
388
+ if ($e->getResponse()->getStatusCode() == 302) {
389
+ // Intercept the original transaction with the new response
390
+ $e->intercept($cachedResponse);
391
+ }
392
+ }
393
+ );
394
+
395
+ $response = $client->send($request);
396
+ echo $response->getStatusCode();
397
+ // 200
398
+
399
+ .. attention::
400
+
401
+ Any ``GuzzleHttp\Exception\RequestException`` encountered while executing
402
+ the ``complete`` event will trigger the ``error`` event of a request.
403
+
404
+ .. _error_event:
405
+
406
+ error
407
+ -----
408
+
409
+ The ``error`` event is emitted when a request fails (whether it's from a
410
+ networking error or an HTTP protocol error). The event emitted is a
411
+ ``GuzzleHttp\Event\ErrorEvent``.
412
+
413
+ This event is useful for retrying failed requests. Here's an example of
414
+ retrying failed basic auth requests by re-sending the original request with
415
+ a username and password.
416
+
417
+ .. code-block:: php
418
+
419
+ use GuzzleHttp\Client;
420
+ use GuzzleHttp\Event\ErrorEvent;
421
+
422
+ $client = new Client(['base_url' => 'http://httpbin.org']);
423
+ $request = $client->createRequest('GET', '/basic-auth/foo/bar');
424
+ $request->getEmitter()->on('error', function (ErrorEvent $e) {
425
+ if ($e->getResponse()->getStatusCode() == 401) {
426
+ // Add authentication stuff as needed and retry the request
427
+ $e->getRequest()->setHeader('Authorization', 'Basic ' . base64_encode('foo:bar'));
428
+ // Get the client of the event and retry the request
429
+ $newResponse = $e->getClient()->send($e->getRequest());
430
+ // Intercept the original transaction with the new response
431
+ $e->intercept($newResponse);
432
+ }
433
+ });
434
+
435
+ .. attention::
436
+
437
+ If an ``error`` event is intercepted with a response, then the ``complete``
438
+ event of a request is triggered. If the ``complete`` event fails, then the
439
+ ``error`` event is triggered once again.
440
+
441
+ .. _progress_event:
442
+
443
+ progress
444
+ --------
445
+
446
+ The ``progress`` event is emitted when data is uploaded or downloaded. The
447
+ event emitted is a ``GuzzleHttp\Event\ProgressEvent``.
448
+
449
+ You can access the emitted progress values using the corresponding public
450
+ properties of the event object:
451
+
452
+ - ``$downloadSize``: The number of bytes that will be downloaded (if known)
453
+ - ``$downloaded``: The number of bytes that have been downloaded
454
+ - ``$uploadSize``: The number of bytes that will be uploaded (if known)
455
+ - ``$uploaded``: The number of bytes that have been uploaded
456
+
457
+ This event cannot be intercepted.
458
+
459
+ .. code-block:: php
460
+
461
+ use GuzzleHttp\Client;
462
+ use GuzzleHttp\Event\ProgressEvent;
463
+
464
+ $client = new Client(['base_url' => 'http://httpbin.org']);
465
+ $request = $client->createRequest('PUT', '/put', [
466
+ 'body' => str_repeat('.', 100000)
467
+ ]);
468
+
469
+ $request->getEmitter()->on('progress', function (ProgressEvent $e) {
470
+ echo 'Downloaded ' . $e->downloaded . ' of ' . $e->downloadSize . ' '
471
+ . 'Uploaded ' . $e->uploaded . ' of ' . $e->uploadSize . "\r";
472
+ });
473
+
474
+ $client->send($request);
475
+ echo "\n";
476
+
477
+ .. _end_event:
478
+
479
+ end
480
+ ---
481
+
482
+ The ``end`` event is a terminal event, emitted once per request, that provides
483
+ access to the repsonse that was received or the exception that was encountered.
484
+ The event emitted is a ``GuzzleHttp\Event\EndEvent``.
485
+
486
+ This event can be intercepted, but keep in mind that the ``complete`` event
487
+ will not fire after intercepting this event.
488
+
489
+ .. code-block:: php
490
+
491
+ use GuzzleHttp\Client;
492
+ use GuzzleHttp\Event\EndEvent;
493
+
494
+ $client = new Client(['base_url' => 'http://httpbin.org']);
495
+ $request = $client->createRequest('PUT', '/put', [
496
+ 'body' => str_repeat('.', 100000)
497
+ ]);
498
+
499
+ $request->getEmitter()->on('end', function (EndEvent $e) {
500
+ if ($e->getException()) {
501
+ echo 'Error: ' . $e->getException()->getMessage();
502
+ } else {
503
+ echo 'Response: ' . $e->getResponse();
504
+ }
505
+ });
506
+
507
+ $client->send($request);
508
+ echo "\n";
backend/vendor/guzzlehttp/guzzle/docs/faq.rst ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ===
2
+ FAQ
3
+ ===
4
+
5
+ Why should I use Guzzle?
6
+ ========================
7
+
8
+ Guzzle makes it easy to send HTTP requests and super simple to integrate with
9
+ web services. Guzzle manages things like persistent connections, represents
10
+ query strings as collections, makes it simple to send streaming POST requests
11
+ with fields and files, and abstracts away the underlying HTTP transport layer.
12
+ By providing an object oriented interface for HTTP clients, requests, responses,
13
+ headers, and message bodies, Guzzle makes it so that you no longer need to fool
14
+ around with cURL options, stream contexts, or sockets.
15
+
16
+ **Asynchronous and Synchronous Requests**
17
+
18
+ Guzzle allows you to send both asynchronous and synchronous requests using the
19
+ same interface and no direct dependency on an event loop. This flexibility
20
+ allows Guzzle to send an HTTP request using the most appropriate HTTP handler
21
+ based on the request being sent. For example, when sending synchronous
22
+ requests, Guzzle will by default send requests using cURL easy handles to
23
+ ensure you're using the fastest possible method for serially transferring HTTP
24
+ requests. When sending asynchronous requests, Guzzle might use cURL's multi
25
+ interface or any other asynchronous handler you configure. When you request
26
+ streaming data, Guzzle will by default use PHP's stream wrapper.
27
+
28
+ **Streams**
29
+
30
+ Request and response message bodies use :doc:`Guzzle Streams <streams>`,
31
+ allowing you to stream data without needing to load it all into memory.
32
+ Guzzle's stream layer provides a large suite of functionality:
33
+
34
+ - You can modify streams at runtime using custom or a number of
35
+ pre-made decorators.
36
+ - You can emit progress events as data is read from a stream.
37
+ - You can validate the integrity of a stream using a rolling hash as data is
38
+ read from a stream.
39
+
40
+ **Event System and Plugins**
41
+
42
+ Guzzle's event system allows you to completely modify the behavior of a client
43
+ or request at runtime to cater them for any API. You can send a request with a
44
+ client, and the client can do things like automatically retry your request if
45
+ it fails, automatically redirect, log HTTP messages that are sent over the
46
+ wire, emit progress events as data is uploaded and downloaded, sign requests
47
+ using OAuth 1.0, verify the integrity of messages before and after they are
48
+ sent over the wire, and anything else you might need.
49
+
50
+ **Testable**
51
+
52
+ Another important aspect of Guzzle is that it's really
53
+ :doc:`easy to test clients <testing>`. You can mock HTTP responses and when
54
+ testing an handler implementation, Guzzle provides a mock node.js web server.
55
+
56
+ **Ecosystem**
57
+
58
+ Guzzle has a large `ecosystem of plugins <http://guzzle.readthedocs.org/en/latest/index.html#http-components>`_,
59
+ including `service descriptions <https://github.com/guzzle/guzzle-services>`_
60
+ which allows you to abstract web services using service descriptions. These
61
+ service descriptions define how to serialize an HTTP request and how to parse
62
+ an HTTP response into a more meaningful model object.
63
+
64
+ - `Guzzle Command <https://github.com/guzzle/command>`_: Provides the building
65
+ blocks for service description abstraction.
66
+ - `Guzzle Services <https://github.com/guzzle/guzzle-services>`_: Provides an
67
+ implementation of "Guzzle Command" that utlizes Guzzle's service description
68
+ format.
69
+
70
+ Does Guzzle require cURL?
71
+ =========================
72
+
73
+ No. Guzzle can use any HTTP handler to send requests. This means that Guzzle
74
+ can be used with cURL, PHP's stream wrapper, sockets, and non-blocking libraries
75
+ like `React <http://reactphp.org/>`_. You just need to configure a
76
+ `RingPHP <http://guzzle-ring.readthedocs.org/en/latest/>`_ handler to use a
77
+ different method of sending requests.
78
+
79
+ .. note::
80
+
81
+ Guzzle has historically only utilized cURL to send HTTP requests. cURL is
82
+ an amazing HTTP client (arguably the best), and Guzzle will continue to use
83
+ it by default when it is available. It is rare, but some developers don't
84
+ have cURL installed on their systems or run into version specific issues.
85
+ By allowing swappable HTTP handlers, Guzzle is now much more customizable
86
+ and able to adapt to fit the needs of more developers.
87
+
88
+ Can Guzzle send asynchronous requests?
89
+ ======================================
90
+
91
+ Yes. Pass the ``future`` true request option to a request to send it
92
+ asynchronously. Guzzle will then return a ``GuzzleHttp\Message\FutureResponse``
93
+ object that can be used synchronously by accessing the response object like a
94
+ normal response, and it can be used asynchronoulsy using a promise that is
95
+ notified when the response is resolved with a real response or rejected with an
96
+ exception.
97
+
98
+ .. code-block:: php
99
+
100
+ $request = $client->createRequest('GET', ['future' => true]);
101
+ $client->send($request)->then(function ($response) {
102
+ echo 'Got a response! ' . $response;
103
+ });
104
+
105
+ You can force an asynchronous response to complete using the ``wait()`` method
106
+ of a response.
107
+
108
+ .. code-block:: php
109
+
110
+ $request = $client->createRequest('GET', ['future' => true]);
111
+ $futureResponse = $client->send($request);
112
+ $futureResponse->wait();
113
+
114
+ How can I add custom cURL options?
115
+ ==================================
116
+
117
+ cURL offer a huge number of `customizable options <http://us1.php.net/curl_setopt>`_.
118
+ While Guzzle normalizes many of these options across different handlers, there
119
+ are times when you need to set custom cURL options. This can be accomplished
120
+ by passing an associative array of cURL settings in the **curl** key of the
121
+ **config** request option.
122
+
123
+ For example, let's say you need to customize the outgoing network interface
124
+ used with a client.
125
+
126
+ .. code-block:: php
127
+
128
+ $client->get('/', [
129
+ 'config' => [
130
+ 'curl' => [
131
+ CURLOPT_INTERFACE => 'xxx.xxx.xxx.xxx'
132
+ ]
133
+ ]
134
+ ]);
135
+
136
+ How can I add custom stream context options?
137
+ ============================================
138
+
139
+ You can pass custom `stream context options <http://www.php.net/manual/en/context.php>`_
140
+ using the **stream_context** key of the **config** request option. The
141
+ **stream_context** array is an associative array where each key is a PHP
142
+ transport, and each value is an associative array of transport options.
143
+
144
+ For example, let's say you need to customize the outgoing network interface
145
+ used with a client and allow self-signed certificates.
146
+
147
+ .. code-block:: php
148
+
149
+ $client->get('/', [
150
+ 'stream' => true,
151
+ 'config' => [
152
+ 'stream_context' => [
153
+ 'ssl' => [
154
+ 'allow_self_signed' => true
155
+ ],
156
+ 'socket' => [
157
+ 'bindto' => 'xxx.xxx.xxx.xxx'
158
+ ]
159
+ ]
160
+ ]
161
+ ]);
162
+
163
+ Why am I getting an SSL verification error?
164
+ ===========================================
165
+
166
+ You need to specify the path on disk to the CA bundle used by Guzzle for
167
+ verifying the peer certificate. See :ref:`verify-option`.
168
+
169
+ What is this Maximum function nesting error?
170
+ ============================================
171
+
172
+ Maximum function nesting level of '100' reached, aborting
173
+
174
+ You could run into this error if you have the XDebug extension installed and
175
+ you execute a lot of requests in callbacks. This error message comes
176
+ specifically from the XDebug extension. PHP itself does not have a function
177
+ nesting limit. Change this setting in your php.ini to increase the limit::
178
+
179
+ xdebug.max_nesting_level = 1000
180
+
181
+ Why am I getting a 417 error response?
182
+ ======================================
183
+
184
+ This can occur for a number of reasons, but if you are sending PUT, POST, or
185
+ PATCH requests with an ``Expect: 100-Continue`` header, a server that does not
186
+ support this header will return a 417 response. You can work around this by
187
+ setting the ``expect`` request option to ``false``:
188
+
189
+ .. code-block:: php
190
+
191
+ $client = new GuzzleHttp\Client();
192
+
193
+ // Disable the expect header on a single request
194
+ $response = $client->put('/', [], 'the body', [
195
+ 'expect' => false
196
+ ]);
197
+
198
+ // Disable the expect header on all client requests
199
+ $client->setDefaultOption('expect', false)
backend/vendor/guzzlehttp/guzzle/docs/handlers.rst ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ================
2
+ RingPHP Handlers
3
+ ================
4
+
5
+ Guzzle uses RingPHP handlers to send HTTP requests over the wire.
6
+ RingPHP provides a low-level library that can be used to "glue" Guzzle with
7
+ any transport method you choose. By default, Guzzle utilizes cURL and PHP's
8
+ stream wrappers to send HTTP requests.
9
+
10
+ RingPHP handlers makes it extremely simple to integrate Guzzle with any
11
+ HTTP transport. For example, you could quite easily bridge Guzzle and React
12
+ to use Guzzle in React's event loop.
13
+
14
+ Using a handler
15
+ ---------------
16
+
17
+ You can change the handler used by a client using the ``handler`` option in the
18
+ ``GuzzleHttp\Client`` constructor.
19
+
20
+ .. code-block:: php
21
+
22
+ use GuzzleHttp\Client;
23
+ use GuzzleHttp\Ring\Client\MockHandler;
24
+
25
+ // Create a mock handler that always returns a 200 response.
26
+ $handler = new MockHandler(['status' => 200]);
27
+
28
+ // Configure to client to use the mock handler.
29
+ $client = new Client(['handler' => $handler]);
30
+
31
+ At its core, handlers are simply PHP callables that accept a request array
32
+ and return a ``GuzzleHttp\Ring\Future\FutureArrayInterface``. This future array
33
+ can be used just like a normal PHP array, causing it to block, or you can use
34
+ the promise interface using the ``then()`` method of the future. Guzzle hooks
35
+ up to the RingPHP project using a very simple bridge class
36
+ (``GuzzleHttp\RingBridge``).
37
+
38
+ Creating a handler
39
+ ------------------
40
+
41
+ See the `RingPHP <http://ringphp.readthedocs.org>`_ project
42
+ documentation for more information on creating custom handlers that can be
43
+ used with Guzzle clients.
backend/vendor/guzzlehttp/guzzle/docs/http-messages.rst ADDED
@@ -0,0 +1,483 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =============================
2
+ Request and Response Messages
3
+ =============================
4
+
5
+ Guzzle is an HTTP client that sends HTTP requests to a server and receives HTTP
6
+ responses. Both requests and responses are referred to as messages.
7
+
8
+ Headers
9
+ =======
10
+
11
+ Both request and response messages contain HTTP headers.
12
+
13
+ Complex Headers
14
+ ---------------
15
+
16
+ Some headers contain additional key value pair information. For example, Link
17
+ headers contain a link and several key value pairs:
18
+
19
+ ::
20
+
21
+ <http://foo.com>; rel="thing"; type="image/jpeg"
22
+
23
+ Guzzle provides a convenience feature that can be used to parse these types of
24
+ headers:
25
+
26
+ .. code-block:: php
27
+
28
+ use GuzzleHttp\Message\Request;
29
+
30
+ $request = new Request('GET', '/', [
31
+ 'Link' => '<http:/.../front.jpeg>; rel="front"; type="image/jpeg"'
32
+ ]);
33
+
34
+ $parsed = Request::parseHeader($request, 'Link');
35
+ var_export($parsed);
36
+
37
+ Will output:
38
+
39
+ .. code-block:: php
40
+
41
+ array (
42
+ 0 =>
43
+ array (
44
+ 0 => '<http:/.../front.jpeg>',
45
+ 'rel' => 'front',
46
+ 'type' => 'image/jpeg',
47
+ ),
48
+ )
49
+
50
+ The result contains a hash of key value pairs. Header values that have no key
51
+ (i.e., the link) are indexed numerically while headers parts that form a key
52
+ value pair are added as a key value pair.
53
+
54
+ See :ref:`headers` for information on how the headers of a request and response
55
+ can be accessed and modified.
56
+
57
+ Body
58
+ ====
59
+
60
+ Both request and response messages can contain a body.
61
+
62
+ You can check to see if a request or response has a body using the
63
+ ``getBody()`` method:
64
+
65
+ .. code-block:: php
66
+
67
+ $response = GuzzleHttp\get('http://httpbin.org/get');
68
+ if ($response->getBody()) {
69
+ echo $response->getBody();
70
+ // JSON string: { ... }
71
+ }
72
+
73
+ The body used in request and response objects is a
74
+ ``GuzzleHttp\Stream\StreamInterface``. This stream is used for both uploading
75
+ data and downloading data. Guzzle will, by default, store the body of a message
76
+ in a stream that uses PHP temp streams. When the size of the body exceeds
77
+ 2 MB, the stream will automatically switch to storing data on disk rather than
78
+ in memory (protecting your application from memory exhaustion).
79
+
80
+ You can change the body used in a request or response using the ``setBody()``
81
+ method:
82
+
83
+ .. code-block:: php
84
+
85
+ use GuzzleHttp\Stream\Stream;
86
+ $request = $client->createRequest('PUT', 'http://httpbin.org/put');
87
+ $request->setBody(Stream::factory('foo'));
88
+
89
+ The easiest way to create a body for a request is using the static
90
+ ``GuzzleHttp\Stream\Stream::factory()`` method. This method accepts various
91
+ inputs like strings, resources returned from ``fopen()``, and other
92
+ ``GuzzleHttp\Stream\StreamInterface`` objects.
93
+
94
+ The body of a request or response can be cast to a string or you can read and
95
+ write bytes off of the stream as needed.
96
+
97
+ .. code-block:: php
98
+
99
+ use GuzzleHttp\Stream\Stream;
100
+ $request = $client->createRequest('PUT', 'http://httpbin.org/put', ['body' => 'testing...']);
101
+
102
+ echo $request->getBody()->read(4);
103
+ // test
104
+ echo $request->getBody()->read(4);
105
+ // ing.
106
+ echo $request->getBody()->read(1024);
107
+ // ..
108
+ var_export($request->eof());
109
+ // true
110
+
111
+ You can find out more about Guzzle stream objects in :doc:`streams`.
112
+
113
+ Requests
114
+ ========
115
+
116
+ Requests are sent from a client to a server. Requests include the method to
117
+ be applied to a resource, the identifier of the resource, and the protocol
118
+ version to use.
119
+
120
+ Clients are used to create request messages. More precisely, clients use
121
+ a ``GuzzleHttp\Message\MessageFactoryInterface`` to create request messages.
122
+ You create requests with a client using the ``createRequest()`` method.
123
+
124
+ .. code-block:: php
125
+
126
+ // Create a request but don't send it immediately
127
+ $request = $client->createRequest('GET', 'http://httpbin.org/get');
128
+
129
+ Request Methods
130
+ ---------------
131
+
132
+ When creating a request, you are expected to provide the HTTP method you wish
133
+ to perform. You can specify any method you'd like, including a custom method
134
+ that might not be part of RFC 7231 (like "MOVE").
135
+
136
+ .. code-block:: php
137
+
138
+ // Create a request using a completely custom HTTP method
139
+ $request = $client->createRequest('MOVE', 'http://httpbin.org/move', ['exceptions' => false]);
140
+
141
+ echo $request->getMethod();
142
+ // MOVE
143
+
144
+ $response = $client->send($request);
145
+ echo $response->getStatusCode();
146
+ // 405
147
+
148
+ You can create and send a request using methods on a client that map to the
149
+ HTTP method you wish to use.
150
+
151
+ :GET: ``$client->get('http://httpbin.org/get', [/** options **/])``
152
+ :POST: ``$client->post('http://httpbin.org/post', [/** options **/])``
153
+ :HEAD: ``$client->head('http://httpbin.org/get', [/** options **/])``
154
+ :PUT: ``$client->put('http://httpbin.org/put', [/** options **/])``
155
+ :DELETE: ``$client->delete('http://httpbin.org/delete', [/** options **/])``
156
+ :OPTIONS: ``$client->options('http://httpbin.org/get', [/** options **/])``
157
+ :PATCH: ``$client->patch('http://httpbin.org/put', [/** options **/])``
158
+
159
+ .. code-block:: php
160
+
161
+ $response = $client->patch('http://httpbin.org/patch', ['body' => 'content']);
162
+
163
+ Request URI
164
+ -----------
165
+
166
+ The resource you are requesting with an HTTP request is identified by the
167
+ path of the request, the query string, and the "Host" header of the request.
168
+
169
+ When creating a request, you can provide the entire resource URI as a URL.
170
+
171
+ .. code-block:: php
172
+
173
+ $response = $client->get('http://httbin.org/get?q=foo');
174
+
175
+ Using the above code, you will send a request that uses ``httpbin.org`` as
176
+ the Host header, sends the request over port 80, uses ``/get`` as the path,
177
+ and sends ``?q=foo`` as the query string. All of this is parsed automatically
178
+ from the provided URI.
179
+
180
+ Sometimes you don't know what the entire request will be when it is created.
181
+ In these cases, you can modify the request as needed before sending it using
182
+ the ``createRequest()`` method of the client and methods on the request that
183
+ allow you to change it.
184
+
185
+ .. code-block:: php
186
+
187
+ $request = $client->createRequest('GET', 'http://httbin.org');
188
+
189
+ You can change the path of the request using ``setPath()``:
190
+
191
+ .. code-block:: php
192
+
193
+ $request->setPath('/get');
194
+ echo $request->getPath();
195
+ // /get
196
+ echo $request->getUrl();
197
+ // http://httpbin.com/get
198
+
199
+ Scheme
200
+ ~~~~~~
201
+
202
+ The `scheme <http://tools.ietf.org/html/rfc3986#section-3.1>`_ of a request
203
+ specifies the protocol to use when sending the request. When using Guzzle, the
204
+ scheme can be set to "http" or "https".
205
+
206
+ You can change the scheme of the request using the ``setScheme()`` method:
207
+
208
+ .. code-block:: php
209
+
210
+ $request = $client->createRequest('GET', 'http://httbin.org');
211
+ $request->setScheme('https');
212
+ echo $request->getScheme();
213
+ // https
214
+ echo $request->getUrl();
215
+ // https://httpbin.com/get
216
+
217
+ Port
218
+ ~~~~
219
+
220
+ No port is necessary when using the "http" or "https" schemes, but you can
221
+ override the port using ``setPort()``. If you need to modify the port used with
222
+ the specified scheme from the default setting, then you must use the
223
+ ``setPort()`` method.
224
+
225
+ .. code-block:: php
226
+
227
+ $request = $client->createRequest('GET', 'http://httbin.org');
228
+ $request->setPort(8080);
229
+ echo $request->getPort();
230
+ // 8080
231
+ echo $request->getUrl();
232
+ // https://httpbin.com:8080/get
233
+
234
+ // Set the port back to the default value for the scheme
235
+ $request->setPort(443);
236
+ echo $request->getUrl();
237
+ // https://httpbin.com/get
238
+
239
+ Query string
240
+ ~~~~~~~~~~~~
241
+
242
+ You can get the query string of the request using the ``getQuery()`` method.
243
+ This method returns a ``GuzzleHttp\Query`` object. A Query object can be
244
+ accessed like a PHP array, iterated in a foreach statement like a PHP array,
245
+ and cast to a string.
246
+
247
+ .. code-block:: php
248
+
249
+ $request = $client->createRequest('GET', 'http://httbin.org');
250
+ $query = $request->getQuery();
251
+ $query['foo'] = 'bar';
252
+ $query['baz'] = 'bam';
253
+ $query['bam'] = ['test' => 'abc'];
254
+
255
+ echo $request->getQuery();
256
+ // foo=bar&baz=bam&bam%5Btest%5D=abc
257
+
258
+ echo $request->getQuery()['foo'];
259
+ // bar
260
+ echo $request->getQuery()->get('foo');
261
+ // bar
262
+ echo $request->getQuery()->get('foo');
263
+ // bar
264
+
265
+ var_export($request->getQuery()['bam']);
266
+ // array('test' => 'abc')
267
+
268
+ foreach ($query as $key => $value) {
269
+ var_export($value);
270
+ }
271
+
272
+ echo $request->getUrl();
273
+ // https://httpbin.com/get?foo=bar&baz=bam&bam%5Btest%5D=abc
274
+
275
+ Query Aggregators
276
+ ^^^^^^^^^^^^^^^^^
277
+
278
+ Query objects can store scalar values or arrays of values. When an array of
279
+ values is added to a query object, the query object uses a query aggregator to
280
+ convert the complex structure into a string. Query objects will use
281
+ `PHP style query strings <http://www.php.net/http_build_query>`_ when complex
282
+ query string parameters are converted to a string. You can customize how
283
+ complex query string parameters are aggregated using the ``setAggregator()``
284
+ method of a query string object.
285
+
286
+ .. code-block:: php
287
+
288
+ $query->setAggregator($query::duplicateAggregator());
289
+
290
+ In the above example, we've changed the query object to use the
291
+ "duplicateAggregator". This aggregator will allow duplicate entries to appear
292
+ in a query string rather than appending "[n]" to each value. So if you had a
293
+ query string with ``['a' => ['b', 'c']]``, the duplicate aggregator would
294
+ convert this to "a=b&a=c" while the default aggregator would convert this to
295
+ "a[0]=b&a[1]=c" (with urlencoded brackets).
296
+
297
+ The ``setAggregator()`` method accepts a ``callable`` which is used to convert
298
+ a deeply nested array of query string variables into a flattened array of key
299
+ value pairs. The callable accepts an array of query data and returns a
300
+ flattened array of key value pairs where each value is an array of strings.
301
+ You can use the ``GuzzleHttp\Query::walkQuery()`` static function to easily
302
+ create custom query aggregators.
303
+
304
+ Host
305
+ ~~~~
306
+
307
+ You can change the host header of the request in a predictable way using the
308
+ ``setHost()`` method of a request:
309
+
310
+ .. code-block:: php
311
+
312
+ $request->setHost('www.google.com');
313
+ echo $request->getHost();
314
+ // www.google.com
315
+ echo $request->getUrl();
316
+ // https://www.google.com/get?foo=bar&baz=bam
317
+
318
+ .. note::
319
+
320
+ The Host header can also be changed by modifying the Host header of a
321
+ request directly, but modifying the Host header directly could result in
322
+ sending a request to a different Host than what is specified in the Host
323
+ header (sometimes this is actually the desired behavior).
324
+
325
+ Resource
326
+ ~~~~~~~~
327
+
328
+ You can use the ``getResource()`` method of a request to return the path and
329
+ query string of a request in a single string.
330
+
331
+ .. code-block:: php
332
+
333
+ $request = $client->createRequest('GET', 'http://httpbin.org/get?baz=bar');
334
+ echo $request->getResource();
335
+ // /get?baz=bar
336
+
337
+ Request Config
338
+ --------------
339
+
340
+ Request messages contain a configuration collection that can be used by
341
+ event listeners and HTTP handlers to modify how a request behaves or is
342
+ transferred over the wire. For example, many of the request options that are
343
+ specified when creating a request are actually set as config options that are
344
+ only acted upon by handlers and listeners when the request is sent.
345
+
346
+ You can get access to the request's config object using the ``getConfig()``
347
+ method of a request.
348
+
349
+ .. code-block:: php
350
+
351
+ $request = $client->createRequest('GET', '/');
352
+ $config = $request->getConfig();
353
+
354
+ The config object is a ``GuzzleHttp\Common\Collection`` object that acts like
355
+ an associative array. You can grab values from the collection using array like
356
+ access. You can also modify and remove values using array like access.
357
+
358
+ .. code-block:: php
359
+
360
+ $config['foo'] = 'bar';
361
+ echo $config['foo'];
362
+ // bar
363
+
364
+ var_export(isset($config['foo']));
365
+ // true
366
+
367
+ unset($config['foo']);
368
+ var_export(isset($config['foo']));
369
+ // false
370
+
371
+ var_export($config['foo']);
372
+ // NULL
373
+
374
+ HTTP handlers and event listeners can expose additional customization options
375
+ through request config settings. For example, in order to specify custom cURL
376
+ options to the cURL handler, you need to specify an associative array in the
377
+ ``curl`` ``config`` request option.
378
+
379
+ .. code-block:: php
380
+
381
+ $client->get('/', [
382
+ 'config' => [
383
+ 'curl' => [
384
+ CURLOPT_HTTPAUTH => CURLAUTH_NTLM,
385
+ CURLOPT_USERPWD => 'username:password'
386
+ ]
387
+ ]
388
+ ]);
389
+
390
+ Consult the HTTP handlers and event listeners you are using to see if they
391
+ allow customization through request configuration options.
392
+
393
+ Event Emitter
394
+ -------------
395
+
396
+ Request objects implement ``GuzzleHttp\Common\HasEmitterInterface``, so they
397
+ have a method called ``getEmitter()`` that can be used to get an event emitter
398
+ used by the request. Any listener or subscriber attached to a request will only
399
+ be triggered for the lifecycle events of a specific request. Conversely, adding
400
+ an event listener or subscriber to a client will listen to all lifecycle events
401
+ of all requests created by the client.
402
+
403
+ See :doc:`events` for more information.
404
+
405
+ Responses
406
+ =========
407
+
408
+ Responses are the HTTP messages a client receives from a server after sending
409
+ an HTTP request message.
410
+
411
+ Start-Line
412
+ ----------
413
+
414
+ The start-line of a response contains the protocol and protocol version,
415
+ status code, and reason phrase.
416
+
417
+ .. code-block:: php
418
+
419
+ $response = GuzzleHttp\get('http://httpbin.org/get');
420
+ echo $response->getStatusCode();
421
+ // 200
422
+ echo $response->getReasonPhrase();
423
+ // OK
424
+ echo $response->getProtocolVersion();
425
+ // 1.1
426
+
427
+ Body
428
+ ----
429
+
430
+ As described earlier, you can get the body of a response using the
431
+ ``getBody()`` method.
432
+
433
+ .. code-block:: php
434
+
435
+ if ($body = $response->getBody()) {
436
+ echo $body;
437
+ // Cast to a string: { ... }
438
+ $body->seek(0);
439
+ // Rewind the body
440
+ $body->read(1024);
441
+ // Read bytes of the body
442
+ }
443
+
444
+ When working with JSON responses, you can use the ``json()`` method of a
445
+ response:
446
+
447
+ .. code-block:: php
448
+
449
+ $json = $response->json();
450
+
451
+ .. note::
452
+
453
+ Guzzle uses the ``json_decode()`` method of PHP and uses arrays rather than
454
+ ``stdClass`` objects for objects.
455
+
456
+ You can use the ``xml()`` method when working with XML data.
457
+
458
+ .. code-block:: php
459
+
460
+ $xml = $response->xml();
461
+
462
+ .. note::
463
+
464
+ Guzzle uses the ``SimpleXMLElement`` objects when converting response
465
+ bodies to XML.
466
+
467
+ Effective URL
468
+ -------------
469
+
470
+ The URL that was ultimately accessed that returned a response can be accessed
471
+ using the ``getEffectiveUrl()`` method of a response. This method will return
472
+ the URL of a request or the URL of the last redirected URL if any redirects
473
+ occurred while transferring a request.
474
+
475
+ .. code-block:: php
476
+
477
+ $response = GuzzleHttp\get('http://httpbin.org/get');
478
+ echo $response->getEffectiveUrl();
479
+ // http://httpbin.org/get
480
+
481
+ $response = GuzzleHttp\get('http://httpbin.org/redirect-to?url=http://www.google.com');
482
+ echo $response->getEffectiveUrl();
483
+ // http://www.google.com
backend/vendor/guzzlehttp/guzzle/docs/index.rst ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .. title:: Guzzle | PHP HTTP client and framework for consuming RESTful web services
2
+
3
+ ======
4
+ Guzzle
5
+ ======
6
+
7
+ Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
8
+ trivial to integrate with web services.
9
+
10
+ - Manages things like persistent connections, represents query strings as
11
+ collections, simplifies sending streaming POST requests with fields and
12
+ files, and abstracts away the underlying HTTP transport layer.
13
+ - Can send both synchronous and asynchronous requests using the same interface
14
+ without requiring a dependency on a specific event loop.
15
+ - Pluggable HTTP handlers allows Guzzle to integrate with any method you choose
16
+ for sending HTTP requests over the wire (e.g., cURL, sockets, PHP's stream
17
+ wrapper, non-blocking event loops like `React <http://reactphp.org/>`_, etc.).
18
+ - Guzzle makes it so that you no longer need to fool around with cURL options,
19
+ stream contexts, or sockets.
20
+
21
+ .. code-block:: php
22
+
23
+ $client = new GuzzleHttp\Client();
24
+ $response = $client->get('http://guzzlephp.org');
25
+ $res = $client->get('https://api.github.com/user', ['auth' => ['user', 'pass']]);
26
+ echo $res->getStatusCode();
27
+ // "200"
28
+ echo $res->getHeader('content-type');
29
+ // 'application/json; charset=utf8'
30
+ echo $res->getBody();
31
+ // {"type":"User"...'
32
+ var_export($res->json());
33
+ // Outputs the JSON decoded data
34
+
35
+ // Send an asynchronous request.
36
+ $req = $client->createRequest('GET', 'http://httpbin.org', ['future' => true]);
37
+ $client->send($req)->then(function ($response) {
38
+ echo 'I completed! ' . $response;
39
+ });
40
+
41
+ User guide
42
+ ----------
43
+
44
+ .. toctree::
45
+ :maxdepth: 2
46
+
47
+ overview
48
+ quickstart
49
+ clients
50
+ http-messages
51
+ events
52
+ streams
53
+ handlers
54
+ testing
55
+ faq
56
+
57
+ HTTP Components
58
+ ---------------
59
+
60
+ There are a number of optional libraries you can use along with Guzzle's HTTP
61
+ layer to add capabilities to the client.
62
+
63
+ `Log Subscriber <https://github.com/guzzle/log-subscriber>`_
64
+ Logs HTTP requests and responses sent over the wire using customizable
65
+ log message templates.
66
+
67
+ `OAuth Subscriber <https://github.com/guzzle/oauth-subscriber>`_
68
+ Signs requests using OAuth 1.0.
69
+
70
+ `Cache Subscriber <https://github.com/guzzle/cache-subscriber>`_
71
+ Implements a private transparent proxy cache that caches HTTP responses.
72
+
73
+ `Retry Subscriber <https://github.com/guzzle/retry-subscriber>`_
74
+ Retries failed requests using customizable retry strategies (e.g., retry
75
+ based on response status code, cURL error codes, etc.)
76
+
77
+ `Message Integrity Subscriber <https://github.com/guzzle/message-integrity-subscriber>`_
78
+ Verifies the message integrity of HTTP responses using customizable
79
+ validators. This plugin can be used, for example, to verify the Content-MD5
80
+ headers of responses.
81
+
82
+ Service Description Commands
83
+ ----------------------------
84
+
85
+ You can use the **Guzzle Command** library to encapsulate interaction with a
86
+ web service using command objects. Building on top of Guzzle's command
87
+ abstraction allows you to easily implement things like service description that
88
+ can be used to serialize requests and parse responses using a meta-description
89
+ of a web service.
90
+
91
+ `Guzzle Command <https://github.com/guzzle/command>`_
92
+ Provides the foundational elements used to build high-level, command based,
93
+ web service clients with Guzzle.
94
+
95
+ `Guzzle Services <https://github.com/guzzle/guzzle-services>`_
96
+ Provides an implementation of the *Guzzle Command* library that uses
97
+ Guzzle service descriptions to describe web services, serialize requests,
98
+ and parse responses into easy to use model structures.
backend/vendor/guzzlehttp/guzzle/docs/overview.rst ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ========
2
+ Overview
3
+ ========
4
+
5
+ Requirements
6
+ ============
7
+
8
+ #. PHP 5.4.0
9
+ #. To use the PHP stream handler, ``allow_url_fopen`` must be enabled in your
10
+ system's php.ini.
11
+ #. To use the cURL handler, you must have a recent version of cURL >= 7.16.2
12
+ compiled with OpenSSL and zlib.
13
+
14
+ .. note::
15
+
16
+ Guzzle no longer requires cURL in order to send HTTP requests. Guzzle will
17
+ use the PHP stream wrapper to send HTTP requests if cURL is not installed.
18
+ Alternatively, you can provide your own HTTP handler used to send requests.
19
+
20
+ .. _installation:
21
+
22
+ Installation
23
+ ============
24
+
25
+ The recommended way to install Guzzle is with `Composer <http://getcomposer.org>`_. Composer is a dependency
26
+ management tool for PHP that allows you to declare the dependencies your project needs and installs them into your
27
+ project.
28
+
29
+ .. code-block:: bash
30
+
31
+ # Install Composer
32
+ curl -sS https://getcomposer.org/installer | php
33
+
34
+ You can add Guzzle as a dependency using the composer.phar CLI:
35
+
36
+ .. code-block:: bash
37
+
38
+ php composer.phar require guzzlehttp/guzzle:~5.0
39
+
40
+ Alternatively, you can specify Guzzle as a dependency in your project's
41
+ existing composer.json file:
42
+
43
+ .. code-block:: js
44
+
45
+ {
46
+ "require": {
47
+ "guzzlehttp/guzzle": "~5.0"
48
+ }
49
+ }
50
+
51
+ After installing, you need to require Composer's autoloader:
52
+
53
+ .. code-block:: php
54
+
55
+ require 'vendor/autoload.php';
56
+
57
+ You can find out more on how to install Composer, configure autoloading, and
58
+ other best-practices for defining dependencies at `getcomposer.org <http://getcomposer.org>`_.
59
+
60
+ Bleeding edge
61
+ -------------
62
+
63
+ During your development, you can keep up with the latest changes on the master
64
+ branch by setting the version requirement for Guzzle to ``~5.0@dev``.
65
+
66
+ .. code-block:: js
67
+
68
+ {
69
+ "require": {
70
+ "guzzlehttp/guzzle": "~5.0@dev"
71
+ }
72
+ }
73
+
74
+ License
75
+ =======
76
+
77
+ Licensed using the `MIT license <http://opensource.org/licenses/MIT>`_.
78
+
79
+ Copyright (c) 2014 Michael Dowling <https://github.com/mtdowling>
80
+
81
+ Permission is hereby granted, free of charge, to any person obtaining a copy
82
+ of this software and associated documentation files (the "Software"), to deal
83
+ in the Software without restriction, including without limitation the rights
84
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
85
+ copies of the Software, and to permit persons to whom the Software is
86
+ furnished to do so, subject to the following conditions:
87
+
88
+ The above copyright notice and this permission notice shall be included in
89
+ all copies or substantial portions of the Software.
90
+
91
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
92
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
93
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
94
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
95
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
96
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
97
+ THE SOFTWARE.
98
+
99
+ Contributing
100
+ ============
101
+
102
+ Guidelines
103
+ ----------
104
+
105
+ 1. Guzzle follows PSR-0, PSR-1, and PSR-2.
106
+ 2. Guzzle is meant to be lean and fast with very few dependencies.
107
+ 3. Guzzle has a minimum PHP version requirement of PHP 5.4. Pull requests must
108
+ not require a PHP version greater than PHP 5.4.
109
+ 4. All pull requests must include unit tests to ensure the change works as
110
+ expected and to prevent regressions.
111
+
112
+ Running the tests
113
+ -----------------
114
+
115
+ In order to contribute, you'll need to checkout the source from GitHub and
116
+ install Guzzle's dependencies using Composer:
117
+
118
+ .. code-block:: bash
119
+
120
+ git clone https://github.com/guzzle/guzzle.git
121
+ cd guzzle && curl -s http://getcomposer.org/installer | php && ./composer.phar install --dev
122
+
123
+ Guzzle is unit tested with PHPUnit. Run the tests using the vendored PHPUnit
124
+ binary:
125
+
126
+ .. code-block:: bash
127
+
128
+ vendor/bin/phpunit
129
+
130
+ .. note::
131
+
132
+ You'll need to install node.js v0.5.0 or newer in order to perform
133
+ integration tests on Guzzle's HTTP handlers.
134
+
135
+ Reporting a security vulnerability
136
+ ==================================
137
+
138
+ We want to ensure that Guzzle is a secure HTTP client library for everyone. If
139
+ you've discovered a security vulnerability in Guzzle, we appreciate your help
140
+ in disclosing it to us in a `responsible manner <http://en.wikipedia.org/wiki/Responsible_disclosure>`_.
141
+
142
+ Publicly disclosing a vulnerability can put the entire community at risk. If
143
+ you've discovered a security concern, please email us at
144
+ security@guzzlephp.org. We'll work with you to make sure that we understand the
145
+ scope of the issue, and that we fully address your concern. We consider
146
+ correspondence sent to security@guzzlephp.org our highest priority, and work to
147
+ address any issues that arise as quickly as possible.
148
+
149
+ After a security vulnerability has been corrected, a security hotfix release will
150
+ be deployed as soon as possible.
backend/vendor/guzzlehttp/guzzle/docs/quickstart.rst ADDED
@@ -0,0 +1,448 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ==========
2
+ Quickstart
3
+ ==========
4
+
5
+ This page provides a quick introduction to Guzzle and introductory examples.
6
+ If you have not already installed, Guzzle, head over to the :ref:`installation`
7
+ page.
8
+
9
+ Make a Request
10
+ ==============
11
+
12
+ You can send requests with Guzzle using a ``GuzzleHttp\ClientInterface``
13
+ object.
14
+
15
+ Creating a Client
16
+ -----------------
17
+
18
+ The procedural API is simple but not very testable; it's best left for quick
19
+ prototyping. If you want to use Guzzle in a more flexible and testable way,
20
+ then you'll need to use a ``GuzzleHttp\ClientInterface`` object.
21
+
22
+ .. code-block:: php
23
+
24
+ use GuzzleHttp\Client;
25
+
26
+ $client = new Client();
27
+ $response = $client->get('http://httpbin.org/get');
28
+
29
+ // You can use the same methods you saw in the procedural API
30
+ $response = $client->delete('http://httpbin.org/delete');
31
+ $response = $client->head('http://httpbin.org/get');
32
+ $response = $client->options('http://httpbin.org/get');
33
+ $response = $client->patch('http://httpbin.org/patch');
34
+ $response = $client->post('http://httpbin.org/post');
35
+ $response = $client->put('http://httpbin.org/put');
36
+
37
+ You can create a request with a client and then send the request with the
38
+ client when you're ready.
39
+
40
+ .. code-block:: php
41
+
42
+ $request = $client->createRequest('GET', 'http://www.foo.com');
43
+ $response = $client->send($request);
44
+
45
+ Client objects provide a great deal of flexibility in how request are
46
+ transferred including default request options, subscribers that are attached
47
+ to each request, and a base URL that allows you to send requests with relative
48
+ URLs. You can find out all about clients in the :doc:`clients` page of the
49
+ documentation.
50
+
51
+ Using Responses
52
+ ===============
53
+
54
+ In the previous examples, we retrieved a ``$response`` variable. This value is
55
+ actually a ``GuzzleHttp\Message\ResponseInterface`` object and contains lots
56
+ of helpful information.
57
+
58
+ You can get the status code and reason phrase of the response.
59
+
60
+ .. code-block:: php
61
+
62
+ $code = $response->getStatusCode();
63
+ // 200
64
+
65
+ $reason = $response->getReasonPhrase();
66
+ // OK
67
+
68
+ By providing the ``future`` request option to a request, you can send requests
69
+ asynchronously using the promise interface of a future response.
70
+
71
+ .. code-block:: php
72
+
73
+ $client->get('http://httpbin.org', ['future' => true])
74
+ ->then(function ($response) {
75
+ echo $response->getStatusCode();
76
+ });
77
+
78
+ Response Body
79
+ -------------
80
+
81
+ The body of a response can be retrieved and cast to a string.
82
+
83
+ .. code-block:: php
84
+
85
+ $body = $response->getBody();
86
+ echo $body;
87
+ // { "some_json_data" ...}
88
+
89
+ You can also read read bytes from body of a response like a stream.
90
+
91
+ .. code-block:: php
92
+
93
+ $body = $response->getBody();
94
+
95
+ while (!$body->eof()) {
96
+ echo $body->read(1024);
97
+ }
98
+
99
+ JSON Responses
100
+ ~~~~~~~~~~~~~~
101
+
102
+ You can more easily work with JSON responses using the ``json()`` method of a
103
+ response.
104
+
105
+ .. code-block:: php
106
+
107
+ $response = $client->get('http://httpbin.org/get');
108
+ $json = $response->json();
109
+ var_dump($json[0]['origin']);
110
+
111
+ Guzzle internally uses PHP's ``json_decode()`` function to parse responses. If
112
+ Guzzle is unable to parse the JSON response body, then a
113
+ ``GuzzleHttp\Exception\ParseException`` is thrown.
114
+
115
+ XML Responses
116
+ ~~~~~~~~~~~~~
117
+
118
+ You can use a response's ``xml()`` method to more easily work with responses
119
+ that contain XML data.
120
+
121
+ .. code-block:: php
122
+
123
+ $response = $client->get('https://github.com/mtdowling.atom');
124
+ $xml = $response->xml();
125
+ echo $xml->id;
126
+ // tag:github.com,2008:/mtdowling
127
+
128
+ Guzzle internally uses a ``SimpleXMLElement`` object to parse responses. If
129
+ Guzzle is unable to parse the XML response body, then a
130
+ ``GuzzleHttp\Exception\ParseException`` is thrown.
131
+
132
+ Query String Parameters
133
+ =======================
134
+
135
+ Sending query string parameters with a request is easy. You can set query
136
+ string parameters in the request's URL.
137
+
138
+ .. code-block:: php
139
+
140
+ $response = $client->get('http://httpbin.org?foo=bar');
141
+
142
+ You can also specify the query string parameters using the ``query`` request
143
+ option.
144
+
145
+ .. code-block:: php
146
+
147
+ $client->get('http://httpbin.org', [
148
+ 'query' => ['foo' => 'bar']
149
+ ]);
150
+
151
+ And finally, you can build up the query string of a request as needed by
152
+ calling the ``getQuery()`` method of a request and modifying the request's
153
+ ``GuzzleHttp\Query`` object as needed.
154
+
155
+ .. code-block:: php
156
+
157
+ $request = $client->createRequest('GET', 'http://httpbin.org');
158
+ $query = $request->getQuery();
159
+ $query->set('foo', 'bar');
160
+
161
+ // You can use the query string object like an array
162
+ $query['baz'] = 'bam';
163
+
164
+ // The query object can be cast to a string
165
+ echo $query;
166
+ // foo=bar&baz=bam
167
+
168
+ // Setting a value to false or null will cause the "=" sign to be omitted
169
+ $query['empty'] = null;
170
+ echo $query;
171
+ // foo=bar&baz=bam&empty
172
+
173
+ // Use an empty string to include the "=" sign with an empty value
174
+ $query['empty'] = '';
175
+ echo $query;
176
+ // foo=bar&baz=bam&empty=
177
+
178
+ .. _headers:
179
+
180
+ Request and Response Headers
181
+ ----------------------------
182
+
183
+ You can specify request headers when sending or creating requests with a
184
+ client. In the following example, we send the ``X-Foo-Header`` with a value of
185
+ ``value`` by setting the ``headers`` request option.
186
+
187
+ .. code-block:: php
188
+
189
+ $response = $client->get('http://httpbin.org/get', [
190
+ 'headers' => ['X-Foo-Header' => 'value']
191
+ ]);
192
+
193
+ You can view the headers of a response using header specific methods of a
194
+ response class. Headers work exactly the same way for request and response
195
+ object.
196
+
197
+ You can retrieve a header from a request or response using the ``getHeader()``
198
+ method of the object. This method is case-insensitive and by default will
199
+ return a string containing the header field value.
200
+
201
+ .. code-block:: php
202
+
203
+ $response = $client->get('http://www.yahoo.com');
204
+ $length = $response->getHeader('Content-Length');
205
+
206
+ Header fields that contain multiple values can be retrieved as a string or as
207
+ an array. Retrieving the field values as a string will naively concatenate all
208
+ of the header values together with a comma. Because not all header fields
209
+ should be represented this way (e.g., ``Set-Cookie``), you can pass an optional
210
+ flag to the ``getHeader()`` method to retrieve the header values as an array.
211
+
212
+ .. code-block:: php
213
+
214
+ $values = $response->getHeader('Set-Cookie', true);
215
+ foreach ($values as $value) {
216
+ echo $value;
217
+ }
218
+
219
+ You can test if a request or response has a specific header using the
220
+ ``hasHeader()`` method. This method accepts a case-insensitive string and
221
+ returns true if the header is present or false if it is not.
222
+
223
+ You can retrieve all of the headers of a message using the ``getHeaders()``
224
+ method of a request or response. The return value is an associative array where
225
+ the keys represent the header name as it will be sent over the wire, and each
226
+ value is an array of strings associated with the header.
227
+
228
+ .. code-block:: php
229
+
230
+ $headers = $response->getHeaders();
231
+ foreach ($message->getHeaders() as $name => $values) {
232
+ echo $name . ": " . implode(", ", $values);
233
+ }
234
+
235
+ Modifying headers
236
+ -----------------
237
+
238
+ The headers of a message can be modified using the ``setHeader()``,
239
+ ``addHeader()``, ``setHeaders()``, and ``removeHeader()`` methods of a request
240
+ or response object.
241
+
242
+ .. code-block:: php
243
+
244
+ $request = $client->createRequest('GET', 'http://httpbin.org/get');
245
+
246
+ // Set a single value for a header
247
+ $request->setHeader('User-Agent', 'Testing!');
248
+
249
+ // Set multiple values for a header in one call
250
+ $request->setHeader('X-Foo', ['Baz', 'Bar']);
251
+
252
+ // Add a header to the message
253
+ $request->addHeader('X-Foo', 'Bam');
254
+
255
+ echo $request->getHeader('X-Foo');
256
+ // Baz, Bar, Bam
257
+
258
+ // Remove a specific header using a case-insensitive name
259
+ $request->removeHeader('x-foo');
260
+ echo $request->getHeader('X-Foo');
261
+ // Echoes an empty string: ''
262
+
263
+ Uploading Data
264
+ ==============
265
+
266
+ Guzzle provides several methods of uploading data.
267
+
268
+ You can send requests that contain a stream of data by passing a string,
269
+ resource returned from ``fopen``, or a ``GuzzleHttp\Stream\StreamInterface``
270
+ object to the ``body`` request option.
271
+
272
+ .. code-block:: php
273
+
274
+ $r = $client->post('http://httpbin.org/post', ['body' => 'raw data']);
275
+
276
+ You can easily upload JSON data using the ``json`` request option.
277
+
278
+ .. code-block:: php
279
+
280
+ $r = $client->put('http://httpbin.org/put', ['json' => ['foo' => 'bar']]);
281
+
282
+ POST Requests
283
+ -------------
284
+
285
+ In addition to specifying the raw data of a request using the ``body`` request
286
+ option, Guzzle provides helpful abstractions over sending POST data.
287
+
288
+ Sending POST Fields
289
+ ~~~~~~~~~~~~~~~~~~~
290
+
291
+ Sending ``application/x-www-form-urlencoded`` POST requests requires that you
292
+ specify the body of a POST request as an array.
293
+
294
+ .. code-block:: php
295
+
296
+ $response = $client->post('http://httpbin.org/post', [
297
+ 'body' => [
298
+ 'field_name' => 'abc',
299
+ 'other_field' => '123'
300
+ ]
301
+ ]);
302
+
303
+ You can also build up POST requests before sending them.
304
+
305
+ .. code-block:: php
306
+
307
+ $request = $client->createRequest('POST', 'http://httpbin.org/post');
308
+ $postBody = $request->getBody();
309
+
310
+ // $postBody is an instance of GuzzleHttp\Post\PostBodyInterface
311
+ $postBody->setField('foo', 'bar');
312
+ echo $postBody->getField('foo');
313
+ // 'bar'
314
+
315
+ echo json_encode($postBody->getFields());
316
+ // {"foo": "bar"}
317
+
318
+ // Send the POST request
319
+ $response = $client->send($request);
320
+
321
+ Sending POST Files
322
+ ~~~~~~~~~~~~~~~~~~
323
+
324
+ Sending ``multipart/form-data`` POST requests (POST requests that contain
325
+ files) is the same as sending ``application/x-www-form-urlencoded``, except
326
+ some of the array values of the POST fields map to PHP ``fopen`` resources, or
327
+ ``GuzzleHttp\Stream\StreamInterface``, or
328
+ ``GuzzleHttp\Post\PostFileInterface`` objects.
329
+
330
+ .. code-block:: php
331
+
332
+ use GuzzleHttp\Post\PostFile;
333
+
334
+ $response = $client->post('http://httpbin.org/post', [
335
+ 'body' => [
336
+ 'field_name' => 'abc',
337
+ 'file_filed' => fopen('/path/to/file', 'r'),
338
+ 'other_file' => new PostFile('other_file', 'this is the content')
339
+ ]
340
+ ]);
341
+
342
+ Just like when sending POST fields, you can also build up POST requests with
343
+ files before sending them.
344
+
345
+ .. code-block:: php
346
+
347
+ use GuzzleHttp\Post\PostFile;
348
+
349
+ $request = $client->createRequest('POST', 'http://httpbin.org/post');
350
+ $postBody = $request->getBody();
351
+ $postBody->setField('foo', 'bar');
352
+ $postBody->addFile(new PostFile('test', fopen('/path/to/file', 'r')));
353
+ $response = $client->send($request);
354
+
355
+ Cookies
356
+ =======
357
+
358
+ Guzzle can maintain a cookie session for you if instructed using the
359
+ ``cookies`` request option.
360
+
361
+ - Set to ``true`` to use a shared cookie session associated with the client.
362
+ - Pass an associative array containing cookies to send in the request and start
363
+ a new cookie session.
364
+ - Set to a ``GuzzleHttp\Subscriber\CookieJar\CookieJarInterface`` object to use
365
+ an existing cookie jar.
366
+
367
+ Redirects
368
+ =========
369
+
370
+ Guzzle will automatically follow redirects unless you tell it not to. You can
371
+ customize the redirect behavior using the ``allow_redirects`` request option.
372
+
373
+ - Set to true to enable normal redirects with a maximum number of 5 redirects.
374
+ This is the default setting.
375
+ - Set to false to disable redirects.
376
+ - Pass an associative array containing the 'max' key to specify the maximum
377
+ number of redirects and optionally provide a 'strict' key value to specify
378
+ whether or not to use strict RFC compliant redirects (meaning redirect POST
379
+ requests with POST requests vs. doing what most browsers do which is
380
+ redirect POST requests with GET requests).
381
+
382
+ .. code-block:: php
383
+
384
+ $response = $client->get('http://github.com');
385
+ echo $response->getStatusCode();
386
+ // 200
387
+ echo $response->getEffectiveUrl();
388
+ // 'https://github.com/'
389
+
390
+ The following example shows that redirects can be disabled.
391
+
392
+ .. code-block:: php
393
+
394
+ $response = $client->get('http://github.com', ['allow_redirects' => false]);
395
+ echo $response->getStatusCode();
396
+ // 301
397
+ echo $response->getEffectiveUrl();
398
+ // 'http://github.com/'
399
+
400
+ Exceptions
401
+ ==========
402
+
403
+ Guzzle throws exceptions for errors that occur during a transfer.
404
+
405
+ - In the event of a networking error (connection timeout, DNS errors, etc.),
406
+ a ``GuzzleHttp\Exception\RequestException`` is thrown. This exception
407
+ extends from ``GuzzleHttp\Exception\TransferException``. Catching this
408
+ exception will catch any exception that can be thrown while transferring
409
+ (non-parallel) requests.
410
+
411
+ .. code-block:: php
412
+
413
+ use GuzzleHttp\Exception\RequestException;
414
+
415
+ try {
416
+ $client->get('https://github.com/_abc_123_404');
417
+ } catch (RequestException $e) {
418
+ echo $e->getRequest();
419
+ if ($e->hasResponse()) {
420
+ echo $e->getResponse();
421
+ }
422
+ }
423
+
424
+ - A ``GuzzleHttp\Exception\ClientException`` is thrown for 400
425
+ level errors if the ``exceptions`` request option is set to true. This
426
+ exception extends from ``GuzzleHttp\Exception\BadResponseException`` and
427
+ ``GuzzleHttp\Exception\BadResponseException`` extends from
428
+ ``GuzzleHttp\Exception\RequestException``.
429
+
430
+ .. code-block:: php
431
+
432
+ use GuzzleHttp\Exception\ClientException;
433
+
434
+ try {
435
+ $client->get('https://github.com/_abc_123_404');
436
+ } catch (ClientException $e) {
437
+ echo $e->getRequest();
438
+ echo $e->getResponse();
439
+ }
440
+
441
+ - A ``GuzzleHttp\Exception\ServerException`` is thrown for 500 level
442
+ errors if the ``exceptions`` request option is set to true. This
443
+ exception extends from ``GuzzleHttp\Exception\BadResponseException``.
444
+ - A ``GuzzleHttp\Exception\TooManyRedirectsException`` is thrown when too
445
+ many redirects are followed. This exception extends from ``GuzzleHttp\Exception\RequestException``.
446
+
447
+ All of the above exceptions extend from
448
+ ``GuzzleHttp\Exception\TransferException``.
backend/vendor/guzzlehttp/guzzle/docs/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Sphinx>=1.2b1
2
+ guzzle_sphinx_theme>=0.6.0
backend/vendor/guzzlehttp/guzzle/docs/streams.rst ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ =======
2
+ Streams
3
+ =======
4
+
5
+ Guzzle uses stream objects to represent request and response message bodies.
6
+ These stream objects allow you to work with various types of data all using a
7
+ common interface.
8
+
9
+ HTTP messages consist of a start-line, headers, and a body. The body of an HTTP
10
+ message can be very small or extremely large. Attempting to represent the body
11
+ of a message as a string can easily consume more memory than intended because
12
+ the body must be stored completely in memory. Attempting to store the body of a
13
+ request or response in memory would preclude the use of that implementation from
14
+ being able to work with large message bodies. The StreamInterface is used in
15
+ order to hide the implementation details of where a stream of data is read from
16
+ or written to.
17
+
18
+ Guzzle's StreamInterface exposes several methods that enable streams to be read
19
+ from, written to, and traversed effectively.
20
+
21
+ Streams expose their capabilities using three methods: ``isReadable()``,
22
+ ``isWritable()``, and ``isSeekable()``. These methods can be used by stream
23
+ collaborators to determine if a stream is capable of their requirements.
24
+
25
+ Each stream instance has various capabilities: they can be read-only,
26
+ write-only, read-write, allow arbitrary random access (seeking forwards or
27
+ backwards to any location), or only allow sequential access (for example in the
28
+ case of a socket or pipe).
29
+
30
+ Creating Streams
31
+ ================
32
+
33
+ The best way to create a stream is using the static factory method,
34
+ ``GuzzleHttp\Stream\Stream::factory()``. This factory accepts strings,
35
+ resources returned from ``fopen()``, an object that implements
36
+ ``__toString()``, and an object that implements
37
+ ``GuzzleHttp\Stream\StreamInterface``.
38
+
39
+ .. code-block:: php
40
+
41
+ use GuzzleHttp\Stream\Stream;
42
+
43
+ $stream = Stream::factory('string data');
44
+ echo $stream;
45
+ // string data
46
+ echo $stream->read(3);
47
+ // str
48
+ echo $stream->getContents();
49
+ // ing data
50
+ var_export($stream->eof());
51
+ // true
52
+ var_export($stream->tell());
53
+ // 11
54
+
55
+ Metadata
56
+ ========
57
+
58
+ Guzzle streams expose stream metadata through the ``getMetadata()`` method.
59
+ This method provides the data you would retrieve when calling PHP's
60
+ `stream_get_meta_data() function <http://php.net/manual/en/function.stream-get-meta-data.php>`_,
61
+ and can optionally expose other custom data.
62
+
63
+ .. code-block:: php
64
+
65
+ use GuzzleHttp\Stream\Stream;
66
+
67
+ $resource = fopen('/path/to/file', 'r');
68
+ $stream = Stream::factory($resource);
69
+ echo $stream->getMetadata('uri');
70
+ // /path/to/file
71
+ var_export($stream->isReadable());
72
+ // true
73
+ var_export($stream->isWritable());
74
+ // false
75
+ var_export($stream->isSeekable());
76
+ // true
77
+
78
+ Stream Decorators
79
+ =================
80
+
81
+ With the small and focused interface, add custom functionality to streams is
82
+ very simple with stream decorators. Guzzle provides several built-in decorators
83
+ that provide additional stream functionality.
84
+
85
+ CachingStream
86
+ -------------
87
+
88
+ The CachingStream is used to allow seeking over previously read bytes on
89
+ non-seekable streams. This can be useful when transferring a non-seekable
90
+ entity body fails due to needing to rewind the stream (for example, resulting
91
+ from a redirect). Data that is read from the remote stream will be buffered in
92
+ a PHP temp stream so that previously read bytes are cached first in memory,
93
+ then on disk.
94
+
95
+ .. code-block:: php
96
+
97
+ use GuzzleHttp\Stream\Stream;
98
+ use GuzzleHttp\Stream\CachingStream;
99
+
100
+ $original = Stream::factory(fopen('http://www.google.com', 'r'));
101
+ $stream = new CachingStream($original);
102
+
103
+ $stream->read(1024);
104
+ echo $stream->tell();
105
+ // 1024
106
+
107
+ $stream->seek(0);
108
+ echo $stream->tell();
109
+ // 0
110
+
111
+ LimitStream
112
+ -----------
113
+
114
+ LimitStream can be used to read a subset or slice of an existing stream object.
115
+ This can be useful for breaking a large file into smaller pieces to be sent in
116
+ chunks (e.g. Amazon S3's multipart upload API).
117
+
118
+ .. code-block:: php
119
+
120
+ use GuzzleHttp\Stream\Stream;
121
+ use GuzzleHttp\Stream\LimitStream;
122
+
123
+ $original = Stream::factory(fopen('/tmp/test.txt', 'r+'));
124
+ echo $original->getSize();
125
+ // >>> 1048576
126
+
127
+ // Limit the size of the body to 1024 bytes and start reading from byte 2048
128
+ $stream = new LimitStream($original, 1024, 2048);
129
+ echo $stream->getSize();
130
+ // >>> 1024
131
+ echo $stream->tell();
132
+ // >>> 0
133
+
134
+ NoSeekStream
135
+ ------------
136
+
137
+ NoSeekStream wraps a stream and does not allow seeking.
138
+
139
+ .. code-block:: php
140
+
141
+ use GuzzleHttp\Stream\Stream;
142
+ use GuzzleHttp\Stream\LimitStream;
143
+
144
+ $original = Stream::factory('foo');
145
+ $noSeek = new NoSeekStream($original);
146
+
147
+ echo $noSeek->read(3);
148
+ // foo
149
+ var_export($noSeek->isSeekable());
150
+ // false
151
+ $noSeek->seek(0);
152
+ var_export($noSeek->read(3));
153
+ // NULL
154
+
155
+ Creating Custom Decorators
156
+ --------------------------
157
+
158
+ Creating a stream decorator is very easy thanks to the
159
+ ``GuzzleHttp\Stream\StreamDecoratorTrait``. This trait provides methods that
160
+ implement ``GuzzleHttp\Stream\StreamInterface`` by proxying to an underlying
161
+ stream. Just ``use`` the ``StreamDecoratorTrait`` and implement your custom
162
+ methods.
163
+
164
+ For example, let's say we wanted to call a specific function each time the last
165
+ byte is read from a stream. This could be implemented by overriding the
166
+ ``read()`` method.
167
+
168
+ .. code-block:: php
169
+
170
+ use GuzzleHttp\Stream\StreamDecoratorTrait;
171
+
172
+ class EofCallbackStream implements StreamInterface
173
+ {
174
+ use StreamDecoratorTrait;
175
+
176
+ private $callback;
177
+
178
+ public function __construct(StreamInterface $stream, callable $callback)
179
+ {
180
+ $this->stream = $stream;
181
+ $this->callback = $callback;
182
+ }
183
+
184
+ public function read($length)
185
+ {
186
+ $result = $this->stream->read($length);
187
+
188
+ // Invoke the callback when EOF is hit.
189
+ if ($this->eof()) {
190
+ call_user_func($this->callback);
191
+ }
192
+
193
+ return $result;
194
+ }
195
+ }
196
+
197
+ This decorator could be added to any existing stream and used like so:
198
+
199
+ .. code-block:: php
200
+
201
+ use GuzzleHttp\Stream\Stream;
202
+
203
+ $original = Stream::factory('foo');
204
+ $eofStream = new EofCallbackStream($original, function () {
205
+ echo 'EOF!';
206
+ });
207
+
208
+ $eofStream->read(2);
209
+ $eofStream->read(1);
210
+ // echoes "EOF!"
211
+ $eofStream->seek(0);
212
+ $eofStream->read(3);
213
+ // echoes "EOF!"
backend/vendor/guzzlehttp/guzzle/docs/testing.rst ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ======================
2
+ Testing Guzzle Clients
3
+ ======================
4
+
5
+ Guzzle provides several tools that will enable you to easily mock the HTTP
6
+ layer without needing to send requests over the internet.
7
+
8
+ * Mock subscriber
9
+ * Mock handler
10
+ * Node.js web server for integration testing
11
+
12
+ Mock Subscriber
13
+ ===============
14
+
15
+ When testing HTTP clients, you often need to simulate specific scenarios like
16
+ returning a successful response, returning an error, or returning specific
17
+ responses in a certain order. Because unit tests need to be predictable, easy
18
+ to bootstrap, and fast, hitting an actual remote API is a test smell.
19
+
20
+ Guzzle provides a mock subscriber that can be attached to clients or requests
21
+ that allows you to queue up a list of responses to use rather than hitting a
22
+ remote API.
23
+
24
+ .. code-block:: php
25
+
26
+ use GuzzleHttp\Client;
27
+ use GuzzleHttp\Subscriber\Mock;
28
+ use GuzzleHttp\Message\Response;
29
+
30
+ $client = new Client();
31
+
32
+ // Create a mock subscriber and queue two responses.
33
+ $mock = new Mock([
34
+ new Response(200, ['X-Foo' => 'Bar']), // Use response object
35
+ "HTTP/1.1 202 OK\r\nContent-Length: 0\r\n\r\n" // Use a response string
36
+ ]);
37
+
38
+ // Add the mock subscriber to the client.
39
+ $client->getEmitter()->attach($mock);
40
+ // The first request is intercepted with the first response.
41
+ echo $client->get('/')->getStatusCode();
42
+ //> 200
43
+ // The second request is intercepted with the second response.
44
+ echo $client->get('/')->getStatusCode();
45
+ //> 202
46
+
47
+ When no more responses are in the queue and a request is sent, an
48
+ ``OutOfBoundsException`` is thrown.
49
+
50
+ History Subscriber
51
+ ==================
52
+
53
+ When using things like the ``Mock`` subscriber, you often need to know if the
54
+ requests you expected to send were sent exactly as you intended. While the mock
55
+ subscriber responds with mocked responses, the ``GuzzleHttp\Subscriber\History``
56
+ subscriber maintains a history of the requests that were sent by a client.
57
+
58
+ .. code-block:: php
59
+
60
+ use GuzzleHttp\Client;
61
+ use GuzzleHttp\Subscriber\History;
62
+
63
+ $client = new Client();
64
+ $history = new History();
65
+
66
+ // Add the history subscriber to the client.
67
+ $client->getEmitter()->attach($history);
68
+
69
+ $client->get('http://httpbin.org/get');
70
+ $client->head('http://httpbin.org/get');
71
+
72
+ // Count the number of transactions
73
+ echo count($history);
74
+ //> 2
75
+ // Get the last request
76
+ $lastRequest = $history->getLastRequest();
77
+ // Get the last response
78
+ $lastRequest = $history->getLastResponse();
79
+
80
+ // Iterate over the transactions that were sent
81
+ foreach ($history as $transaction) {
82
+ echo $transaction['request']->getMethod();
83
+ //> GET, HEAD
84
+ echo $transaction['response']->getStatusCode();
85
+ //> 200, 200
86
+ }
87
+
88
+ The history subscriber can also be printed, revealing the requests and
89
+ responses that were sent as a string, in order.
90
+
91
+ .. code-block:: php
92
+
93
+ echo $history;
94
+
95
+ ::
96
+
97
+ > GET /get HTTP/1.1
98
+ Host: httpbin.org
99
+ User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
100
+
101
+ < HTTP/1.1 200 OK
102
+ Access-Control-Allow-Origin: *
103
+ Content-Type: application/json
104
+ Date: Tue, 25 Mar 2014 03:53:27 GMT
105
+ Server: gunicorn/0.17.4
106
+ Content-Length: 270
107
+ Connection: keep-alive
108
+
109
+ {
110
+ "headers": {
111
+ "Connection": "close",
112
+ "X-Request-Id": "3d0f7d5c-c937-4394-8248-2b8e03fcccdb",
113
+ "User-Agent": "Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8",
114
+ "Host": "httpbin.org"
115
+ },
116
+ "origin": "76.104.247.1",
117
+ "args": {},
118
+ "url": "http://httpbin.org/get"
119
+ }
120
+
121
+ > HEAD /get HTTP/1.1
122
+ Host: httpbin.org
123
+ User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
124
+
125
+ < HTTP/1.1 200 OK
126
+ Access-Control-Allow-Origin: *
127
+ Content-length: 270
128
+ Content-Type: application/json
129
+ Date: Tue, 25 Mar 2014 03:53:27 GMT
130
+ Server: gunicorn/0.17.4
131
+ Connection: keep-alive
132
+
133
+ Mock Adapter
134
+ ============
135
+
136
+ In addition to using the Mock subscriber, you can use the
137
+ ``GuzzleHttp\Ring\Client\MockAdapter`` as the handler of a client to return the
138
+ same response over and over or return the result of a callable function.
139
+
140
+ Test Web Server
141
+ ===============
142
+
143
+ Using mock responses is almost always enough when testing a web service client.
144
+ When implementing custom :doc:`HTTP handlers <handlers>`, you'll need to send
145
+ actual HTTP requests in order to sufficiently test the handler. However, a
146
+ best practice is to contact a local web server rather than a server over the
147
+ internet.
148
+
149
+ - Tests are more reliable
150
+ - Tests do not require a network connection
151
+ - Tests have no external dependencies
152
+
153
+ Using the test server
154
+ ---------------------
155
+
156
+ .. warning::
157
+
158
+ The following functionality is provided to help developers of Guzzle
159
+ develop HTTP handlers. There is no promise of backwards compatibility
160
+ when it comes to the node.js test server or the ``GuzzleHttp\Tests\Server``
161
+ class. If you are using the test server or ``Server`` class outside of
162
+ guzzlehttp/guzzle, then you will need to configure autoloading and
163
+ ensure the web server is started manually.
164
+
165
+ .. hint::
166
+
167
+ You almost never need to use this test web server. You should only ever
168
+ consider using it when developing HTTP handlers. The test web server
169
+ is not necessary for mocking requests. For that, please use the
170
+ Mock subcribers and History subscriber.
171
+
172
+ Guzzle ships with a node.js test server that receives requests and returns
173
+ responses from a queue. The test server exposes a simple API that is used to
174
+ enqueue responses and inspect the requests that it has received.
175
+
176
+ Any operation on the ``Server`` object will ensure that
177
+ the server is running and wait until it is able to receive requests before
178
+ returning.
179
+
180
+ .. code-block:: php
181
+
182
+ use GuzzleHttp\Client;
183
+ use GuzzleHttp\Tests\Server;
184
+
185
+ // Start the server and queue a response
186
+ Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
187
+
188
+ $client = new Client(['base_url' => Server::$url]);
189
+ echo $client->get('/foo')->getStatusCode();
190
+ // 200
191
+
192
+ ``GuzzleHttp\Tests\Server`` provides a static interface to the test server. You
193
+ can queue an HTTP response or an array of responses by calling
194
+ ``Server::enqueue()``. This method accepts a string representing an HTTP
195
+ response message, a ``GuzzleHttp\Message\ResponseInterface``, or an array of
196
+ HTTP message strings / ``GuzzleHttp\Message\ResponseInterface`` objects.
197
+
198
+ .. code-block:: php
199
+
200
+ // Queue single response
201
+ Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
202
+
203
+ // Clear the queue and queue an array of responses
204
+ Server::enqueue([
205
+ "HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n",
206
+ "HTTP/1.1 404 Not Found\r\n\Content-Length: 0r\n\r\n"
207
+ ]);
208
+
209
+ When a response is queued on the test server, the test server will remove any
210
+ previously queued responses. As the server receives requests, queued responses
211
+ are dequeued and returned to the request. When the queue is empty, the server
212
+ will return a 500 response.
213
+
214
+ You can inspect the requests that the server has retrieved by calling
215
+ ``Server::received()``. This method accepts an optional ``$hydrate`` parameter
216
+ that specifies if you are retrieving an array of HTTP requests as strings or an
217
+ array of ``GuzzleHttp\Message\RequestInterface`` objects.
218
+
219
+ .. code-block:: php
220
+
221
+ foreach (Server::received() as $response) {
222
+ echo $response;
223
+ }
224
+
225
+ You can clear the list of received requests from the web server using the
226
+ ``Server::flush()`` method.
227
+
228
+ .. code-block:: php
229
+
230
+ Server::flush();
231
+ echo count(Server::received());
232
+ // 0
backend/vendor/guzzlehttp/guzzle/phpunit.xml.dist ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <exclude>
13
+ <directory suffix="Interface.php">src/</directory>
14
+ </exclude>
15
+ </whitelist>
16
+ </filter>
17
+ </phpunit>
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/Client.php ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Client\Middleware;
10
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
11
+ use GuzzleHttp\Ring\Client\CurlHandler;
12
+ use GuzzleHttp\Ring\Client\StreamHandler;
13
+ use GuzzleHttp\Ring\Core;
14
+ use GuzzleHttp\Ring\Future\FutureInterface;
15
+ use GuzzleHttp\Exception\RequestException;
16
+ use React\Promise\FulfilledPromise;
17
+ use React\Promise\RejectedPromise;
18
+
19
+ /**
20
+ * HTTP client
21
+ */
22
+ class Client implements ClientInterface
23
+ {
24
+ use HasEmitterTrait;
25
+
26
+ /** @var MessageFactoryInterface Request factory used by the client */
27
+ private $messageFactory;
28
+
29
+ /** @var Url Base URL of the client */
30
+ private $baseUrl;
31
+
32
+ /** @var array Default request options */
33
+ private $defaults;
34
+
35
+ /** @var callable Request state machine */
36
+ private $fsm;
37
+
38
+ /**
39
+ * Clients accept an array of constructor parameters.
40
+ *
41
+ * Here's an example of creating a client using an URI template for the
42
+ * client's base_url and an array of default request options to apply
43
+ * to each request:
44
+ *
45
+ * $client = new Client([
46
+ * 'base_url' => [
47
+ * 'http://www.foo.com/{version}/',
48
+ * ['version' => '123']
49
+ * ],
50
+ * 'defaults' => [
51
+ * 'timeout' => 10,
52
+ * 'allow_redirects' => false,
53
+ * 'proxy' => '192.168.16.1:10'
54
+ * ]
55
+ * ]);
56
+ *
57
+ * @param array $config Client configuration settings
58
+ * - base_url: Base URL of the client that is merged into relative URLs.
59
+ * Can be a string or an array that contains a URI template followed
60
+ * by an associative array of expansion variables to inject into the
61
+ * URI template.
62
+ * - handler: callable RingPHP handler used to transfer requests
63
+ * - message_factory: Factory used to create request and response object
64
+ * - defaults: Default request options to apply to each request
65
+ * - emitter: Event emitter used for request events
66
+ * - fsm: (internal use only) The request finite state machine. A
67
+ * function that accepts a transaction and optional final state. The
68
+ * function is responsible for transitioning a request through its
69
+ * lifecycle events.
70
+ */
71
+ public function __construct(array $config = [])
72
+ {
73
+ $this->configureBaseUrl($config);
74
+ $this->configureDefaults($config);
75
+
76
+ if (isset($config['emitter'])) {
77
+ $this->emitter = $config['emitter'];
78
+ }
79
+
80
+ $this->messageFactory = isset($config['message_factory'])
81
+ ? $config['message_factory']
82
+ : new MessageFactory();
83
+
84
+ if (isset($config['fsm'])) {
85
+ $this->fsm = $config['fsm'];
86
+ } else {
87
+ if (isset($config['handler'])) {
88
+ $handler = $config['handler'];
89
+ } elseif (isset($config['adapter'])) {
90
+ $handler = $config['adapter'];
91
+ } else {
92
+ $handler = static::getDefaultHandler();
93
+ }
94
+ $this->fsm = new RequestFsm($handler, $this->messageFactory);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Create a default handler to use based on the environment
100
+ *
101
+ * @throws \RuntimeException if no viable Handler is available.
102
+ */
103
+ public static function getDefaultHandler()
104
+ {
105
+ $default = $future = $streaming = null;
106
+
107
+ if (extension_loaded('curl')) {
108
+ $config = [
109
+ 'select_timeout' => getenv('GUZZLE_CURL_SELECT_TIMEOUT') ?: 1
110
+ ];
111
+ if ($maxHandles = getenv('GUZZLE_CURL_MAX_HANDLES')) {
112
+ $config['max_handles'] = $maxHandles;
113
+ }
114
+ $future = new CurlMultiHandler($config);
115
+ if (function_exists('curl_reset')) {
116
+ $default = new CurlHandler();
117
+ }
118
+ }
119
+
120
+ if (ini_get('allow_url_fopen')) {
121
+ $streaming = new StreamHandler();
122
+ }
123
+
124
+ if (!($default = ($default ?: $future) ?: $streaming)) {
125
+ throw new \RuntimeException('Guzzle requires cURL, the '
126
+ . 'allow_url_fopen ini setting, or a custom HTTP handler.');
127
+ }
128
+
129
+ $handler = $default;
130
+
131
+ if ($streaming && $streaming !== $default) {
132
+ $handler = Middleware::wrapStreaming($default, $streaming);
133
+ }
134
+
135
+ if ($future) {
136
+ $handler = Middleware::wrapFuture($handler, $future);
137
+ }
138
+
139
+ return $handler;
140
+ }
141
+
142
+ /**
143
+ * Get the default User-Agent string to use with Guzzle
144
+ *
145
+ * @return string
146
+ */
147
+ public static function getDefaultUserAgent()
148
+ {
149
+ static $defaultAgent = '';
150
+ if (!$defaultAgent) {
151
+ $defaultAgent = 'Guzzle/' . self::VERSION;
152
+ if (extension_loaded('curl')) {
153
+ $defaultAgent .= ' curl/' . curl_version()['version'];
154
+ }
155
+ $defaultAgent .= ' PHP/' . PHP_VERSION;
156
+ }
157
+
158
+ return $defaultAgent;
159
+ }
160
+
161
+ public function getDefaultOption($keyOrPath = null)
162
+ {
163
+ return $keyOrPath === null
164
+ ? $this->defaults
165
+ : Utils::getPath($this->defaults, $keyOrPath);
166
+ }
167
+
168
+ public function setDefaultOption($keyOrPath, $value)
169
+ {
170
+ Utils::setPath($this->defaults, $keyOrPath, $value);
171
+ }
172
+
173
+ public function getBaseUrl()
174
+ {
175
+ return (string) $this->baseUrl;
176
+ }
177
+
178
+ public function createRequest($method, $url = null, array $options = [])
179
+ {
180
+ $headers = $this->mergeDefaults($options);
181
+ // Use a clone of the client's emitter
182
+ $options['config']['emitter'] = clone $this->getEmitter();
183
+
184
+ $request = $this->messageFactory->createRequest(
185
+ $method,
186
+ $url ? (string) $this->buildUrl($url) : (string) $this->baseUrl,
187
+ $options
188
+ );
189
+
190
+ // Merge in default headers
191
+ if ($headers) {
192
+ foreach ($headers as $key => $value) {
193
+ if (!$request->hasHeader($key)) {
194
+ $request->setHeader($key, $value);
195
+ }
196
+ }
197
+ }
198
+
199
+ return $request;
200
+ }
201
+
202
+ public function get($url = null, $options = [])
203
+ {
204
+ return $this->send($this->createRequest('GET', $url, $options));
205
+ }
206
+
207
+ public function head($url = null, array $options = [])
208
+ {
209
+ return $this->send($this->createRequest('HEAD', $url, $options));
210
+ }
211
+
212
+ public function delete($url = null, array $options = [])
213
+ {
214
+ return $this->send($this->createRequest('DELETE', $url, $options));
215
+ }
216
+
217
+ public function put($url = null, array $options = [])
218
+ {
219
+ return $this->send($this->createRequest('PUT', $url, $options));
220
+ }
221
+
222
+ public function patch($url = null, array $options = [])
223
+ {
224
+ return $this->send($this->createRequest('PATCH', $url, $options));
225
+ }
226
+
227
+ public function post($url = null, array $options = [])
228
+ {
229
+ return $this->send($this->createRequest('POST', $url, $options));
230
+ }
231
+
232
+ public function options($url = null, array $options = [])
233
+ {
234
+ return $this->send($this->createRequest('OPTIONS', $url, $options));
235
+ }
236
+
237
+ public function send(RequestInterface $request)
238
+ {
239
+ $trans = new Transaction($this, $request);
240
+ $fn = $this->fsm;
241
+
242
+ // Ensure a future response is returned if one was requested.
243
+ if ($request->getConfig()->get('future')) {
244
+ try {
245
+ $fn($trans);
246
+ // Turn the normal response into a future if needed.
247
+ return $trans->response instanceof FutureInterface
248
+ ? $trans->response
249
+ : new FutureResponse(new FulfilledPromise($trans->response));
250
+ } catch (RequestException $e) {
251
+ // Wrap the exception in a promise if the user asked for a future.
252
+ return new FutureResponse(new RejectedPromise($e));
253
+ }
254
+ } else {
255
+ try {
256
+ $fn($trans);
257
+ return $trans->response instanceof FutureInterface
258
+ ? $trans->response->wait()
259
+ : $trans->response;
260
+ } catch (\Exception $e) {
261
+ throw RequestException::wrapException($trans->request, $e);
262
+ }
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Get an array of default options to apply to the client
268
+ *
269
+ * @return array
270
+ */
271
+ protected function getDefaultOptions()
272
+ {
273
+ $settings = [
274
+ 'allow_redirects' => true,
275
+ 'exceptions' => true,
276
+ 'decode_content' => true,
277
+ 'verify' => true
278
+ ];
279
+
280
+ // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set
281
+ if ($proxy = getenv('HTTP_PROXY')) {
282
+ $settings['proxy']['http'] = $proxy;
283
+ }
284
+
285
+ if ($proxy = getenv('HTTPS_PROXY')) {
286
+ $settings['proxy']['https'] = $proxy;
287
+ }
288
+
289
+ return $settings;
290
+ }
291
+
292
+ /**
293
+ * Expand a URI template and inherit from the base URL if it's relative
294
+ *
295
+ * @param string|array $url URL or URI template to expand
296
+ *
297
+ * @return string
298
+ */
299
+ private function buildUrl($url)
300
+ {
301
+ // URI template (absolute or relative)
302
+ if (!is_array($url)) {
303
+ return strpos($url, '://')
304
+ ? (string) $url
305
+ : (string) $this->baseUrl->combine($url);
306
+ }
307
+
308
+ // Absolute URL
309
+ if (strpos($url[0], '://')) {
310
+ return Utils::uriTemplate($url[0], $url[1]);
311
+ }
312
+
313
+ // Combine the relative URL with the base URL
314
+ return (string) $this->baseUrl->combine(
315
+ Utils::uriTemplate($url[0], $url[1])
316
+ );
317
+ }
318
+
319
+ private function configureBaseUrl(&$config)
320
+ {
321
+ if (!isset($config['base_url'])) {
322
+ $this->baseUrl = new Url('', '');
323
+ } elseif (is_array($config['base_url'])) {
324
+ $this->baseUrl = Url::fromString(
325
+ Utils::uriTemplate(
326
+ $config['base_url'][0],
327
+ $config['base_url'][1]
328
+ )
329
+ );
330
+ $config['base_url'] = (string) $this->baseUrl;
331
+ } else {
332
+ $this->baseUrl = Url::fromString($config['base_url']);
333
+ }
334
+ }
335
+
336
+ private function configureDefaults($config)
337
+ {
338
+ if (!isset($config['defaults'])) {
339
+ $this->defaults = $this->getDefaultOptions();
340
+ } else {
341
+ $this->defaults = array_replace(
342
+ $this->getDefaultOptions(),
343
+ $config['defaults']
344
+ );
345
+ }
346
+
347
+ // Add the default user-agent header
348
+ if (!isset($this->defaults['headers'])) {
349
+ $this->defaults['headers'] = [
350
+ 'User-Agent' => static::getDefaultUserAgent()
351
+ ];
352
+ } elseif (!Core::hasHeader($this->defaults, 'User-Agent')) {
353
+ // Add the User-Agent header if one was not already set
354
+ $this->defaults['headers']['User-Agent'] = static::getDefaultUserAgent();
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Merges default options into the array passed by reference and returns
360
+ * an array of headers that need to be merged in after the request is
361
+ * created.
362
+ *
363
+ * @param array $options Options to modify by reference
364
+ *
365
+ * @return array|null
366
+ */
367
+ private function mergeDefaults(&$options)
368
+ {
369
+ // Merging optimization for when no headers are present
370
+ if (!isset($options['headers']) || !isset($this->defaults['headers'])) {
371
+ $options = array_replace_recursive($this->defaults, $options);
372
+ return null;
373
+ }
374
+
375
+ $defaults = $this->defaults;
376
+ unset($defaults['headers']);
377
+ $options = array_replace_recursive($defaults, $options);
378
+
379
+ return $this->defaults['headers'];
380
+ }
381
+
382
+ /**
383
+ * @deprecated Use {@see GuzzleHttp\Pool} instead.
384
+ * @see GuzzleHttp\Pool
385
+ */
386
+ public function sendAll($requests, array $options = [])
387
+ {
388
+ (new Pool($this, $requests, $options))->wait();
389
+ }
390
+ }
backend/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.0.3';
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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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))) {
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
+ }
backend/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
+ }
backend/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() && 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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * @return Transaction
46
+ */
47
+ protected function getTransaction()
48
+ {
49
+ return $this->transaction;
50
+ }
51
+ }
backend/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
+ $this->transaction->response = null;
31
+ $this->transaction->exception = null;
32
+ $this->transaction->state = 'before';
33
+
34
+ if ($afterDelay) {
35
+ $this->transaction->request->getConfig()->set('delay', $afterDelay);
36
+ }
37
+
38
+ $this->stopPropagation();
39
+ }
40
+ }
backend/vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ return !$name
24
+ ? $this->transaction->transferInfo
25
+ : (isset($this->transaction->transferInfo[$name])
26
+ ? $this->transaction->transferInfo[$name]
27
+ : null);
28
+ }
29
+
30
+ /**
31
+ * Returns true/false if a response is available.
32
+ *
33
+ * @return bool
34
+ */
35
+ public function hasResponse()
36
+ {
37
+ return !($this->transaction->response instanceof FutureInterface);
38
+ }
39
+
40
+ /**
41
+ * Get the response.
42
+ *
43
+ * @return ResponseInterface|null
44
+ */
45
+ public function getResponse()
46
+ {
47
+ return $this->hasResponse() ? $this->transaction->response : null;
48
+ }
49
+
50
+ /**
51
+ * Intercept the request and associate a response
52
+ *
53
+ * @param ResponseInterface $response Response to set
54
+ */
55
+ public function intercept(ResponseInterface $response)
56
+ {
57
+ $this->transaction->response = $response;
58
+ $this->transaction->exception = null;
59
+ $this->stopPropagation();
60
+ }
61
+ }
backend/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
+ }
backend/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 {}
backend/vendor/guzzlehttp/guzzle/src/Event/Emitter.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ $eventName
48
+ ) use (&$onceListener, $eventName, $listener, $priority) {
49
+ $this->removeListener($eventName, $onceListener);
50
+ $listener($event, $eventName, $this);
51
+ };
52
+
53
+ $this->on($eventName, $onceListener, $priority);
54
+ }
55
+
56
+ public function removeListener($eventName, callable $listener)
57
+ {
58
+ if (empty($this->listeners[$eventName])) {
59
+ return;
60
+ }
61
+
62
+ foreach ($this->listeners[$eventName] as $priority => $listeners) {
63
+ if (false !== ($key = array_search($listener, $listeners, true))) {
64
+ unset(
65
+ $this->listeners[$eventName][$priority][$key],
66
+ $this->sorted[$eventName]
67
+ );
68
+ }
69
+ }
70
+ }
71
+
72
+ public function listeners($eventName = null)
73
+ {
74
+ // Return all events in a sorted priority order
75
+ if ($eventName === null) {
76
+ foreach (array_keys($this->listeners) as $eventName) {
77
+ if (empty($this->sorted[$eventName])) {
78
+ $this->listeners($eventName);
79
+ }
80
+ }
81
+ return $this->sorted;
82
+ }
83
+
84
+ // Return the listeners for a specific event, sorted in priority order
85
+ if (empty($this->sorted[$eventName])) {
86
+ $this->sorted[$eventName] = [];
87
+ if (isset($this->listeners[$eventName])) {
88
+ krsort($this->listeners[$eventName], SORT_NUMERIC);
89
+ foreach ($this->listeners[$eventName] as $listeners) {
90
+ foreach ($listeners as $listener) {
91
+ $this->sorted[$eventName][] = $listener;
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ return $this->sorted[$eventName];
98
+ }
99
+
100
+ public function hasListeners($eventName)
101
+ {
102
+ return !empty($this->listeners[$eventName]);
103
+ }
104
+
105
+ public function emit($eventName, EventInterface $event)
106
+ {
107
+ if (isset($this->listeners[$eventName])) {
108
+ foreach ($this->listeners($eventName) as $listener) {
109
+ $listener($event, $eventName);
110
+ if ($event->isPropagationStopped()) {
111
+ break;
112
+ }
113
+ }
114
+ }
115
+
116
+ return $event;
117
+ }
118
+
119
+ public function attach(SubscriberInterface $subscriber)
120
+ {
121
+ foreach ($subscriber->getEvents() as $eventName => $listeners) {
122
+ if (is_array($listeners[0])) {
123
+ foreach ($listeners as $listener) {
124
+ $this->on(
125
+ $eventName,
126
+ [$subscriber, $listener[0]],
127
+ isset($listener[1]) ? $listener[1] : 0
128
+ );
129
+ }
130
+ } else {
131
+ $this->on(
132
+ $eventName,
133
+ [$subscriber, $listeners[0]],
134
+ isset($listeners[1]) ? $listeners[1] : 0
135
+ );
136
+ }
137
+ }
138
+ }
139
+
140
+ public function detach(SubscriberInterface $subscriber)
141
+ {
142
+ foreach ($subscriber->getEvents() as $eventName => $listener) {
143
+ $this->removeListener($eventName, [$subscriber, $listener[0]]);
144
+ }
145
+ }
146
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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 {}
backend/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 {}
backend/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class ConnectException extends RequestException {}
backend/vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class CouldNotRewindStreamException extends RequestException {}
backend/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
+ }
backend/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-RequesExceptions 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
+ }
backend/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 {}
backend/vendor/guzzlehttp/guzzle/src/Exception/StateException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class StateException extends TransferException {};
backend/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TooManyRedirectsException extends RequestException {}
backend/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TransferException extends \RuntimeException {}
backend/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
+ }
backend/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
+ }
backend/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->setHeader($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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ ];
47
+
48
+ /**
49
+ * @param array $customOptions Associative array of custom request option
50
+ * names mapping to functions used to apply
51
+ * the option. The function accepts the request
52
+ * and the option value to apply.
53
+ */
54
+ public function __construct(array $customOptions = [])
55
+ {
56
+ $this->errorPlugin = new HttpError();
57
+ $this->redirectPlugin = new Redirect();
58
+ $this->customOptions = $customOptions;
59
+ }
60
+
61
+ public function createResponse(
62
+ $statusCode,
63
+ array $headers = [],
64
+ $body = null,
65
+ array $options = []
66
+ ) {
67
+ if (null !== $body) {
68
+ $body = Stream::factory($body);
69
+ }
70
+
71
+ return new Response($statusCode, $headers, $body, $options);
72
+ }
73
+
74
+ public function createRequest($method, $url, array $options = [])
75
+ {
76
+ // Handle the request protocol version option that needs to be
77
+ // specified in the request constructor.
78
+ if (isset($options['version'])) {
79
+ $options['config']['protocol_version'] = $options['version'];
80
+ unset($options['version']);
81
+ }
82
+
83
+ $request = new Request($method, $url, [], null,
84
+ isset($options['config']) ? $options['config'] : []);
85
+
86
+ unset($options['config']);
87
+
88
+ // Use a POST body by default
89
+ if ($method == 'POST'
90
+ && !isset($options['body'])
91
+ && !isset($options['json'])
92
+ ) {
93
+ $options['body'] = [];
94
+ }
95
+
96
+ if ($options) {
97
+ $this->applyOptions($request, $options);
98
+ }
99
+
100
+ return $request;
101
+ }
102
+
103
+ /**
104
+ * Create a request or response object from an HTTP message string
105
+ *
106
+ * @param string $message Message to parse
107
+ *
108
+ * @return RequestInterface|ResponseInterface
109
+ * @throws \InvalidArgumentException if unable to parse a message
110
+ */
111
+ public function fromMessage($message)
112
+ {
113
+ static $parser;
114
+ if (!$parser) {
115
+ $parser = new MessageParser();
116
+ }
117
+
118
+ // Parse a response
119
+ if (strtoupper(substr($message, 0, 4)) == 'HTTP') {
120
+ $data = $parser->parseResponse($message);
121
+ return $this->createResponse(
122
+ $data['code'],
123
+ $data['headers'],
124
+ $data['body'] === '' ? null : $data['body'],
125
+ $data
126
+ );
127
+ }
128
+
129
+ // Parse a request
130
+ if (!($data = ($parser->parseRequest($message)))) {
131
+ throw new \InvalidArgumentException('Unable to parse request');
132
+ }
133
+
134
+ return $this->createRequest(
135
+ $data['method'],
136
+ Url::buildUrl($data['request_url']),
137
+ [
138
+ 'headers' => $data['headers'],
139
+ 'body' => $data['body'] === '' ? null : $data['body'],
140
+ 'config' => [
141
+ 'protocol_version' => $data['protocol_version']
142
+ ]
143
+ ]
144
+ );
145
+ }
146
+
147
+ /**
148
+ * Apply POST fields and files to a request to attempt to give an accurate
149
+ * representation.
150
+ *
151
+ * @param RequestInterface $request Request to update
152
+ * @param array $body Body to apply
153
+ */
154
+ protected function addPostData(RequestInterface $request, array $body)
155
+ {
156
+ static $fields = ['string' => true, 'array' => true, 'NULL' => true,
157
+ 'boolean' => true, 'double' => true, 'integer' => true];
158
+
159
+ $post = new PostBody();
160
+ foreach ($body as $key => $value) {
161
+ if (isset($fields[gettype($value)])) {
162
+ $post->setField($key, $value);
163
+ } elseif ($value instanceof PostFileInterface) {
164
+ $post->addFile($value);
165
+ } else {
166
+ $post->addFile(new PostFile($key, $value));
167
+ }
168
+ }
169
+
170
+ if ($request->getHeader('Content-Type') == 'multipart/form-data') {
171
+ $post->forceMultipartUpload(true);
172
+ }
173
+
174
+ $request->setBody($post);
175
+ }
176
+
177
+ protected function applyOptions(
178
+ RequestInterface $request,
179
+ array $options = []
180
+ ) {
181
+ $config = $request->getConfig();
182
+ $emitter = $request->getEmitter();
183
+
184
+ foreach ($options as $key => $value) {
185
+
186
+ if (isset(self::$configMap[$key])) {
187
+ $config[$key] = $value;
188
+ continue;
189
+ }
190
+
191
+ switch ($key) {
192
+
193
+ case 'allow_redirects':
194
+
195
+ if ($value === false) {
196
+ continue;
197
+ }
198
+
199
+ if ($value === true) {
200
+ $value = self::$defaultRedirect;
201
+ } elseif (!isset($value['max'])) {
202
+ throw new Iae('allow_redirects must be true, false, or an '
203
+ . 'array that contains the \'max\' key');
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;
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
+
231
+ // Do not overwrite existing headers
232
+ foreach ($value as $k => $v) {
233
+ if (!$request->hasHeader($k)) {
234
+ $request->setHeader($k, $v);
235
+ }
236
+ }
237
+ break;
238
+
239
+ case 'exceptions':
240
+
241
+ if ($value === true) {
242
+ $emitter->attach($this->errorPlugin);
243
+ }
244
+ break;
245
+
246
+ case 'body':
247
+
248
+ if (is_array($value)) {
249
+ $this->addPostData($request, $value);
250
+ } elseif ($value !== null) {
251
+ $request->setBody(Stream::factory($value));
252
+ }
253
+ break;
254
+
255
+ case 'auth':
256
+
257
+ if (!$value) {
258
+ continue;
259
+ }
260
+
261
+ if (is_array($value)) {
262
+ $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
263
+ } else {
264
+ $type = strtolower($value);
265
+ }
266
+
267
+ $config['auth'] = $value;
268
+
269
+ if ($type == 'basic') {
270
+ $request->setHeader(
271
+ 'Authorization',
272
+ 'Basic ' . base64_encode("$value[0]:$value[1]")
273
+ );
274
+ } elseif ($type == 'digest') {
275
+ // @todo: Do not rely on curl
276
+ $config->setPath('curl/' . CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
277
+ $config->setPath('curl/' . CURLOPT_USERPWD, "$value[0]:$value[1]");
278
+ }
279
+ break;
280
+
281
+ case 'query':
282
+
283
+ if ($value instanceof Query) {
284
+ $original = $request->getQuery();
285
+ // Do not overwrite existing query string variables by
286
+ // overwriting the object with the query string data passed
287
+ // in the URL
288
+ $value->overwriteWith($original->toArray());
289
+ $request->setQuery($value);
290
+ } elseif (is_array($value)) {
291
+ // Do not overwrite existing query string variables
292
+ $query = $request->getQuery();
293
+ foreach ($value as $k => $v) {
294
+ if (!isset($query[$k])) {
295
+ $query[$k] = $v;
296
+ }
297
+ }
298
+ } else {
299
+ throw new Iae('query must be an array or Query object');
300
+ }
301
+ break;
302
+
303
+ case 'cookies':
304
+
305
+ if ($value === true) {
306
+ static $cookie = null;
307
+ if (!$cookie) {
308
+ $cookie = new Cookie();
309
+ }
310
+ $emitter->attach($cookie);
311
+ } elseif (is_array($value)) {
312
+ $emitter->attach(
313
+ new Cookie(CookieJar::fromArray($value, $request->getHost()))
314
+ );
315
+ } elseif ($value instanceof CookieJarInterface) {
316
+ $emitter->attach(new Cookie($value));
317
+ } elseif ($value !== false) {
318
+ throw new Iae('cookies must be an array, true, or CookieJarInterface');
319
+ }
320
+ break;
321
+
322
+ case 'events':
323
+
324
+ if (!is_array($value)) {
325
+ throw new Iae('events must be an array');
326
+ }
327
+
328
+ $this->attachListeners($request,
329
+ $this->prepareListeners(
330
+ $value,
331
+ ['before', 'complete', 'error', 'progress', 'end']
332
+ )
333
+ );
334
+ break;
335
+
336
+ case 'subscribers':
337
+
338
+ if (!is_array($value)) {
339
+ throw new Iae('subscribers must be an array');
340
+ }
341
+
342
+ foreach ($value as $subscribers) {
343
+ $emitter->attach($subscribers);
344
+ }
345
+ break;
346
+
347
+ case 'json':
348
+
349
+ $request->setBody(Stream::factory(json_encode($value)));
350
+ if (!$request->hasHeader('Content-Type')) {
351
+ $request->setHeader('Content-Type', 'application/json');
352
+ }
353
+ break;
354
+
355
+ default:
356
+
357
+ // Check for custom handler functions.
358
+ if (isset($this->customOptions[$key])) {
359
+ $fn = $this->customOptions[$key];
360
+ $fn($request, $value);
361
+ continue;
362
+ }
363
+
364
+ throw new Iae("No method can handle the {$key} config key");
365
+ }
366
+ }
367
+ }
368
+ }
backend/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/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/clients.html#request-options
69
+ */
70
+ public function createRequest($method, $url, array $options = []);
71
+ }
backend/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
+ }
backend/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
+ }
backend/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->setHeader($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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/Pool.php ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Event\RequestEvents;
5
+ use GuzzleHttp\Message\RequestInterface;
6
+ use GuzzleHttp\Message\ResponseInterface;
7
+ use GuzzleHttp\Ring\Core;
8
+ use GuzzleHttp\Ring\Future\FutureInterface;
9
+ use GuzzleHttp\Event\ListenerAttacherTrait;
10
+ use GuzzleHttp\Event\EndEvent;
11
+ use React\Promise\Deferred;
12
+ use React\Promise\PromiseInterface;
13
+
14
+ /**
15
+ * Sends and iterator of requests concurrently using a capped pool size.
16
+ *
17
+ * The Pool object implements FutureInterface, meaning it can be used later
18
+ * when necessary, the requests provided to the pool can be cancelled, and
19
+ * you can check the state of the pool to know if it has been dereferenced
20
+ * (sent) or has been cancelled.
21
+ *
22
+ * When sending the pool, keep in mind that no results are returned: callers
23
+ * are expected to handle results asynchronously using Guzzle's event system.
24
+ * When requests complete, more are added to the pool to ensure that the
25
+ * requested pool size is always filled as much as possible.
26
+ *
27
+ * IMPORTANT: Do not provide a pool size greater that what the utilized
28
+ * underlying RingPHP handler can support. This will result is extremely poor
29
+ * performance.
30
+ */
31
+ class Pool implements FutureInterface
32
+ {
33
+ use ListenerAttacherTrait;
34
+
35
+ /** @var \GuzzleHttp\ClientInterface */
36
+ private $client;
37
+
38
+ /** @var \Iterator Yields requests */
39
+ private $iter;
40
+
41
+ /** @var Deferred */
42
+ private $deferred;
43
+
44
+ /** @var PromiseInterface */
45
+ private $promise;
46
+
47
+ private $waitQueue = [];
48
+ private $eventListeners = [];
49
+ private $poolSize;
50
+ private $isRealized = false;
51
+
52
+ /**
53
+ * The option values for 'before', 'after', and 'error' can be a callable,
54
+ * an associative array containing event data, or an array of event data
55
+ * arrays. Event data arrays contain the following keys:
56
+ *
57
+ * - fn: callable to invoke that receives the event
58
+ * - priority: Optional event priority (defaults to 0)
59
+ * - once: Set to true so that the event is removed after it is triggered
60
+ *
61
+ * @param ClientInterface $client Client used to send the requests.
62
+ * @param array|\Iterator $requests Requests to send in parallel
63
+ * @param array $options Associative array of options
64
+ * - pool_size: (int) Maximum number of requests to send concurrently
65
+ * - before: (callable|array) Receives a BeforeEvent
66
+ * - after: (callable|array) Receives a CompleteEvent
67
+ * - error: (callable|array) Receives a ErrorEvent
68
+ */
69
+ public function __construct(
70
+ ClientInterface $client,
71
+ $requests,
72
+ array $options = []
73
+ ) {
74
+ $this->client = $client;
75
+ $this->iter = $this->coerceIterable($requests);
76
+ $this->deferred = new Deferred();
77
+ $this->promise = $this->deferred->promise();
78
+ $this->poolSize = isset($options['pool_size'])
79
+ ? $options['pool_size'] : 25;
80
+ $this->eventListeners = $this->prepareListeners(
81
+ $options,
82
+ ['before', 'complete', 'error', 'end']
83
+ );
84
+ }
85
+
86
+ /**
87
+ * Sends multiple requests in parallel and returns an array of responses
88
+ * and exceptions that uses the same ordering as the provided requests.
89
+ *
90
+ * IMPORTANT: This method keeps every request and response in memory, and
91
+ * as such, is NOT recommended when sending a large number or an
92
+ * indeterminate number of requests concurrently.
93
+ *
94
+ * @param ClientInterface $client Client used to send the requests
95
+ * @param array|\Iterator $requests Requests to send in parallel
96
+ * @param array $options Passes through the options available in
97
+ * {@see GuzzleHttp\Pool::__construct}
98
+ *
99
+ * @return BatchResults Returns a container for the results.
100
+ * @throws \InvalidArgumentException if the event format is incorrect.
101
+ */
102
+ public static function batch(
103
+ ClientInterface $client,
104
+ $requests,
105
+ array $options = []
106
+ ) {
107
+ $hash = new \SplObjectStorage();
108
+ foreach ($requests as $request) {
109
+ $hash->attach($request);
110
+ }
111
+
112
+ // In addition to the normally run events when requests complete, add
113
+ // and event to continuously track the results of transfers in the hash.
114
+ (new self($client, $requests, RequestEvents::convertEventArray(
115
+ $options,
116
+ ['end'],
117
+ [
118
+ 'priority' => RequestEvents::LATE,
119
+ 'fn' => function (EndEvent $e) use ($hash) {
120
+ $hash[$e->getRequest()] = $e->getException()
121
+ ? $e->getException()
122
+ : $e->getResponse();
123
+ }
124
+ ]
125
+ )))->wait();
126
+
127
+ return new BatchResults($hash);
128
+ }
129
+
130
+ /**
131
+ * Creates a Pool and immediately sends the requests.
132
+ *
133
+ * @param ClientInterface $client Client used to send the requests
134
+ * @param array|\Iterator $requests Requests to send in parallel
135
+ * @param array $options Passes through the options available in
136
+ * {@see GuzzleHttp\Pool::__construct}
137
+ */
138
+ public static function send(
139
+ ClientInterface $client,
140
+ $requests,
141
+ array $options = []
142
+ ) {
143
+ (new self($client, $requests, $options))->wait();
144
+ }
145
+
146
+ public function wait()
147
+ {
148
+ if ($this->isRealized) {
149
+ return false;
150
+ }
151
+
152
+ // Seed the pool with N number of requests.
153
+ for ($i = 0; $i < $this->poolSize; $i++) {
154
+ if (!$this->addNextRequest()) {
155
+ break;
156
+ }
157
+ }
158
+
159
+ // Stop if the pool was cancelled while transferring requests.
160
+ if ($this->isRealized) {
161
+ return false;
162
+ }
163
+
164
+ // Wait on any outstanding FutureResponse objects.
165
+ while ($response = array_pop($this->waitQueue)) {
166
+ try {
167
+ $response->wait();
168
+ } catch (\Exception $e) {
169
+ // Eat exceptions because they should be handled asynchronously
170
+ }
171
+ }
172
+
173
+ // Clean up no longer needed state.
174
+ $this->isRealized = true;
175
+ $this->waitQueue = $this->eventListeners = [];
176
+ $this->client = $this->iter = null;
177
+ $this->deferred->resolve(true);
178
+
179
+ return true;
180
+ }
181
+
182
+ /**
183
+ * {@inheritdoc}
184
+ *
185
+ * Attempt to cancel all outstanding requests (requests that are queued for
186
+ * dereferencing). Returns true if all outstanding requests can be
187
+ * cancelled.
188
+ *
189
+ * @return bool
190
+ */
191
+ public function cancel()
192
+ {
193
+ if ($this->isRealized) {
194
+ return false;
195
+ }
196
+
197
+ $success = $this->isRealized = true;
198
+ foreach ($this->waitQueue as $response) {
199
+ if (!$response->cancel()) {
200
+ $success = false;
201
+ }
202
+ }
203
+
204
+ return $success;
205
+ }
206
+
207
+ /**
208
+ * Returns a promise that is invoked when the pool completed. There will be
209
+ * no passed value.
210
+ *
211
+ * {@inheritdoc}
212
+ */
213
+ public function then(
214
+ callable $onFulfilled = null,
215
+ callable $onRejected = null,
216
+ callable $onProgress = null
217
+ ) {
218
+ return $this->promise->then($onFulfilled, $onRejected, $onProgress);
219
+ }
220
+
221
+ public function promise()
222
+ {
223
+ return $this->promise;
224
+ }
225
+
226
+ private function coerceIterable($requests)
227
+ {
228
+ if ($requests instanceof \Iterator) {
229
+ return $requests;
230
+ } elseif (is_array($requests)) {
231
+ return new \ArrayIterator($requests);
232
+ }
233
+
234
+ throw new \InvalidArgumentException('Expected Iterator or array. '
235
+ . 'Found ' . Core::describeType($requests));
236
+ }
237
+
238
+ /**
239
+ * Adds the next request to pool and tracks what requests need to be
240
+ * dereferenced when completing the pool.
241
+ */
242
+ private function addNextRequest()
243
+ {
244
+ if ($this->isRealized || !$this->iter || !$this->iter->valid()) {
245
+ return false;
246
+ }
247
+
248
+ $request = $this->iter->current();
249
+ $this->iter->next();
250
+
251
+ if (!($request instanceof RequestInterface)) {
252
+ throw new \InvalidArgumentException(sprintf(
253
+ 'All requests in the provided iterator must implement '
254
+ . 'RequestInterface. Found %s',
255
+ Core::describeType($request)
256
+ ));
257
+ }
258
+
259
+ // Be sure to use "lazy" futures, meaning they do not send right away.
260
+ $request->getConfig()->set('future', 'lazy');
261
+ $this->attachListeners($request, $this->eventListeners);
262
+ $response = $this->client->send($request);
263
+ $hash = spl_object_hash($request);
264
+ $this->waitQueue[$hash] = $response;
265
+
266
+ // Use this function for both resolution and rejection.
267
+ $fn = function ($value) use ($request, $hash) {
268
+ unset($this->waitQueue[$hash]);
269
+ $result = $value instanceof ResponseInterface
270
+ ? ['request' => $request, 'response' => $value, 'error' => null]
271
+ : ['request' => $request, 'response' => null, 'error' => $value];
272
+ $this->deferred->progress($result);
273
+ $this->addNextRequest();
274
+ };
275
+
276
+ $response->then($fn, $fn);
277
+
278
+ return true;
279
+ }
280
+ }
backend/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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Post;
3
+
4
+ use GuzzleHttp\Message\RequestInterface;
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
12
+ {
13
+ /**
14
+ * Apply headers to the request appropriate for the current state of the object
15
+ *
16
+ * @param RequestInterface $request Request
17
+ */
18
+ public function applyRequestHeaders(RequestInterface $request);
19
+
20
+ /**
21
+ * Set a specific field
22
+ *
23
+ * @param string $name Name of the field to set
24
+ * @param string|array $value Value to set
25
+ */
26
+ public function setField($name, $value);
27
+
28
+ /**
29
+ * Set the aggregation strategy that will be used to turn multi-valued
30
+ * fields into a string.
31
+ *
32
+ * The aggregation function accepts a deeply nested array of query string
33
+ * values and returns a flattened associative array of key value pairs.
34
+ *
35
+ * @param callable $aggregator
36
+ */
37
+ public function setAggregator(callable $aggregator);
38
+
39
+ /**
40
+ * Set to true to force a multipart upload even if there are no files.
41
+ *
42
+ * @param bool $force Set to true to force multipart uploads or false to
43
+ * remove this flag.
44
+ */
45
+ public function forceMultipartUpload($force);
46
+
47
+ /**
48
+ * Replace all existing form fields with an array of fields
49
+ *
50
+ * @param array $fields Associative array of fields to set
51
+ */
52
+ public function replaceFields(array $fields);
53
+
54
+ /**
55
+ * Get a specific field by name
56
+ *
57
+ * @param string $name Name of the POST field to retrieve
58
+ *
59
+ * @return string|null
60
+ */
61
+ public function getField($name);
62
+
63
+ /**
64
+ * Remove a field by name
65
+ *
66
+ * @param string $name Name of the field to remove
67
+ */
68
+ public function removeField($name);
69
+
70
+ /**
71
+ * Returns an associative array of names to values or a query string.
72
+ *
73
+ * @param bool $asString Set to true to retrieve the fields as a query
74
+ * string.
75
+ *
76
+ * @return array|string
77
+ */
78
+ public function getFields($asString = false);
79
+
80
+ /**
81
+ * Returns true if a field is set
82
+ *
83
+ * @param string $name Name of the field to set
84
+ *
85
+ * @return bool
86
+ */
87
+ public function hasField($name);
88
+
89
+ /**
90
+ * Get all of the files
91
+ *
92
+ * @return array Returns an array of PostFileInterface objects
93
+ */
94
+ public function getFiles();
95
+
96
+ /**
97
+ * Get a POST file by name.
98
+ *
99
+ * @param string $name Name of the POST file to retrieve
100
+ *
101
+ * @return PostFileInterface|null
102
+ */
103
+ public function getFile($name);
104
+
105
+ /**
106
+ * Add a file to the POST
107
+ *
108
+ * @param PostFileInterface $file File to add
109
+ */
110
+ public function addFile(PostFileInterface $file);
111
+
112
+ /**
113
+ * Remove all files from the collection
114
+ */
115
+ public function clearFiles();
116
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/RequestFsm.php ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ private $states = [
24
+ // When a mock intercepts the emitted "before" event, then we
25
+ // transition to the "complete" intercept state.
26
+ 'before' => [
27
+ 'success' => 'send',
28
+ 'intercept' => 'complete',
29
+ 'error' => 'error'
30
+ ],
31
+ // The complete and error events are handled using the "then" of
32
+ // the RingPHP request, so we exit the FSM.
33
+ 'send' => ['error' => 'error'],
34
+ 'complete' => [
35
+ 'success' => 'end',
36
+ 'intercept' => 'before',
37
+ 'error' => 'error'
38
+ ],
39
+ 'error' => [
40
+ 'success' => 'complete',
41
+ 'intercept' => 'before',
42
+ 'error' => 'end'
43
+ ],
44
+ 'end' => []
45
+ ];
46
+
47
+ public function __construct(
48
+ callable $handler,
49
+ MessageFactoryInterface $messageFactory,
50
+ $maxTransitions = 200
51
+ ) {
52
+ $this->mf = $messageFactory;
53
+ $this->maxTransitions = $maxTransitions;
54
+ $this->handler = $handler;
55
+ }
56
+
57
+ /**
58
+ * Runs the state machine until a terminal state is entered or the
59
+ * optionally supplied $finalState is entered.
60
+ *
61
+ * @param Transaction $trans Transaction being transitioned.
62
+ * @param string $finalState The state to stop on. If unspecified,
63
+ * runs until a terminal state is found.
64
+ *
65
+ * @throws \Exception if a terminal state throws an exception.
66
+ */
67
+ public function __invoke(Transaction $trans, $finalState = null)
68
+ {
69
+ $trans->_transitionCount = 1;
70
+
71
+ if (!$trans->state) {
72
+ $trans->state = 'before';
73
+ }
74
+
75
+ while ($trans->state !== $finalState) {
76
+
77
+ if (!isset($this->states[$trans->state])) {
78
+ throw new StateException("Invalid state: {$trans->state}");
79
+ } elseif (++$trans->_transitionCount > $this->maxTransitions) {
80
+ throw new StateException('Too many state transitions were '
81
+ . 'encountered ({$trans->_transitionCount}). This likely '
82
+ . 'means that a combination of event listeners are in an '
83
+ . 'infinite loop.');
84
+ }
85
+
86
+ $state = $this->states[$trans->state];
87
+
88
+ try {
89
+ /** @var callable $fn */
90
+ $fn = [$this, $trans->state];
91
+ if ($fn($trans)) {
92
+ // Handles transitioning to the "intercept" state.
93
+ if (isset($state['intercept'])) {
94
+ $trans->state = $state['intercept'];
95
+ continue;
96
+ }
97
+ throw new StateException('Invalid intercept state '
98
+ . 'transition from ' . $trans->state);
99
+ }
100
+
101
+ if (isset($state['success'])) {
102
+ // Transition to the success state
103
+ $trans->state = $state['success'];
104
+ } else {
105
+ // Break: this is a terminal state with no transition.
106
+ break;
107
+ }
108
+
109
+ } catch (StateException $e) {
110
+ // State exceptions are thrown no matter what.
111
+ throw $e;
112
+ } catch (\Exception $e) {
113
+ $trans->exception = $e;
114
+ // Terminal error states throw the exception.
115
+ if (!isset($state['error'])) {
116
+ throw $e;
117
+ }
118
+ // Transition to the error state.
119
+ $trans->state = $state['error'];
120
+ }
121
+ }
122
+ }
123
+
124
+ private function before(Transaction $trans)
125
+ {
126
+ $trans->request->getEmitter()->emit('before', new BeforeEvent($trans));
127
+
128
+ // When a response is set during the before event (i.e., a mock), then
129
+ // we don't need to send anything. Skip ahead to the complete event
130
+ // by returning to to go to the intercept state.
131
+ return (bool) $trans->response;
132
+ }
133
+
134
+ private function send(Transaction $trans)
135
+ {
136
+ $fn = $this->handler;
137
+ $trans->response = FutureResponse::proxy(
138
+ $fn(RingBridge::prepareRingRequest($trans)),
139
+ function ($value) use ($trans) {
140
+ RingBridge::completeRingResponse($trans, $value, $this->mf, $this);
141
+ return $trans->response;
142
+ }
143
+ );
144
+ }
145
+
146
+ /**
147
+ * Emits the error event and ensures that the exception is set and is an
148
+ * instance of RequestException. If the error event is not intercepted,
149
+ * then the exception is thrown and we transition to the "end" event. This
150
+ * event also allows requests to be retried, and when retried, transitions
151
+ * to the "before" event. Otherwise, when no retries, and the exception is
152
+ * intercepted, transition to the "complete" event.
153
+ */
154
+ private function error(Transaction $trans)
155
+ {
156
+ // Convert non-request exception to a wrapped exception
157
+ if (!($trans->exception instanceof RequestException)) {
158
+ $trans->exception = RequestException::wrapException(
159
+ $trans->request, $trans->exception
160
+ );
161
+ }
162
+
163
+ // Dispatch an event and allow interception
164
+ $event = new ErrorEvent($trans);
165
+ $trans->request->getEmitter()->emit('error', $event);
166
+
167
+ if ($trans->exception) {
168
+ throw $trans->exception;
169
+ }
170
+
171
+ $trans->exception = null;
172
+
173
+ // Return true to transition to the 'before' state. False otherwise.
174
+ return $trans->state === 'before';
175
+ }
176
+
177
+ /**
178
+ * Emits a complete event, and if a request is marked for a retry during
179
+ * the complete event, then the "before" state is transitioned to.
180
+ */
181
+ private function complete(Transaction $trans)
182
+ {
183
+ // Futures will have their own end events emitted when dereferenced.
184
+ if ($trans->response instanceof FutureInterface) {
185
+ return false;
186
+ }
187
+
188
+ $trans->response->setEffectiveUrl($trans->request->getUrl());
189
+ $trans->request->getEmitter()->emit('complete', new CompleteEvent($trans));
190
+
191
+ // Return true to transition to the 'before' state. False otherwise.
192
+ return $trans->state === 'before';
193
+ }
194
+
195
+ /**
196
+ * Emits the "end" event and throws an exception if one is present.
197
+ */
198
+ private function end(Transaction $trans)
199
+ {
200
+ // Futures will have their own end events emitted when dereferenced,
201
+ // but still emit, even for futures, when an exception is present.
202
+ if (!$trans->exception && $trans->response instanceof FutureInterface) {
203
+ return;
204
+ }
205
+
206
+ $trans->request->getEmitter()->emit('end', new EndEvent($trans));
207
+
208
+ // Throw exceptions in the terminal event if the exception was not
209
+ // handled by an "end" event listener.
210
+ if ($trans->exception) {
211
+ throw $trans->exception;
212
+ }
213
+ }
214
+ }
backend/vendor/guzzlehttp/guzzle/src/RingBridge.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 any
76
+ * necessary events are emitted based on the ring response.
77
+ *
78
+ * @param Transaction $trans Owns request and response.
79
+ * @param array $response Ring response array
80
+ * @param MessageFactoryInterface $messageFactory Creates response objects.
81
+ * @param callable $fsm Request FSM function.
82
+ */
83
+ public static function completeRingResponse(
84
+ Transaction $trans,
85
+ array $response,
86
+ MessageFactoryInterface $messageFactory,
87
+ callable $fsm
88
+ ) {
89
+ $trans->state = 'complete';
90
+ $trans->transferInfo = isset($response['transfer_stats'])
91
+ ? $response['transfer_stats'] : [];
92
+
93
+ if (!empty($response['status'])) {
94
+ $options = [];
95
+ if (isset($response['version'])) {
96
+ $options['protocol_version'] = $response['version'];
97
+ }
98
+ if (isset($response['reason'])) {
99
+ $options['reason_phrase'] = $response['reason'];
100
+ }
101
+ $trans->response = $messageFactory->createResponse(
102
+ $response['status'],
103
+ isset($response['headers']) ? $response['headers'] : [],
104
+ isset($response['body']) ? $response['body'] : null,
105
+ $options
106
+ );
107
+ if (isset($response['effective_url'])) {
108
+ $trans->response->setEffectiveUrl($response['effective_url']);
109
+ }
110
+ } elseif (empty($response['error'])) {
111
+ // When nothing was returned, then we need to add an error.
112
+ $response['error'] = self::getNoRingResponseException($trans->request);
113
+ }
114
+
115
+ if (isset($response['error'])) {
116
+ $trans->state = 'error';
117
+ $trans->exception = $response['error'];
118
+ }
119
+
120
+ // Complete the lifecycle of the request.
121
+ $fsm($trans);
122
+ }
123
+
124
+ /**
125
+ * Creates a Guzzle request object using a ring request array.
126
+ *
127
+ * @param array $request Ring request
128
+ *
129
+ * @return Request
130
+ * @throws \InvalidArgumentException for incomplete requests.
131
+ */
132
+ public static function fromRingRequest(array $request)
133
+ {
134
+ $options = [];
135
+ if (isset($request['version'])) {
136
+ $options['protocol_version'] = $request['version'];
137
+ }
138
+
139
+ if (!isset($request['http_method'])) {
140
+ throw new \InvalidArgumentException('No http_method');
141
+ }
142
+
143
+ return new Request(
144
+ $request['http_method'],
145
+ Core::url($request),
146
+ isset($request['headers']) ? $request['headers'] : [],
147
+ isset($request['body']) ? Stream::factory($request['body']) : null,
148
+ $options
149
+ );
150
+ }
151
+
152
+ /**
153
+ * Get an exception that can be used when a RingPHP handler does not
154
+ * populate a response.
155
+ *
156
+ * @param RequestInterface $request
157
+ *
158
+ * @return RequestException
159
+ */
160
+ public static function getNoRingResponseException(RequestInterface $request)
161
+ {
162
+ $message = <<<EOT
163
+ Sending the request did not return a response, exception, or populate the
164
+ transaction with a response. This is most likely due to an incorrectly
165
+ implemented RingPHP handler. If you are simply trying to mock responses,
166
+ then it is recommneded to use the GuzzleHttp\Ring\Client\MockHandler.
167
+ EOT;
168
+ return new RequestException($message, $request);
169
+ }
170
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
11
+ /**
12
+ * Queues mock responses or exceptions and delivers mock responses or
13
+ * exceptions in a fifo order.
14
+ */
15
+ class Mock implements SubscriberInterface, \Countable
16
+ {
17
+ /** @var array Array of mock responses / exceptions */
18
+ private $queue = [];
19
+
20
+ /** @var bool Whether or not to consume an entity body when mocking */
21
+ private $readBodies;
22
+
23
+ /** @var MessageFactory */
24
+ private $factory;
25
+
26
+ /**
27
+ * @param array $items Array of responses or exceptions to queue
28
+ * @param bool $readBodies Set to false to not consume the entity body of
29
+ * a request when a mock is served.
30
+ */
31
+ public function __construct(array $items = [], $readBodies = true)
32
+ {
33
+ $this->factory = new MessageFactory();
34
+ $this->readBodies = $readBodies;
35
+ $this->addMultiple($items);
36
+ }
37
+
38
+ public function getEvents()
39
+ {
40
+ // Fire the event last, after signing
41
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST - 10]];
42
+ }
43
+
44
+ /**
45
+ * @throws \OutOfBoundsException|\Exception
46
+ */
47
+ public function onBefore(BeforeEvent $event)
48
+ {
49
+ if (!$item = array_shift($this->queue)) {
50
+ throw new \OutOfBoundsException('Mock queue is empty');
51
+ } elseif ($item instanceof RequestException) {
52
+ throw $item;
53
+ }
54
+
55
+ // Emulate reading a response body
56
+ $request = $event->getRequest();
57
+ if ($this->readBodies && $request->getBody()) {
58
+ while (!$request->getBody()->eof()) {
59
+ $request->getBody()->read(8096);
60
+ }
61
+ }
62
+
63
+ $event->intercept($item);
64
+ }
65
+
66
+ public function count()
67
+ {
68
+ return count($this->queue);
69
+ }
70
+
71
+ /**
72
+ * Add a response to the end of the queue
73
+ *
74
+ * @param string|ResponseInterface $response Response or path to response file
75
+ *
76
+ * @return self
77
+ * @throws \InvalidArgumentException if a string or Response is not passed
78
+ */
79
+ public function addResponse($response)
80
+ {
81
+ if (is_string($response)) {
82
+ $response = file_exists($response)
83
+ ? $this->factory->fromMessage(file_get_contents($response))
84
+ : $this->factory->fromMessage($response);
85
+ } elseif (!($response instanceof ResponseInterface)) {
86
+ throw new \InvalidArgumentException('Response must a message '
87
+ . 'string, response object, or path to a file');
88
+ }
89
+
90
+ $this->queue[] = $response;
91
+
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Add an exception to the end of the queue
97
+ *
98
+ * @param RequestException $e Exception to throw when the request is executed
99
+ *
100
+ * @return self
101
+ */
102
+ public function addException(RequestException $e)
103
+ {
104
+ $this->queue[] = $e;
105
+
106
+ return $this;
107
+ }
108
+
109
+ /**
110
+ * Add multiple items to the queue
111
+ *
112
+ * @param array $items Items to add
113
+ */
114
+ public function addMultiple(array $items)
115
+ {
116
+ foreach ($items as $item) {
117
+ if ($item instanceof RequestException) {
118
+ $this->addException($item);
119
+ } else {
120
+ $this->addResponse($item);
121
+ }
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Clear the queue
127
+ */
128
+ public function clearQueue()
129
+ {
130
+ $this->queue = [];
131
+ }
132
+ }
backend/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\RequestInterface;
8
+ use GuzzleHttp\Mimetypes;
9
+ use GuzzleHttp\Post\PostBodyInterface;
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 PostBodyInterface) {
44
+ // Synchronize the POST body with the request's 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
+ }
backend/vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\CouldNotRewindStreamException;
8
+ use GuzzleHttp\Exception\TooManyRedirectsException;
9
+ use GuzzleHttp\Message\RequestInterface;
10
+ use GuzzleHttp\Message\ResponseInterface;
11
+ use GuzzleHttp\Url;
12
+
13
+ /**
14
+ * Subscriber used to implement HTTP redirects.
15
+ *
16
+ * **Request options**
17
+ *
18
+ * - redirect: Associative array containing the 'max', 'strict', and 'referer'
19
+ * keys.
20
+ *
21
+ * - max: Maximum number of redirects allowed per-request
22
+ * - strict: You can use strict redirects by setting this value to ``true``.
23
+ * Strict redirects adhere to strict RFC compliant redirection (e.g.,
24
+ * redirect POST with POST) vs doing what most clients do (e.g., redirect
25
+ * POST request with a GET request).
26
+ * - referer: Set to true to automatically add the "Referer" header when a
27
+ * redirect request is sent.
28
+ */
29
+ class Redirect implements SubscriberInterface
30
+ {
31
+ public function getEvents()
32
+ {
33
+ return ['complete' => ['onComplete', RequestEvents::REDIRECT_RESPONSE]];
34
+ }
35
+
36
+ /**
37
+ * Rewind the entity body of the request if needed
38
+ *
39
+ * @param RequestInterface $redirectRequest
40
+ * @throws CouldNotRewindStreamException
41
+ */
42
+ public static function rewindEntityBody(RequestInterface $redirectRequest)
43
+ {
44
+ // Rewind the entity body of the request if needed
45
+ if ($body = $redirectRequest->getBody()) {
46
+ // Only rewind the body if some of it has been read already, and
47
+ // throw an exception if the rewind fails
48
+ if ($body->tell() && !$body->seek(0)) {
49
+ throw new CouldNotRewindStreamException(
50
+ 'Unable to rewind the non-seekable request body after redirecting',
51
+ $redirectRequest
52
+ );
53
+ }
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Called when a request receives a redirect response
59
+ *
60
+ * @param CompleteEvent $event Event emitted
61
+ * @throws TooManyRedirectsException
62
+ */
63
+ public function onComplete(CompleteEvent $event)
64
+ {
65
+ $response = $event->getResponse();
66
+
67
+ if (substr($response->getStatusCode(), 0, 1) != '3'
68
+ || !$response->hasHeader('Location')
69
+ ) {
70
+ return;
71
+ }
72
+
73
+ $request = $event->getRequest();
74
+ $config = $request->getConfig();
75
+
76
+ // Increment the redirect and initialize the redirect state.
77
+ if ($redirectCount = $config['redirect_count']) {
78
+ $config['redirect_count'] = ++$redirectCount;
79
+ } else {
80
+ $config['redirect_scheme'] = $request->getScheme();
81
+ $config['redirect_count'] = $redirectCount = 1;
82
+ }
83
+
84
+ $max = $config->getPath('redirect/max') ?: 5;
85
+
86
+ if ($redirectCount > $max) {
87
+ throw new TooManyRedirectsException(
88
+ "Will not follow more than {$redirectCount} redirects",
89
+ $request
90
+ );
91
+ }
92
+
93
+ $this->modifyRedirectRequest($request, $response);
94
+ $event->retry();
95
+ }
96
+
97
+ private function modifyRedirectRequest(
98
+ RequestInterface $request,
99
+ ResponseInterface $response
100
+ ) {
101
+ $config = $request->getConfig();
102
+
103
+ // Use a GET request if this is an entity enclosing request and we are
104
+ // not forcing RFC compliance, but rather emulating what all browsers
105
+ // would do.
106
+ $statusCode = $response->getStatusCode();
107
+ if ($statusCode == 303 ||
108
+ ($statusCode <= 302 && $request->getBody() && !$config->getPath('redirect/strict'))
109
+ ) {
110
+ $request->setMethod('GET');
111
+ $request->setBody(null);
112
+ }
113
+
114
+ $previousUrl = $request->getUrl();
115
+ $this->setRedirectUrl($request, $response);
116
+ $this->rewindEntityBody($request);
117
+
118
+ // Add the Referer header if it is told to do so and only
119
+ // add the header if we are not redirecting from https to http.
120
+ if ($config->getPath('redirect/referer')
121
+ && ($request->getScheme() == 'https' || $request->getScheme() == $config['redirect_scheme'])
122
+ ) {
123
+ $url = Url::fromString($previousUrl);
124
+ $url->setUsername(null);
125
+ $url->setPassword(null);
126
+ $request->setHeader('Referer', (string) $url);
127
+ } else {
128
+ $request->removeHeader('Referer');
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Set the appropriate URL on the request based on the location header
134
+ *
135
+ * @param RequestInterface $request
136
+ * @param ResponseInterface $response
137
+ */
138
+ private function setRedirectUrl(
139
+ RequestInterface $request,
140
+ ResponseInterface $response
141
+ ) {
142
+ $location = $response->getHeader('Location');
143
+ $location = Url::fromString($location);
144
+
145
+ // Combine location with the original URL if it is not absolute.
146
+ if (!$location->isAbsolute()) {
147
+ $originalUrl = Url::fromString($request->getUrl());
148
+ // Remove query string parameters and just take what is present on
149
+ // the redirect Location header
150
+ $originalUrl->getQuery()->clear();
151
+ $location = $originalUrl->combine($location);
152
+ }
153
+
154
+ $request->setUrl($location);
155
+ }
156
+ }
backend/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
+ }
backend/vendor/guzzlehttp/guzzle/src/Transaction.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 transaction's state.
60
+ *
61
+ * @var string
62
+ */
63
+ public $state;
64
+
65
+ /**
66
+ * The number of state transitions that this transactions has been through.
67
+ *
68
+ * @var int
69
+ * @internal This is for internal use only. If you modify this, then you
70
+ * are asking for trouble.
71
+ */
72
+ public $_transitionCount;
73
+
74
+ /**
75
+ * @param ClientInterface $client Client that is used to send the requests
76
+ * @param RequestInterface $request Request to send
77
+ */
78
+ public function __construct(
79
+ ClientInterface $client,
80
+ RequestInterface $request
81
+ ) {
82
+ $this->client = $client;
83
+ $this->request = $request;
84
+ }
85
+ }
backend/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
+ }
backend/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 $query = null,
139
+ $fragment = null
140
+ ) {
141
+ $this->scheme = $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 = $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
+ }
backend/vendor/guzzlehttp/guzzle/src/Utils.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Utility methods used throughout Guzzle.
6
+ */
7
+ final class Utils
8
+ {
9
+ /**
10
+ * Gets a value from an array using a path syntax to retrieve nested data.
11
+ *
12
+ * This method does not allow for keys that contain "/". You must traverse
13
+ * the array manually or using something more advanced like JMESPath to
14
+ * work with keys that contain "/".
15
+ *
16
+ * // Get the bar key of a set of nested arrays.
17
+ * // This is equivalent to $collection['foo']['baz']['bar'] but won't
18
+ * // throw warnings for missing keys.
19
+ * GuzzleHttp\get_path($data, 'foo/baz/bar');
20
+ *
21
+ * @param array $data Data to retrieve values from
22
+ * @param string $path Path to traverse and retrieve a value from
23
+ *
24
+ * @return mixed|null
25
+ */
26
+ public static function getPath($data, $path)
27
+ {
28
+ $path = explode('/', $path);
29
+
30
+ while (null !== ($part = array_shift($path))) {
31
+ if (!is_array($data) || !isset($data[$part])) {
32
+ return null;
33
+ }
34
+ $data = $data[$part];
35
+ }
36
+
37
+ return $data;
38
+ }
39
+
40
+ /**
41
+ * Set a value in a nested array key. Keys will be created as needed to set
42
+ * the value.
43
+ *
44
+ * This function does not support keys that contain "/" or "[]" characters
45
+ * because these are special tokens used when traversing the data structure.
46
+ * A value may be prepended to an existing array by using "[]" as the final
47
+ * key of a path.
48
+ *
49
+ * GuzzleHttp\get_path($data, 'foo/baz'); // null
50
+ * GuzzleHttp\set_path($data, 'foo/baz/[]', 'a');
51
+ * GuzzleHttp\set_path($data, 'foo/baz/[]', 'b');
52
+ * GuzzleHttp\get_path($data, 'foo/baz');
53
+ * // Returns ['a', 'b']
54
+ *
55
+ * @param array $data Data to modify by reference
56
+ * @param string $path Path to set
57
+ * @param mixed $value Value to set at the key
58
+ *
59
+ * @throws \RuntimeException when trying to setPath using a nested path
60
+ * that travels through a scalar value.
61
+ */
62
+ public static function setPath(&$data, $path, $value)
63
+ {
64
+ $current =& $data;
65
+ $queue = explode('/', $path);
66
+ while (null !== ($key = array_shift($queue))) {
67
+ if (!is_array($current)) {
68
+ throw new \RuntimeException("Trying to setPath {$path}, but "
69
+ . "{$key} is set and is not an array");
70
+ } elseif (!$queue) {
71
+ if ($key == '[]') {
72
+ $current[] = $value;
73
+ } else {
74
+ $current[$key] = $value;
75
+ }
76
+ } elseif (isset($current[$key])) {
77
+ $current =& $current[$key];
78
+ } else {
79
+ $current[$key] = [];
80
+ $current =& $current[$key];
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Expands a URI template
87
+ *
88
+ * @param string $template URI template
89
+ * @param array $variables Template variables
90
+ *
91
+ * @return string
92
+ */
93
+ public static function uriTemplate($template, array $variables)
94
+ {
95
+ if (function_exists('\\uri_template')) {
96
+ return \uri_template($template, $variables);
97
+ }
98
+
99
+ static $uriTemplate;
100
+ if (!$uriTemplate) {
101
+ $uriTemplate = new UriTemplate();
102
+ }
103
+
104
+ return $uriTemplate->expand($template, $variables);
105
+ }
106
+
107
+ /**
108
+ * Wrapper for JSON decode that implements error detection with helpful
109
+ * error messages.
110
+ *
111
+ * @param string $json JSON data to parse
112
+ * @param bool $assoc When true, returned objects will be converted
113
+ * into associative arrays.
114
+ * @param int $depth User specified recursion depth.
115
+ * @param int $options Bitmask of JSON decode options.
116
+ *
117
+ * @return mixed
118
+ * @throws \InvalidArgumentException if the JSON cannot be parsed.
119
+ * @link http://www.php.net/manual/en/function.json-decode.php
120
+ */
121
+ public static function jsonDecode($json, $assoc = false, $depth = 512, $options = 0)
122
+ {
123
+ static $jsonErrors = [
124
+ JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH - Maximum stack depth exceeded',
125
+ JSON_ERROR_STATE_MISMATCH => 'JSON_ERROR_STATE_MISMATCH - Underflow or the modes mismatch',
126
+ JSON_ERROR_CTRL_CHAR => 'JSON_ERROR_CTRL_CHAR - Unexpected control character found',
127
+ JSON_ERROR_SYNTAX => 'JSON_ERROR_SYNTAX - Syntax error, malformed JSON',
128
+ JSON_ERROR_UTF8 => 'JSON_ERROR_UTF8 - Malformed UTF-8 characters, possibly incorrectly encoded'
129
+ ];
130
+
131
+ $data = \json_decode($json, $assoc, $depth, $options);
132
+
133
+ if (JSON_ERROR_NONE !== json_last_error()) {
134
+ $last = json_last_error();
135
+ throw new \InvalidArgumentException(
136
+ 'Unable to parse JSON data: '
137
+ . (isset($jsonErrors[$last])
138
+ ? $jsonErrors[$last]
139
+ : 'Unknown error')
140
+ );
141
+ }
142
+
143
+ return $data;
144
+ }
145
+ }
backend/vendor/guzzlehttp/ringphp/.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ vendor
2
+ build/artifacts/
3
+ composer.lock
4
+ docs/_build/
backend/vendor/guzzlehttp/ringphp/.travis.yml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ - ~/.nvm/nvm.sh install v0.6.14
13
+ - ~/.nvm/nvm.sh run v0.6.14
14
+
15
+ script:
16
+ - make test
17
+
18
+ matrix:
19
+ allow_failures:
20
+ - php: hhvm
21
+ fast_finish: true
backend/vendor/guzzlehttp/ringphp/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CHANGELOG
2
+
3
+ ## 1.0.3 - 2014-11-03
4
+
5
+ * Setting the `header` stream option as a string to be compatible with GAE.
6
+ * Header parsing now ensures that header order is maintained in the parsed
7
+ message.
8
+
9
+ ## 1.0.2 - 2014-10-28
10
+
11
+ * Now correctly honoring a `version` option is supplied in a request.
12
+ See https://github.com/guzzle/RingPHP/pull/8
13
+
14
+ ## 1.0.1 - 2014-10-26
15
+
16
+ * Fixed a header parsing issue with the `CurlHandler` and `CurlMultiHandler`
17
+ that caused cURL requests with multiple responses to merge repsonses together
18
+ (e.g., requests with digest authentication).
19
+
20
+ ## 1.0.0 - 2014-10-12
21
+
22
+ * Initial release.
backend/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.
backend/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
backend/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.
backend/vendor/guzzlehttp/ringphp/composer.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "guzzlehttp/ringphp",
3
+ "license": "MIT",
4
+ "authors": [
5
+ {
6
+ "name": "Michael Dowling",
7
+ "email": "mtdowling@gmail.com",
8
+ "homepage": "https://github.com/mtdowling"
9
+ }
10
+ ],
11
+ "require": {
12
+ "php": ">=5.4.0",
13
+ "guzzlehttp/streams": "~3.0",
14
+ "react/promise": "~2.0"
15
+ },
16
+ "require-dev": {
17
+ "ext-curl": "*",
18
+ "phpunit/phpunit": "~4.0"
19
+ },
20
+ "suggest": {
21
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
22
+ },
23
+ "autoload": {
24
+ "psr-4": {
25
+ "GuzzleHttp\\Ring\\": "src/"
26
+ }
27
+ },
28
+ "autoload-dev": {
29
+ "psr-4": {
30
+ "GuzzleHttp\\Tests\\Ring\\": "tests/"
31
+ }
32
+ },
33
+ "extra": {
34
+ "branch-alias": {
35
+ "dev-master": "1.0-dev"
36
+ }
37
+ }
38
+ }
backend/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."
backend/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.
backend/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
+ ]);
backend/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()]
backend/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
+ );
backend/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.
backend/vendor/guzzlehttp/ringphp/docs/requirements.txt ADDED
@@ -0,0 +1 @@
 
1
+ sphinx_rtd_theme
backend/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 **/]);
backend/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']);
backend/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>
backend/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/latest/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
+ }
backend/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php ADDED
@@ -0,0 +1,538 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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['status'] = isset($startLine[1]) ? (int) $startLine[1] : null;
84
+ $response['reason'] = isset($startLine[2]) ? $startLine[2] : null;
85
+ $response['body'] = $body;
86
+ Core::rewindBody($response);
87
+ }
88
+
89
+ return !empty($response['curl']['errno']) || !isset($response['status'])
90
+ ? self::createErrorResponse($handler, $request, $response)
91
+ : $response;
92
+ }
93
+
94
+ private static function createErrorResponse(
95
+ callable $handler,
96
+ array $request,
97
+ array $response
98
+ ) {
99
+ static $connectionErrors = [
100
+ CURLE_OPERATION_TIMEOUTED => true,
101
+ CURLE_COULDNT_RESOLVE_HOST => true,
102
+ CURLE_COULDNT_CONNECT => true,
103
+ CURLE_SSL_CONNECT_ERROR => true,
104
+ CURLE_GOT_NOTHING => true,
105
+ ];
106
+
107
+ // Retry when nothing is present or when curl failed to rewind.
108
+ if (!isset($response['err_message'])
109
+ && (empty($response['curl']['errno'])
110
+ || $response['curl']['errno'] == 65)
111
+ ) {
112
+ return self::retryFailedRewind($handler, $request, $response);
113
+ }
114
+
115
+ $message = isset($response['err_message'])
116
+ ? $response['err_message']
117
+ : sprintf('cURL error %s: %s',
118
+ $response['curl']['errno'],
119
+ isset($response['curl']['error'])
120
+ ? $response['curl']['error']
121
+ : 'See http://curl.haxx.se/libcurl/c/libcurl-errors.html');
122
+
123
+ $error = isset($response['curl']['errno'])
124
+ && isset($connectionErrors[$response['curl']['errno']])
125
+ ? new ConnectException($message)
126
+ : new RingException($message);
127
+
128
+ return $response + [
129
+ 'status' => null,
130
+ 'reason' => null,
131
+ 'body' => null,
132
+ 'headers' => [],
133
+ 'error' => $error,
134
+ ];
135
+ }
136
+
137
+ private function getOutputBody(array $request, array &$options)
138
+ {
139
+ // Determine where the body of the response (if any) will be streamed.
140
+ if (isset($options[CURLOPT_WRITEFUNCTION])) {
141
+ return $request['client']['save_to'];
142
+ }
143
+
144
+ if (isset($options[CURLOPT_FILE])) {
145
+ return $options[CURLOPT_FILE];
146
+ }
147
+
148
+ if ($request['http_method'] != 'HEAD') {
149
+ // Create a default body if one was not provided
150
+ return $options[CURLOPT_FILE] = fopen('php://temp', 'w+');
151
+ }
152
+
153
+ return null;
154
+ }
155
+
156
+ private function getDefaultOptions(array $request, array &$headers)
157
+ {
158
+ $url = Core::url($request);
159
+ $startingResponse = false;
160
+
161
+ $options = [
162
+ '_headers' => $request['headers'],
163
+ CURLOPT_CUSTOMREQUEST => $request['http_method'],
164
+ CURLOPT_URL => $url,
165
+ CURLOPT_RETURNTRANSFER => false,
166
+ CURLOPT_HEADER => false,
167
+ CURLOPT_CONNECTTIMEOUT => 150,
168
+ CURLOPT_HEADERFUNCTION => function ($ch, $h) use (&$headers, &$startingResponse) {
169
+ $value = trim($h);
170
+ if ($value === '') {
171
+ $startingResponse = true;
172
+ } elseif ($startingResponse) {
173
+ $startingResponse = false;
174
+ $headers = [$value];
175
+ } else {
176
+ $headers[] = $value;
177
+ }
178
+ return strlen($h);
179
+ },
180
+ ];
181
+
182
+ if (isset($request['version'])) {
183
+ $options[CURLOPT_HTTP_VERSION] = $request['version'] == 1.1 ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
184
+ }
185
+
186
+ if (defined('CURLOPT_PROTOCOLS')) {
187
+ $options[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
188
+ }
189
+
190
+ return $options;
191
+ }
192
+
193
+ private function applyMethod(array $request, array &$options)
194
+ {
195
+ if (isset($request['body'])) {
196
+ $this->applyBody($request, $options);
197
+ return;
198
+ }
199
+
200
+ switch ($request['http_method']) {
201
+ case 'PUT':
202
+ case 'POST':
203
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
204
+ if (!Core::hasHeader($request, 'Content-Length')) {
205
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
206
+ }
207
+ break;
208
+ case 'HEAD':
209
+ $options[CURLOPT_NOBODY] = true;
210
+ unset(
211
+ $options[CURLOPT_WRITEFUNCTION],
212
+ $options[CURLOPT_READFUNCTION],
213
+ $options[CURLOPT_FILE],
214
+ $options[CURLOPT_INFILE]
215
+ );
216
+ }
217
+ }
218
+
219
+ private function applyBody(array $request, array &$options)
220
+ {
221
+ $contentLength = Core::firstHeader($request, 'Content-Length');
222
+ $size = $contentLength !== null ? (int) $contentLength : null;
223
+
224
+ // Send the body as a string if the size is less than 1MB OR if the
225
+ // [client][curl][body_as_string] request value is set.
226
+ if (($size !== null && $size < 1000000) ||
227
+ isset($request['client']['curl']['body_as_string']) ||
228
+ is_string($request['body'])
229
+ ) {
230
+ $options[CURLOPT_POSTFIELDS] = Core::body($request);
231
+ // Don't duplicate the Content-Length header
232
+ $this->removeHeader('Content-Length', $options);
233
+ $this->removeHeader('Transfer-Encoding', $options);
234
+ } else {
235
+ $options[CURLOPT_UPLOAD] = true;
236
+ if ($size !== null) {
237
+ // Let cURL handle setting the Content-Length header
238
+ $options[CURLOPT_INFILESIZE] = $size;
239
+ $this->removeHeader('Content-Length', $options);
240
+ }
241
+ $this->addStreamingBody($request, $options);
242
+ }
243
+
244
+ // If the Expect header is not present, prevent curl from adding it
245
+ if (!Core::hasHeader($request, 'Expect')) {
246
+ $options[CURLOPT_HTTPHEADER][] = 'Expect:';
247
+ }
248
+
249
+ // cURL sometimes adds a content-type by default. Prevent this.
250
+ if (!Core::hasHeader($request, 'Content-Type')) {
251
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Type:';
252
+ }
253
+ }
254
+
255
+ private function addStreamingBody(array $request, array &$options)
256
+ {
257
+ $body = $request['body'];
258
+
259
+ if ($body instanceof StreamInterface) {
260
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
261
+ return (string) $body->read($length);
262
+ };
263
+ if (!isset($options[CURLOPT_INFILESIZE])) {
264
+ if ($size = $body->getSize()) {
265
+ $options[CURLOPT_INFILESIZE] = $size;
266
+ }
267
+ }
268
+ } elseif (is_resource($body)) {
269
+ $options[CURLOPT_INFILE] = $body;
270
+ } elseif ($body instanceof \Iterator) {
271
+ $buf = '';
272
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body, &$buf) {
273
+ if ($body->valid()) {
274
+ $buf .= $body->current();
275
+ $body->next();
276
+ }
277
+ $result = (string) substr($buf, 0, $length);
278
+ $buf = substr($buf, $length);
279
+ return $result;
280
+ };
281
+ } else {
282
+ throw new \InvalidArgumentException('Invalid request body provided');
283
+ }
284
+ }
285
+
286
+ private function applyHeaders(array $request, array &$options)
287
+ {
288
+ foreach ($options['_headers'] as $name => $values) {
289
+ foreach ($values as $value) {
290
+ $options[CURLOPT_HTTPHEADER][] = "$name: $value";
291
+ }
292
+ }
293
+
294
+ // Remove the Accept header if one was not set
295
+ if (!Core::hasHeader($request, 'Accept')) {
296
+ $options[CURLOPT_HTTPHEADER][] = 'Accept:';
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Takes an array of curl options specified in the 'curl' option of a
302
+ * request's configuration array and maps them to CURLOPT_* options.
303
+ *
304
+ * This method is only called when a request has a 'curl' config setting.
305
+ *
306
+ * @param array $config Configuration array of custom curl option
307
+ * @param array $options Array of existing curl options
308
+ *
309
+ * @return array Returns a new array of curl options
310
+ */
311
+ private function applyCustomCurlOptions(array $config, array $options)
312
+ {
313
+ $curlOptions = [];
314
+ foreach ($config as $key => $value) {
315
+ if (is_int($key)) {
316
+ $curlOptions[$key] = $value;
317
+ }
318
+ }
319
+
320
+ return $curlOptions + $options;
321
+ }
322
+
323
+ /**
324
+ * Remove a header from the options array.
325
+ *
326
+ * @param string $name Case-insensitive header to remove
327
+ * @param array $options Array of options to modify
328
+ */
329
+ private function removeHeader($name, array &$options)
330
+ {
331
+ foreach (array_keys($options['_headers']) as $key) {
332
+ if (!strcasecmp($key, $name)) {
333
+ unset($options['_headers'][$key]);
334
+ return;
335
+ }
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Applies an array of request client options to a the options array.
341
+ *
342
+ * This method uses a large switch rather than double-dispatch to save on
343
+ * high overhead of calling functions in PHP.
344
+ */
345
+ private function applyHandlerOptions(array $request, array &$options)
346
+ {
347
+ foreach ($request['client'] as $key => $value) {
348
+ switch ($key) {
349
+ // Violating PSR-4 to provide more room.
350
+ case 'verify':
351
+
352
+ if ($value === false) {
353
+ unset($options[CURLOPT_CAINFO]);
354
+ $options[CURLOPT_SSL_VERIFYHOST] = 0;
355
+ $options[CURLOPT_SSL_VERIFYPEER] = false;
356
+ continue;
357
+ }
358
+
359
+ $options[CURLOPT_SSL_VERIFYHOST] = 2;
360
+ $options[CURLOPT_SSL_VERIFYPEER] = true;
361
+
362
+ if (is_string($value)) {
363
+ $options[CURLOPT_CAINFO] = $value;
364
+ if (!file_exists($value)) {
365
+ throw new \InvalidArgumentException(
366
+ "SSL CA bundle not found: $value"
367
+ );
368
+ }
369
+ }
370
+ break;
371
+
372
+ case 'decode_content':
373
+
374
+ if ($value === false) {
375
+ continue;
376
+ }
377
+
378
+ $accept = Core::firstHeader($request, 'Accept-Encoding');
379
+ if ($accept) {
380
+ $options[CURLOPT_ENCODING] = $accept;
381
+ } else {
382
+ $options[CURLOPT_ENCODING] = '';
383
+ // Don't let curl send the header over the wire
384
+ $options[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
385
+ }
386
+ break;
387
+
388
+ case 'save_to':
389
+
390
+ if (is_string($value)) {
391
+ $value = new LazyOpenStream($value, 'w+');
392
+ }
393
+
394
+ if ($value instanceof StreamInterface) {
395
+ $options[CURLOPT_WRITEFUNCTION] =
396
+ function ($ch, $write) use ($value) {
397
+ return $value->write($write);
398
+ };
399
+ } elseif (is_resource($value)) {
400
+ $options[CURLOPT_FILE] = $value;
401
+ } else {
402
+ throw new \InvalidArgumentException('save_to must be a '
403
+ . 'GuzzleHttp\Stream\StreamInterface or resource');
404
+ }
405
+ break;
406
+
407
+ case 'timeout':
408
+
409
+ $options[CURLOPT_TIMEOUT_MS] = $value * 1000;
410
+ break;
411
+
412
+ case 'connect_timeout':
413
+
414
+ $options[CURLOPT_CONNECTTIMEOUT_MS] = $value * 1000;
415
+ break;
416
+
417
+ case 'proxy':
418
+
419
+ if (!is_array($value)) {
420
+ $options[CURLOPT_PROXY] = $value;
421
+ } elseif (isset($request['scheme'])) {
422
+ $scheme = $request['scheme'];
423
+ if (isset($value[$scheme])) {
424
+ $options[CURLOPT_PROXY] = $value[$scheme];
425
+ }
426
+ }
427
+ break;
428
+
429
+ case 'cert':
430
+
431
+ if (is_array($value)) {
432
+ $options[CURLOPT_SSLCERTPASSWD] = $value[1];
433
+ $value = $value[0];
434
+ }
435
+
436
+ if (!file_exists($value)) {
437
+ throw new \InvalidArgumentException(
438
+ "SSL certificate not found: {$value}"
439
+ );
440
+ }
441
+
442
+ $options[CURLOPT_SSLCERT] = $value;
443
+ break;
444
+
445
+ case 'ssl_key':
446
+
447
+ if (is_array($value)) {
448
+ $options[CURLOPT_SSLKEYPASSWD] = $value[1];
449
+ $value = $value[0];
450
+ }
451
+
452
+ if (!file_exists($value)) {
453
+ throw new \InvalidArgumentException(
454
+ "SSL private key not found: {$value}"
455
+ );
456
+ }
457
+
458
+ $options[CURLOPT_SSLKEY] = $value;
459
+ break;
460
+
461
+ case 'progress':
462
+
463
+ if (!is_callable($value)) {
464
+ throw new \InvalidArgumentException(
465
+ 'progress client option must be callable'
466
+ );
467
+ }
468
+
469
+ $options[CURLOPT_NOPROGRESS] = false;
470
+ $options[CURLOPT_PROGRESSFUNCTION] =
471
+ function () use ($value) {
472
+ $args = func_get_args();
473
+ // PHP 5.5 pushed the handle onto the start of the args
474
+ if (is_resource($args[0])) {
475
+ array_shift($args);
476
+ }
477
+ call_user_func_array($value, $args);
478
+ };
479
+ break;
480
+
481
+ case 'debug':
482
+
483
+ if ($value) {
484
+ $options[CURLOPT_STDERR] = Core::getDebugResource($value);
485
+ $options[CURLOPT_VERBOSE] = true;
486
+ }
487
+ break;
488
+ }
489
+ }
490
+ }
491
+
492
+ /**
493
+ * This function ensures that a response was set on a transaction. If one
494
+ * was not set, then the request is retried if possible. This error
495
+ * typically means you are sending a payload, curl encountered a
496
+ * "Connection died, retrying a fresh connect" error, tried to rewind the
497
+ * stream, and then encountered a "necessary data rewind wasn't possible"
498
+ * error, causing the request to be sent through curl_multi_info_read()
499
+ * without an error status.
500
+ */
501
+ private static function retryFailedRewind(
502
+ callable $handler,
503
+ array $request,
504
+ array $response
505
+ ) {
506
+ // If there is no body, then there is some other kind of issue. This
507
+ // is weird and should probably never happen.
508
+ if (!isset($request['body'])) {
509
+ $response['err_message'] = 'No response was received for a request '
510
+ . 'with no body. This could mean that you are saturating your '
511
+ . 'network.';
512
+ return self::createErrorResponse($handler, $request, $response);
513
+ }
514
+
515
+ if (!Core::rewindBody($request)) {
516
+ $response['err_message'] = 'The connection unexpectedly failed '
517
+ . 'without providing an error. The request would have been '
518
+ . 'retried, but attempting to rewind the request body failed.';
519
+ return self::createErrorResponse($handler, $request, $response);
520
+ }
521
+
522
+ // Retry no more than 3 times before giving up.
523
+ if (!isset($request['curl']['retries'])) {
524
+ $request['curl']['retries'] = 1;
525
+ } elseif ($request['curl']['retries'] == 2) {
526
+ $response['err_message'] = 'The cURL request was retried 3 times '
527
+ . 'and did no succeed. cURL was unable to rewind the body of '
528
+ . 'the request and subsequent retries resulted in the same '
529
+ . 'error. Turn on the debug option to see what went wrong. '
530
+ . 'See https://bugs.php.net/bug.php?id=47204 for more information.';
531
+ return self::createErrorResponse($handler, $request, $response);
532
+ } else {
533
+ $request['curl']['retries']++;
534
+ }
535
+
536
+ return $handler($request);
537
+ }
538
+ }
backend/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ public function __invoke(array $request)
61
+ {
62
+ $factory = $this->factory;
63
+
64
+ // Ensure headers are by reference. They're updated elsewhere.
65
+ $result = $factory($request, $this->checkoutEasyHandle());
66
+ $h = $result[0];
67
+ $hd =& $result[1];
68
+ $bd = $result[2];
69
+ Core::doSleep($request);
70
+ curl_exec($h);
71
+ $response = ['transfer_stats' => curl_getinfo($h)];
72
+ $response['curl']['error'] = curl_error($h);
73
+ $response['curl']['errno'] = curl_errno($h);
74
+ $this->releaseEasyHandle($h);
75
+
76
+ return new CompletedFutureArray(
77
+ CurlFactory::createResponse($this, $request, $response, $hd, $bd)
78
+ );
79
+ }
80
+
81
+ private function checkoutEasyHandle()
82
+ {
83
+ // Find an unused handle in the cache
84
+ if (false !== ($key = array_search(false, $this->ownedHandles, true))) {
85
+ $this->ownedHandles[$key] = true;
86
+ return $this->handles[$key];
87
+ }
88
+
89
+ // Add a new handle
90
+ $handle = curl_init();
91
+ $id = (int) $handle;
92
+ $this->handles[$id] = $handle;
93
+ $this->ownedHandles[$id] = true;
94
+
95
+ return $handle;
96
+ }
97
+
98
+ private function releaseEasyHandle($handle)
99
+ {
100
+ $id = (int) $handle;
101
+ if (count($this->ownedHandles) > $this->maxHandles) {
102
+ curl_close($this->handles[$id]);
103
+ unset($this->handles[$id], $this->ownedHandles[$id]);
104
+ } else {
105
+ // curl_reset doesn't clear these out for some reason
106
+ static $unsetValues = [
107
+ CURLOPT_HEADERFUNCTION => null,
108
+ CURLOPT_WRITEFUNCTION => null,
109
+ CURLOPT_READFUNCTION => null,
110
+ CURLOPT_PROGRESSFUNCTION => null,
111
+ ];
112
+ curl_setopt_array($handle, $unsetValues);
113
+ curl_reset($handle);
114
+ $this->ownedHandles[$id] = false;
115
+ }
116
+ }
117
+ }
backend/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ class CurlMultiHandler
18
+ {
19
+ /** @var callable */
20
+ private $factory;
21
+ private $selectTimeout;
22
+ private $mh;
23
+ private $active;
24
+ private $handles = [];
25
+ private $delays = [];
26
+ private $maxHandles;
27
+
28
+ /**
29
+ * This handler accepts the following options:
30
+ *
31
+ * - mh: An optional curl_multi resource
32
+ * - handle_factory: An optional callable used to generate curl handle
33
+ * resources. the callable accepts a request hash and returns an array
34
+ * of the handle, headers file resource, and the body resource.
35
+ * - select_timeout: Optional timeout (in seconds) to block before timing
36
+ * out while selecting curl handles. Defaults to 1 second.
37
+ * - max_handles: Optional integer representing the maximum number of
38
+ * open requests. When this number is reached, the queued futures are
39
+ * flushed.
40
+ *
41
+ * @param array $options
42
+ */
43
+ public function __construct(array $options = [])
44
+ {
45
+ $this->mh = isset($options['mh'])
46
+ ? $options['mh'] : curl_multi_init();
47
+ $this->factory = isset($options['handle_factory'])
48
+ ? $options['handle_factory'] : new CurlFactory();
49
+ $this->selectTimeout = isset($options['select_timeout'])
50
+ ? $options['select_timeout'] : 1;
51
+ $this->maxHandles = isset($options['max_handles'])
52
+ ? $options['max_handles'] : 100;
53
+ }
54
+
55
+ public function __destruct()
56
+ {
57
+ // Finish any open connections before terminating the script.
58
+ if ($this->handles) {
59
+ $this->execute();
60
+ }
61
+
62
+ if ($this->mh) {
63
+ curl_multi_close($this->mh);
64
+ $this->mh = null;
65
+ }
66
+ }
67
+
68
+ public function __invoke(array $request)
69
+ {
70
+ $factory = $this->factory;
71
+ $result = $factory($request);
72
+ $entry = [
73
+ 'request' => $request,
74
+ 'response' => [],
75
+ 'handle' => $result[0],
76
+ 'headers' => &$result[1],
77
+ 'body' => $result[2],
78
+ 'deferred' => new Deferred(),
79
+ ];
80
+
81
+ $id = (int) $result[0];
82
+
83
+ $future = new FutureArray(
84
+ $entry['deferred']->promise(),
85
+ [$this, 'execute'],
86
+ function () use ($id) {
87
+ return $this->cancel($id);
88
+ }
89
+ );
90
+
91
+ $this->addRequest($entry);
92
+
93
+ // Transfer outstanding requests if there are too many open handles.
94
+ if (count($this->handles) >= $this->maxHandles) {
95
+ $this->execute();
96
+ }
97
+
98
+ return $future;
99
+ }
100
+
101
+ /**
102
+ * Runs until all outstanding connections have completed.
103
+ */
104
+ public function execute()
105
+ {
106
+ do {
107
+
108
+ if ($this->active &&
109
+ curl_multi_select($this->mh, $this->selectTimeout) === -1
110
+ ) {
111
+ // Perform a usleep if a select returns -1.
112
+ // See: https://bugs.php.net/bug.php?id=61141
113
+ usleep(250);
114
+ }
115
+
116
+ // Add any delayed futures if needed.
117
+ if ($this->delays) {
118
+ $this->addDelays();
119
+ }
120
+
121
+ do {
122
+ $mrc = curl_multi_exec($this->mh, $this->active);
123
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
124
+
125
+ $this->processMessages();
126
+
127
+ // If there are delays but no transfers, then sleep for a bit.
128
+ if (!$this->active && $this->delays) {
129
+ usleep(500);
130
+ }
131
+
132
+ } while ($this->active || $this->handles);
133
+ }
134
+
135
+ private function addRequest(array &$entry)
136
+ {
137
+ $id = (int) $entry['handle'];
138
+ $this->handles[$id] = $entry;
139
+
140
+ // If the request is a delay, then add the reques to the curl multi
141
+ // pool only after the specified delay.
142
+ if (isset($entry['request']['client']['delay'])) {
143
+ $this->delays[$id] = microtime(true) + ($entry['request']['client']['delay'] / 1000);
144
+ } elseif (empty($entry['request']['future'])) {
145
+ curl_multi_add_handle($this->mh, $entry['handle']);
146
+ } else {
147
+ curl_multi_add_handle($this->mh, $entry['handle']);
148
+ // "lazy" futures are only sent once the pool has many requests.
149
+ if ($entry['request']['future'] !== 'lazy') {
150
+ do {
151
+ $mrc = curl_multi_exec($this->mh, $this->active);
152
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
153
+ $this->processMessages();
154
+ }
155
+ }
156
+ }
157
+
158
+ private function removeProcessed($id)
159
+ {
160
+ if (isset($this->handles[$id])) {
161
+ curl_multi_remove_handle(
162
+ $this->mh,
163
+ $this->handles[$id]['handle']
164
+ );
165
+ curl_close($this->handles[$id]['handle']);
166
+ unset($this->handles[$id], $this->delays[$id]);
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Cancels a handle from sending and removes references to it.
172
+ *
173
+ * @param int $id Handle ID to cancel and remove.
174
+ *
175
+ * @return bool True on success, false on failure.
176
+ */
177
+ private function cancel($id)
178
+ {
179
+ // Cannot cancel if it has been processed.
180
+ if (!isset($this->handles[$id])) {
181
+ return false;
182
+ }
183
+
184
+ $handle = $this->handles[$id]['handle'];
185
+ unset($this->delays[$id], $this->handles[$id]);
186
+ curl_multi_remove_handle($this->mh, $handle);
187
+ curl_close($handle);
188
+
189
+ return true;
190
+ }
191
+
192
+ private function addDelays()
193
+ {
194
+ $currentTime = microtime(true);
195
+
196
+ foreach ($this->delays as $id => $delay) {
197
+ if ($currentTime >= $delay) {
198
+ unset($this->delays[$id]);
199
+ curl_multi_add_handle(
200
+ $this->mh,
201
+ $this->handles[$id]['handle']
202
+ );
203
+ }
204
+ }
205
+ }
206
+
207
+ private function processMessages()
208
+ {
209
+ while ($done = curl_multi_info_read($this->mh)) {
210
+ $id = (int) $done['handle'];
211
+
212
+ if (!isset($this->handles[$id])) {
213
+ // Probably was cancelled.
214
+ continue;
215
+ }
216
+
217
+ $entry = $this->handles[$id];
218
+ $entry['response']['transfer_stats'] = curl_getinfo($done['handle']);
219
+
220
+ if ($done['result'] !== CURLM_OK) {
221
+ $entry['response']['curl']['errno'] = $done['result'];
222
+ if (function_exists('curl_strerror')) {
223
+ $entry['response']['curl']['error'] = curl_strerror($done['result']);
224
+ }
225
+ }
226
+
227
+ $result = CurlFactory::createResponse(
228
+ $this,
229
+ $entry['request'],
230
+ $entry['response'],
231
+ $entry['headers'],
232
+ $entry['body']
233
+ );
234
+
235
+ $this->removeProcessed($id);
236
+ $entry['deferred']->resolve($result);
237
+ }
238
+ }
239
+ }
backend/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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
20
+ public function __construct(array $options = [])
21
+ {
22
+ $this->options = $options;
23
+ }
24
+
25
+ public function __invoke(array $request)
26
+ {
27
+ $url = Core::url($request);
28
+ Core::doSleep($request);
29
+
30
+ try {
31
+ // Does not support the expect header.
32
+ $request = Core::removeHeader($request, 'Expect');
33
+ $stream = $this->createStream($url, $request, $headers);
34
+ return $this->createResponse($request, $url, $headers, $stream);
35
+ } catch (RingException $e) {
36
+ return $this->createErrorResponse($url, $e);
37
+ }
38
+ }
39
+
40
+ private function createResponse(array $request, $url, array $hdrs, $stream)
41
+ {
42
+ $parts = explode(' ', array_shift($hdrs), 3);
43
+ $response = [
44
+ 'status' => $parts[1],
45
+ 'reason' => isset($parts[2]) ? $parts[2] : null,
46
+ 'headers' => Core::headersFromLines($hdrs),
47
+ 'effective_url' => $url,
48
+ ];
49
+
50
+ $stream = $this->checkDecode($request, $response, $stream);
51
+
52
+ // If not streaming, then drain the response into a stream.
53
+ if (empty($request['client']['stream'])) {
54
+ $dest = isset($request['client']['save_to'])
55
+ ? $request['client']['save_to']
56
+ : fopen('php://temp', 'r+');
57
+ $stream = $this->drain($stream, $dest);
58
+ }
59
+
60
+ $response['body'] = $stream;
61
+
62
+ return new CompletedFutureArray($response);
63
+ }
64
+
65
+ private function checkDecode(array $request, array $response, $stream)
66
+ {
67
+ // Automatically decode responses when instructed.
68
+ if (!empty($request['client']['decode_content'])) {
69
+ switch (Core::firstHeader($response, 'Content-Encoding', true)) {
70
+ case 'gzip':
71
+ case 'deflate':
72
+ $stream = new InflateStream(Stream::factory($stream));
73
+ break;
74
+ }
75
+ }
76
+
77
+ return $stream;
78
+ }
79
+
80
+ /**
81
+ * Drains the stream into the "save_to" client option.
82
+ *
83
+ * @param resource $stream
84
+ * @param string|resource|StreamInterface $dest
85
+ *
86
+ * @return Stream
87
+ * @throws \RuntimeException when the save_to option is invalid.
88
+ */
89
+ private function drain($stream, $dest)
90
+ {
91
+ if (is_resource($stream)) {
92
+ if (!is_resource($dest)) {
93
+ $stream = Stream::factory($stream);
94
+ } else {
95
+ stream_copy_to_stream($stream, $dest);
96
+ fclose($stream);
97
+ rewind($dest);
98
+ return $dest;
99
+ }
100
+ }
101
+
102
+ // Stream the response into the destination stream
103
+ $dest = is_string($dest)
104
+ ? new Stream(Utils::open($dest, 'r+'))
105
+ : Stream::factory($dest);
106
+
107
+ Utils::copyToStream($stream, $dest);
108
+ $dest->seek(0);
109
+ $stream->close();
110
+
111
+ return $dest;
112
+ }
113
+
114
+ /**
115
+ * Creates an error response for the given stream.
116
+ *
117
+ * @param string $url
118
+ * @param RingException $e
119
+ *
120
+ * @return array
121
+ */
122
+ private function createErrorResponse($url, RingException $e)
123
+ {
124
+ // Determine if the error was a networking error.
125
+ $message = $e->getMessage();
126
+
127
+ // This list can probably get more comprehensive.
128
+ if (strpos($message, 'getaddrinfo') // DNS lookup failed
129
+ || strpos($message, 'Connection refused')
130
+ ) {
131
+ $e = new ConnectException($e->getMessage(), 0, $e);
132
+ }
133
+
134
+ return [
135
+ 'status' => null,
136
+ 'body' => null,
137
+ 'headers' => [],
138
+ 'effective_url' => $url,
139
+ 'error' => $e
140
+ ];
141
+ }
142
+
143
+ /**
144
+ * Create a resource and check to ensure it was created successfully
145
+ *
146
+ * @param callable $callback Callable that returns stream resource
147
+ *
148
+ * @return resource
149
+ * @throws \RuntimeException on error
150
+ */
151
+ private function createResource(callable $callback)
152
+ {
153
+ // Turn off error reporting while we try to initiate the request
154
+ $level = error_reporting(0);
155
+ $resource = call_user_func($callback);
156
+ error_reporting($level);
157
+
158
+ // If the resource could not be created, then grab the last error and
159
+ // throw an exception.
160
+ if (!is_resource($resource)) {
161
+ $message = 'Error creating resource: ';
162
+ foreach ((array) error_get_last() as $key => $value) {
163
+ $message .= "[{$key}] {$value} ";
164
+ }
165
+ throw new RingException(trim($message));
166
+ }
167
+
168
+ return $resource;
169
+ }
170
+
171
+ private function createStream(
172
+ $url,
173
+ array $request,
174
+ &$http_response_header
175
+ ) {
176
+ static $methods;
177
+ if (!$methods) {
178
+ $methods = array_flip(get_class_methods(__CLASS__));
179
+ }
180
+
181
+ // HTTP/1.1 streams using the PHP stream wrapper require a
182
+ // Connection: close header
183
+ if ((!isset($request['version']) || $request['version'] == '1.1')
184
+ && !Core::hasHeader($request, 'Connection')
185
+ ) {
186
+ $request['headers']['Connection'] = ['close'];
187
+ }
188
+
189
+ // Ensure SSL is verified by default
190
+ if (!isset($request['client']['verify'])) {
191
+ $request['client']['verify'] = true;
192
+ }
193
+
194
+ $params = [];
195
+ $options = $this->getDefaultOptions($request);
196
+
197
+ if (isset($request['client'])) {
198
+ foreach ($request['client'] as $key => $value) {
199
+ $method = "add_{$key}";
200
+ if (isset($methods[$method])) {
201
+ $this->{$method}($request, $options, $value, $params);
202
+ }
203
+ }
204
+ }
205
+
206
+ return $this->createStreamResource(
207
+ $url,
208
+ $request,
209
+ $options,
210
+ $this->createContext($request, $options, $params),
211
+ $http_response_header
212
+ );
213
+ }
214
+
215
+ private function getDefaultOptions(array $request)
216
+ {
217
+ $headers = "";
218
+ foreach ($request['headers'] as $name => $value) {
219
+ foreach ((array) $value as $val) {
220
+ $headers .= "$name: $val\r\n";
221
+ }
222
+ }
223
+
224
+ $context = [
225
+ 'http' => [
226
+ 'method' => $request['http_method'],
227
+ 'header' => $headers,
228
+ 'protocol_version' => isset($request['version']) ? $request['version'] : 1.1,
229
+ 'ignore_errors' => true,
230
+ 'follow_location' => 0,
231
+ ],
232
+ ];
233
+
234
+ $body = Core::body($request);
235
+ if (isset($body)) {
236
+ $context['http']['content'] = $body;
237
+ // Prevent the HTTP handler from adding a Content-Type header.
238
+ if (!Core::hasHeader($request, 'Content-Type')) {
239
+ $context['http']['header'] .= "Content-Type:\r\n";
240
+ }
241
+ }
242
+
243
+ $context['http']['header'] = rtrim($context['http']['header']);
244
+
245
+ return $context;
246
+ }
247
+
248
+ private function add_proxy(array $request, &$options, $value, &$params)
249
+ {
250
+ if (!is_array($value)) {
251
+ $options['http']['proxy'] = $value;
252
+ } else {
253
+ $scheme = isset($request['scheme']) ? $request['scheme'] : 'http';
254
+ if (isset($value[$scheme])) {
255
+ $options['http']['proxy'] = $value[$scheme];
256
+ }
257
+ }
258
+ }
259
+
260
+ private function add_timeout(array $request, &$options, $value, &$params)
261
+ {
262
+ $options['http']['timeout'] = $value;
263
+ }
264
+
265
+ private function add_verify(array $request, &$options, $value, &$params)
266
+ {
267
+ if ($value === true) {
268
+ // PHP 5.6 or greater will find the system cert by default. When
269
+ // < 5.6, use the Guzzle bundled cacert.
270
+ if (PHP_VERSION_ID < 50600) {
271
+ $options['ssl']['cafile'] = ClientUtils::getDefaultCaBundle();
272
+ }
273
+ } elseif (is_string($value)) {
274
+ $options['ssl']['cafile'] = $value;
275
+ if (!file_exists($value)) {
276
+ throw new RingException("SSL CA bundle not found: $value");
277
+ }
278
+ } elseif ($value === false) {
279
+ $options['ssl']['verify_peer'] = false;
280
+ return;
281
+ } else {
282
+ throw new RingException('Invalid verify request option');
283
+ }
284
+
285
+ $options['ssl']['verify_peer'] = true;
286
+ $options['ssl']['allow_self_signed'] = true;
287
+ }
288
+
289
+ private function add_cert(array $request, &$options, $value, &$params)
290
+ {
291
+ if (is_array($value)) {
292
+ $options['ssl']['passphrase'] = $value[1];
293
+ $value = $value[0];
294
+ }
295
+
296
+ if (!file_exists($value)) {
297
+ throw new RingException("SSL certificate not found: {$value}");
298
+ }
299
+
300
+ $options['ssl']['local_cert'] = $value;
301
+ }
302
+
303
+ private function add_progress(array $request, &$options, $value, &$params)
304
+ {
305
+ $fn = function ($code, $_, $_, $_, $transferred, $total) use ($value) {
306
+ if ($code == STREAM_NOTIFY_PROGRESS) {
307
+ $value($total, $transferred, null, null);
308
+ }
309
+ };
310
+
311
+ // Wrap the existing function if needed.
312
+ $params['notification'] = isset($params['notification'])
313
+ ? Core::callArray([$params['notification'], $fn])
314
+ : $fn;
315
+ }
316
+
317
+ private function add_debug(array $request, &$options, $value, &$params)
318
+ {
319
+ static $map = [
320
+ STREAM_NOTIFY_CONNECT => 'CONNECT',
321
+ STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
322
+ STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
323
+ STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
324
+ STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
325
+ STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
326
+ STREAM_NOTIFY_PROGRESS => 'PROGRESS',
327
+ STREAM_NOTIFY_FAILURE => 'FAILURE',
328
+ STREAM_NOTIFY_COMPLETED => 'COMPLETED',
329
+ STREAM_NOTIFY_RESOLVE => 'RESOLVE',
330
+ ];
331
+
332
+ static $args = ['severity', 'message', 'message_code',
333
+ 'bytes_transferred', 'bytes_max'];
334
+
335
+ $value = Core::getDebugResource($value);
336
+ $ident = $request['http_method'] . ' ' . Core::url($request);
337
+ $fn = function () use ($ident, $value, $map, $args) {
338
+ $passed = func_get_args();
339
+ $code = array_shift($passed);
340
+ fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
341
+ foreach (array_filter($passed) as $i => $v) {
342
+ fwrite($value, $args[$i] . ': "' . $v . '" ');
343
+ }
344
+ fwrite($value, "\n");
345
+ };
346
+
347
+ // Wrap the existing function if needed.
348
+ $params['notification'] = isset($params['notification'])
349
+ ? Core::callArray([$params['notification'], $fn])
350
+ : $fn;
351
+ }
352
+
353
+ private function applyCustomOptions(array $request, array &$options)
354
+ {
355
+ if (!isset($request['client']['stream_context'])) {
356
+ return;
357
+ }
358
+
359
+ if (!is_array($request['client']['stream_context'])) {
360
+ throw new RingException('stream_context must be an array');
361
+ }
362
+
363
+ $options = array_replace_recursive(
364
+ $options,
365
+ $request['client']['stream_context']
366
+ );
367
+ }
368
+
369
+ private function createContext(array $request, array $options, array $params)
370
+ {
371
+ $this->applyCustomOptions($request, $options);
372
+ return $this->createResource(
373
+ function () use ($request, $options, $params) {
374
+ return stream_context_create($options, $params);
375
+ },
376
+ $request,
377
+ $options
378
+ );
379
+ }
380
+
381
+ private function createStreamResource(
382
+ $url,
383
+ array $request,
384
+ array $options,
385
+ $context,
386
+ &$http_response_header
387
+ ) {
388
+ return $this->createResource(
389
+ function () use ($url, &$http_response_header, $context) {
390
+ if (false === strpos($url, 'http')) {
391
+ trigger_error("URL is invalid: {$url}", E_USER_WARNING);
392
+ return null;
393
+ }
394
+ return fopen($url, 'r', null, $context);
395
+ },
396
+ $request,
397
+ $options
398
+ );
399
+ }
400
+ }
backend/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
+ }
backend/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 {}
backend/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 {}
backend/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 {}
backend/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 {};
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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 {};
backend/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 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
+
41
+ /**
42
+ * Create and return a promise that invokes the given methods when the
43
+ * future has a value, exception, or progress events.
44
+ *
45
+ * @param callable $onFulfilled Called when the promise is resolved.
46
+ * @param callable $onRejected Called when the promise is rejected.
47
+ * @param callable $onProgress Called on progress events.
48
+ *
49
+ * @return PromiseInterface
50
+ */
51
+ public function then(
52
+ callable $onFulfilled = null,
53
+ callable $onRejected = null,
54
+ callable $onProgress = null
55
+ );
56
+ }
backend/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
+ }
backend/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
+ }
backend/vendor/guzzlehttp/streams/.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ .idea
2
+ .DS_STORE
3
+ coverage
4
+ phpunit.xml
5
+ composer.lock
6
+ vendor/
backend/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
backend/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
backend/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.
backend/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/*
backend/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``.
backend/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
+ }
backend/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>
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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 {}
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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 {}
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/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
+ }
backend/vendor/react/promise/.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ composer.lock
2
+ composer.phar
3
+ phpunit.xml
4
+ vendor/
backend/vendor/react/promise/.travis.yml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
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 --dev --prefer-source
12
+
13
+ script: phpunit --coverage-text
backend/vendor/react/promise/CHANGELOG.md ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CHANGELOG
2
+ =========
3
+
4
+ * 2.1.0 (2014-10-15)
5
+
6
+ * Introduce new CancellablePromiseInterface implemented by all promises
7
+ * Add new .cancel() method (part of the CancellablePromiseInterface)
8
+
9
+ * 2.0.0 (2013-12-10)
10
+
11
+ New major release. The goal was to streamline the API and to make it more
12
+ compliant with other promise libraries and especially with the new upcoming
13
+ [ES6 promises specification](https://github.com/domenic/promises-unwrapping/).
14
+
15
+ * Add standalone Promise class.
16
+ * Add new React\Promise\race() function.
17
+ * BC break: Bump minimum PHP version to PHP 5.4.
18
+ * BC break: Remove ResolverInterface and PromiseInterface from Deferred.
19
+ * BC break: Change signature of PromiseInterface.
20
+ * BC break: Remove When and Util classes and move static methods to functions.
21
+ * BC break: FulfilledPromise and RejectedPromise now throw an exception when
22
+ initialized with a promise instead of a value/reason.
23
+ * BC break: React\Promise\Deferred::resolve() and React\Promise\Deferred::reject()
24
+ no longer return a promise.
25
+
26
+ * 1.0.4 (2013-04-03)
27
+
28
+ * Trigger PHP errors when invalid callback is passed.
29
+ * Fully resolve rejection value before calling rejection handler.
30
+ * Add When::lazy() to create lazy promises which will be initialized once a
31
+ consumer calls the then() method.
32
+
33
+ * 1.0.3 (2012-11-17)
34
+
35
+ * Add `PromisorInterface` for objects that have a `promise()` method.
36
+
37
+ * 1.0.2 (2012-11-14)
38
+
39
+ * Fix bug in When::any() not correctly unwrapping to a single result value
40
+ * $promiseOrValue argument of When::resolve() and When::reject() is now optional
41
+
42
+ * 1.0.1 (2012-11-13)
43
+
44
+ * Prevent deep recursion which was reaching `xdebug.max_nesting_level` default of 100
45
+
46
+ * 1.0.0 (2012-11-07)
47
+
48
+ * First tagged release
backend/vendor/react/promise/LICENSE ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2012 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.
backend/vendor/react/promise/README.md ADDED
@@ -0,0 +1,617 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ React/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://secure.travis-ci.org/reactphp/promise.png?branch=master)](http://travis-ci.org/reactphp/promise)
8
+
9
+ Table of Contents
10
+ -----------------
11
+
12
+ 1. [Introduction](#introduction)
13
+ 2. [Concepts](#concepts)
14
+ * [Deferred](#deferred)
15
+ * [Promise](#promise)
16
+ 3. [API](#api)
17
+ * [Deferred](#deferred-1)
18
+ * [Deferred::promise()](#deferredpromise)
19
+ * [Deferred::resolve()](#deferredresolve)
20
+ * [Deferred::reject()](#deferredreject)
21
+ * [Deferred::progress()](#deferredprogress)
22
+ * [PromiseInterface](#promiseinterface)
23
+ * [PromiseInterface::then()](#promiseinterfacethen)
24
+ * [CancellablePromiseInterface](#cancellablepromiseinterface)
25
+ * [CancellablePromiseInterface::cancel()](#cancellablepromiseinterfacecancel)
26
+ * [Promise](#promise-1)
27
+ * [FulfilledPromise](#fulfilledpromise)
28
+ * [RejectedPromise](#rejectedpromise)
29
+ * [LazyPromise](#lazypromise)
30
+ * [Functions](#functions)
31
+ * [resolve()](#resolve)
32
+ * [reject()](#reject)
33
+ * [all()](#all)
34
+ * [race()](#race)
35
+ * [any()](#any)
36
+ * [some()](#some)
37
+ * [map()](#map)
38
+ * [reduce()](#reduce)
39
+ * [PromisorInterface](#promisorinterface)
40
+ 4. [Examples](#examples)
41
+ * [How to use Deferred](#how-to-use-deferred)
42
+ * [How promise forwarding works](#how-promise-forwarding-works)
43
+ * [Resolution forwarding](#resolution-forwarding)
44
+ * [Rejection forwarding](#rejection-forwarding)
45
+ * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding)
46
+ * [Progress event forwarding](#progress-event-forwarding)
47
+ 5. [Credits](#credits)
48
+ 6. [License](#license)
49
+
50
+ Introduction
51
+ ------------
52
+
53
+ React/Promise is a library implementing
54
+ [CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP.
55
+
56
+ It also provides several other useful promise-related concepts, such as joining
57
+ multiple promises and mapping and reducing collections of promises.
58
+
59
+ If you've never heard about promises before,
60
+ [read this first](https://gist.github.com/3889970).
61
+
62
+ Concepts
63
+ --------
64
+
65
+ ### Deferred
66
+
67
+ A **Deferred** represents a computation or unit of work that may not have
68
+ completed yet. Typically (but not always), that computation will be something
69
+ that executes asynchronously and completes at some point in the future.
70
+
71
+ ### Promise
72
+
73
+ While a deferred represents the computation itself, a **Promise** represents
74
+ the result of that computation. Thus, each deferred has a promise that acts as
75
+ a placeholder for its actual result.
76
+
77
+ API
78
+ ---
79
+
80
+ ### Deferred
81
+
82
+ A deferred represents an operation whose resolution is pending. It has separate
83
+ promise and resolver parts.
84
+
85
+ ``` php
86
+ $deferred = new React\Promise\Deferred();
87
+
88
+ $promise = $deferred->promise();
89
+
90
+ $deferred->resolve(mixed $value = null);
91
+ $deferred->reject(mixed $reason = null);
92
+ $deferred->progress(mixed $update = null);
93
+ ```
94
+
95
+ The `promise` method returns the promise of the deferred.
96
+
97
+ The `resolve` and `reject` methods control the state of the deferred.
98
+
99
+ The `progress` method is for progress notification.
100
+
101
+ The constructor of the `Deferred` accepts an optional `$canceller` argument.
102
+ See [Promise](#promise-1) for more information.
103
+
104
+ #### Deferred::promise()
105
+
106
+ ``` php
107
+ $promise = $deferred->promise();
108
+ ```
109
+
110
+ Returns the promise of the deferred, which you can hand out to others while
111
+ keeping the authority to modify its state to yourself.
112
+
113
+ #### Deferred::resolve()
114
+
115
+ ``` php
116
+ $deferred->resolve(mixed $value = null);
117
+ ```
118
+
119
+ Resolves the promise returned by `promise()`. All consumers are notified by
120
+ having `$onFulfilled` (which they registered via `$promise->then()`) called with
121
+ `$value`.
122
+
123
+ If `$value` itself is a promise, the promise will transition to the state of
124
+ this promise once it is resolved.
125
+
126
+ #### Deferred::reject()
127
+
128
+ ``` php
129
+ $deferred->reject(mixed $reason = null);
130
+ ```
131
+
132
+ Rejects the promise returned by `promise()`, signalling that the deferred's
133
+ computation failed.
134
+ All consumers are notified by having `$onRejected` (which they registered via
135
+ `$promise->then()`) called with `$reason`.
136
+
137
+ If `$reason` itself is a promise, the promise will be rejected with the outcome
138
+ of this promise regardless whether it fulfills or rejects.
139
+
140
+ #### Deferred::progress()
141
+
142
+ ``` php
143
+ $deferred->progress(mixed $update = null);
144
+ ```
145
+
146
+ Triggers progress notifications, to indicate to consumers that the computation
147
+ is making progress toward its result.
148
+
149
+ All consumers are notified by having `$onProgress` (which they registered via
150
+ `$promise->then()`) called with `$update`.
151
+
152
+ ### PromiseInterface
153
+
154
+ The promise interface provides the common interface for all promise
155
+ implementations.
156
+
157
+ A promise represents an eventual outcome, which is either fulfillment (success)
158
+ and an associated value, or rejection (failure) and an associated reason.
159
+
160
+ Once in the fulfilled or rejected state, a promise becomes immutable.
161
+ Neither its state nor its result (or error) can be modified.
162
+
163
+ #### PromiseInterface::then()
164
+
165
+ ``` php
166
+ $newPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
167
+ ```
168
+
169
+ The `then()` method registers new fulfilled, rejection and progress handlers
170
+ with this promise (all parameters are optional):
171
+
172
+ * `$onFulfilled` will be invoked once the promise is fulfilled and passed
173
+ the result as the first argument.
174
+ * `$onRejected` will be invoked once the promise is rejected and passed the
175
+ reason as the first argument.
176
+ * `$onProgress` will be invoked whenever the producer of the promise
177
+ triggers progress notifications and passed a single argument (whatever it
178
+ wants) to indicate progress.
179
+
180
+ It returns a new promise that will fulfill with the return value of either
181
+ `$onFulfilled` or `$onRejected`, whichever is called, or will reject with
182
+ the thrown exception if either throws.
183
+
184
+ A promise makes the following guarantees about handlers registered in
185
+ the same call to `then()`:
186
+
187
+ 1. Only one of `$onFulfilled` or `$onRejected` will be called,
188
+ never both.
189
+ 2. `$onFulfilled` and `$onRejected` will never be called more
190
+ than once.
191
+ 3. `$onProgress` may be called multiple times.
192
+
193
+ #### Implementations
194
+
195
+ * [Promise](#promise-1)
196
+ * [FulfilledPromise](#fulfilledpromise)
197
+ * [RejectedPromise](#rejectedpromise)
198
+ * [LazyPromise](#lazypromise)
199
+
200
+ #### See also
201
+
202
+ * [resolve()](#resolve) - Creating a resolved promise
203
+ * [reject()](#reject) - Creating a rejected promise
204
+
205
+ ### CancellablePromiseInterface
206
+
207
+ A cancellable promise provides a mechanism for consumers to notify the creator
208
+ of the promise that they are not longer interested in the result of an
209
+ operation.
210
+
211
+ #### CancellablePromiseInterface::cancel()
212
+
213
+ ``` php
214
+ $promise->cancel();
215
+ ```
216
+
217
+ The `cancel()` method notifies the creator of the promise that there is no
218
+ further interest in the results of the operation.
219
+
220
+ Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
221
+ a promise has no effect.
222
+
223
+ #### Implementations
224
+
225
+ * [Promise](#promise-1)
226
+ * [FulfilledPromise](#fulfilledpromise)
227
+ * [RejectedPromise](#rejectedpromise)
228
+ * [LazyPromise](#lazypromise)
229
+
230
+ ### Promise
231
+
232
+ Creates a promise whose state is controlled by the functions passed to
233
+ `$resolver`.
234
+
235
+ ``` php
236
+ $resolver = function (callable $resolve, callable $reject, callable $progress) {
237
+ // Do some work, possibly asynchronously, and then
238
+ // resolve or reject. You can notify of progress events
239
+ // along the way if you want/need.
240
+
241
+ $resolve($awesomeResult);
242
+ // or $resolve($anotherPromise);
243
+ // or $reject($nastyError);
244
+ // or $progress($progressNotification);
245
+ };
246
+
247
+ $canceller = function (callable $resolve, callable $reject, callable $progress) {
248
+ // Cancel/abort any running operations like network connections, streams etc.
249
+
250
+ $reject(new \Exception('Promise cancelled'));
251
+ };
252
+
253
+ $promise = new React\Promise\Promise($resolver, $canceller);
254
+ ```
255
+
256
+ The promise constructor receives a resolver function and an optional canceller
257
+ function which both will be called with 3 arguments:
258
+
259
+ * `$resolve($value)` - Primary function that seals the fate of the
260
+ returned promise. Accepts either a non-promise value, or another promise.
261
+ When called with a non-promise value, fulfills promise with that value.
262
+ When called with another promise, e.g. `$resolve($otherPromise)`, promise's
263
+ fate will be equivalent to that of `$otherPromise`.
264
+ * `$reject($reason)` - Function that rejects the promise.
265
+ * `$progress($update)` - Function that issues progress events for the promise.
266
+
267
+ If the resolver or canceller throw an exception, the promise will be rejected
268
+ with that thrown exception as the rejection reason.
269
+
270
+ The resolver function will be called immediately, the canceller function only
271
+ once all consumers called the `cancel()` method of the promise.
272
+
273
+ ### FulfilledPromise
274
+
275
+ Creates a already fulfilled promise.
276
+
277
+ ```php
278
+ $promise = React\Promise\FulfilledPromise($value);
279
+ ```
280
+
281
+ Note, that `$value` **cannot** be a promise. It's recommended to use
282
+ [resolve()](#resolve) for creating resolved promises.
283
+
284
+ ### RejectedPromise
285
+
286
+ Creates a already rejected promise.
287
+
288
+ ```php
289
+ $promise = React\Promise\RejectedPromise($reason);
290
+ ```
291
+
292
+ Note, that `$reason` **cannot** be a promise. It's recommended to use
293
+ [reject()](#reject) for creating rejected promises.
294
+
295
+ ### LazyPromise
296
+
297
+ Creates a promise which will be lazily initialized by `$factory` once a consumer
298
+ calls the `then()` method.
299
+
300
+ ```php
301
+ $factory = function () {
302
+ $deferred = new React\Promise\Deferred();
303
+
304
+ // Do some heavy stuff here and resolve the deferred once completed
305
+
306
+ return $deferred->promise();
307
+ };
308
+
309
+ $promise = React\Promise\LazyPromise($factory);
310
+
311
+ // $factory will only be executed once we call then()
312
+ $promise->then(function ($value) {
313
+ });
314
+ ```
315
+
316
+ ### Functions
317
+
318
+ Useful functions for creating, joining, mapping and reducing collections of
319
+ promises.
320
+
321
+ #### resolve()
322
+
323
+ ``` php
324
+ $promise = React\Promise\resolve(mixed $promiseOrValue);
325
+ ```
326
+
327
+ Creates a resolved promise for the supplied `$promiseOrValue`.
328
+
329
+ If `$promiseOrValue` is a value, it will be the resolution value of the
330
+ returned promise.
331
+
332
+ If `$promiseOrValue` is a promise, it will simply be returned.
333
+
334
+ #### reject()
335
+
336
+ ``` php
337
+ $promise = React\Promise\reject(mixed $promiseOrValue);
338
+ ```
339
+
340
+ Creates a rejected promise for the supplied `$promiseOrValue`.
341
+
342
+ If `$promiseOrValue` is a value, it will be the rejection value of the
343
+ returned promise.
344
+
345
+ If `$promiseOrValue` is a promise, its completion value will be the rejected
346
+ value of the returned promise.
347
+
348
+ This can be useful in situations where you need to reject a promise without
349
+ throwing an exception. For example, it allows you to propagate a rejection with
350
+ the value of another promise.
351
+
352
+ #### all()
353
+
354
+ ``` php
355
+ $promise = React\Promise\all(array|React\Promise\PromiseInterface $promisesOrValues);
356
+ ```
357
+
358
+ Returns a promise that will resolve only once all the items in
359
+ `$promisesOrValues` have resolved. The resolution value of the returned promise
360
+ will be an array containing the resolution values of each of the items in
361
+ `$promisesOrValues`.
362
+
363
+ #### race()
364
+
365
+ ``` php
366
+ $promise = React\Promise\race(array|React\Promise\PromiseInterface $promisesOrValues);
367
+ ```
368
+
369
+ Initiates a competitive race that allows one winner. Returns a promise which is
370
+ resolved in the same way the first settled promise resolves.
371
+
372
+ #### any()
373
+
374
+ ``` php
375
+ $promise = React\Promise\any(array|React\Promise\PromiseInterface $promisesOrValues);
376
+ ```
377
+
378
+ Returns a promise that will resolve when any one of the items in
379
+ `$promisesOrValues` resolves. The resolution value of the returned promise
380
+ will be the resolution value of the triggering item.
381
+
382
+ The returned promise will only reject if *all* items in `$promisesOrValues` are
383
+ rejected. The rejection value will be an array of all rejection reasons.
384
+
385
+ #### some()
386
+
387
+ ``` php
388
+ $promise = React\Promise\some(array|React\Promise\PromiseInterface $promisesOrValues, integer $howMany);
389
+ ```
390
+
391
+ Returns a promise that will resolve when `$howMany` of the supplied items in
392
+ `$promisesOrValues` resolve. The resolution value of the returned promise
393
+ will be an array of length `$howMany` containing the resolution values of the
394
+ triggering items.
395
+
396
+ The returned promise will reject if it becomes impossible for `$howMany` items
397
+ to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
398
+ reject). The rejection value will be an array of
399
+ `(count($promisesOrValues) - $howMany) + 1` rejection reasons.
400
+
401
+ #### map()
402
+
403
+ ``` php
404
+ $promise = React\Promise\map(array|React\Promise\PromiseInterface $promisesOrValues, callable $mapFunc);
405
+ ```
406
+
407
+ Traditional map function, similar to `array_map()`, but allows input to contain
408
+ promises and/or values, and `$mapFunc` may return either a value or a promise.
409
+
410
+ The map function receives each item as argument, where item is a fully resolved
411
+ value of a promise or value in `$promisesOrValues`.
412
+
413
+ #### reduce()
414
+
415
+ ``` php
416
+ $promise = React\Promise\reduce(array|React\Promise\PromiseInterface $promisesOrValues, callable $reduceFunc , $initialValue = null);
417
+ ```
418
+
419
+ Traditional reduce function, similar to `array_reduce()`, but input may contain
420
+ promises and/or values, and `$reduceFunc` may return either a value or a
421
+ promise, *and* `$initialValue` may be a promise or a value for the starting
422
+ value.
423
+
424
+ ### PromisorInterface
425
+
426
+ The `React\Promise\PromisorInterface` provides a common interface for objects
427
+ that provide a promise. `React\Promise\Deferred` implements it, but since it
428
+ is part of the public API anyone can implement it.
429
+
430
+ Examples
431
+ --------
432
+
433
+ ### How to use Deferred
434
+
435
+ ``` php
436
+ function getAwesomeResultPromise()
437
+ {
438
+ $deferred = new React\Promise\Deferred();
439
+
440
+ // Execute a Node.js-style function using the callback pattern
441
+ computeAwesomeResultAsynchronously(function ($error, $result) use ($deferred) {
442
+ if ($error) {
443
+ $deferred->reject($error);
444
+ } else {
445
+ $deferred->resolve($result);
446
+ }
447
+ });
448
+
449
+ // Return the promise
450
+ return $deferred->promise();
451
+ }
452
+
453
+ getAwesomeResultPromise()
454
+ ->then(
455
+ function ($value) {
456
+ // Deferred resolved, do something with $value
457
+ },
458
+ function ($reason) {
459
+ // Deferred rejected, do something with $reason
460
+ },
461
+ function ($update) {
462
+ // Progress notification triggered, do something with $update
463
+ }
464
+ );
465
+ ```
466
+
467
+ ### How promise forwarding works
468
+
469
+ A few simple examples to show how the mechanics of Promises/A forwarding works.
470
+ These examples are contrived, of course, and in real usage, promise chains will
471
+ typically be spread across several function calls, or even several levels of
472
+ your application architecture.
473
+
474
+ #### Resolution forwarding
475
+
476
+ Resolved promises forward resolution values to the next promise.
477
+ The first promise, `$deferred->promise()`, will resolve with the value passed
478
+ to `$deferred->resolve()` below.
479
+
480
+ Each call to `then()` returns a new promise that will resolve with the return
481
+ value of the previous handler. This creates a promise "pipeline".
482
+
483
+ ``` php
484
+ $deferred = new React\Promise\Deferred();
485
+
486
+ $deferred->promise()
487
+ ->then(function ($x) {
488
+ // $x will be the value passed to $deferred->resolve() below
489
+ // and returns a *new promise* for $x + 1
490
+ return $x + 1;
491
+ })
492
+ ->then(function ($x) {
493
+ // $x === 2
494
+ // This handler receives the return value of the
495
+ // previous handler.
496
+ return $x + 1;
497
+ })
498
+ ->then(function ($x) {
499
+ // $x === 3
500
+ // This handler receives the return value of the
501
+ // previous handler.
502
+ return $x + 1;
503
+ })
504
+ ->then(function ($x) {
505
+ // $x === 4
506
+ // This handler receives the return value of the
507
+ // previous handler.
508
+ echo 'Resolve ' . $x;
509
+ });
510
+
511
+ $deferred->resolve(1); // Prints "Resolve 4"
512
+ ```
513
+
514
+ #### Rejection forwarding
515
+
516
+ Rejected promises behave similarly, and also work similarly to try/catch:
517
+ When you catch an exception, you must rethrow for it to propagate.
518
+
519
+ Similarly, when you handle a rejected promise, to propagate the rejection,
520
+ "rethrow" it by either returning a rejected promise, or actually throwing
521
+ (since promise translates thrown exceptions into rejections)
522
+
523
+ ``` php
524
+ $deferred = new React\Promise\Deferred();
525
+
526
+ $deferred->promise()
527
+ ->then(function ($x) {
528
+ throw new \Exception($x + 1);
529
+ })
530
+ ->then(null, function (\Exception $x) {
531
+ // Propagate the rejection
532
+ throw $x;
533
+ })
534
+ ->then(null, function (\Exception $x) {
535
+ // Can also propagate by returning another rejection
536
+ return React\Promise\reject((integer) $x->getMessage() + 1);
537
+ })
538
+ ->then(null, function ($x) {
539
+ echo 'Reject ' . $x; // 3
540
+ });
541
+
542
+ $deferred->resolve(1); // Prints "Reject 3"
543
+ ```
544
+
545
+ #### Mixed resolution and rejection forwarding
546
+
547
+ Just like try/catch, you can choose to propagate or not. Mixing resolutions and
548
+ rejections will still forward handler results in a predictable way.
549
+
550
+ ``` php
551
+ $deferred = new React\Promise\Deferred();
552
+
553
+ $deferred->promise()
554
+ ->then(function ($x) {
555
+ return $x + 1;
556
+ })
557
+ ->then(function ($x) {
558
+ throw \Exception($x + 1);
559
+ })
560
+ ->then(null, function (\Exception $x) {
561
+ // Handle the rejection, and don't propagate.
562
+ // This is like catch without a rethrow
563
+ return (integer) $x->getMessage() + 1;
564
+ })
565
+ ->then(function ($x) {
566
+ echo 'Mixed ' . $x; // 4
567
+ });
568
+
569
+ $deferred->resolve(1); // Prints "Mixed 4"
570
+ ```
571
+
572
+ #### Progress event forwarding
573
+
574
+ In the same way as resolution and rejection handlers, your progress handler
575
+ **MUST** return a progress event to be propagated to the next link in the chain.
576
+ If you return nothing, `null` will be propagated.
577
+
578
+ Also in the same way as resolutions and rejections, if you don't register a
579
+ progress handler, the update will be propagated through.
580
+
581
+ If your progress handler throws an exception, the exception will be propagated
582
+ to the next link in the chain. The best thing to do is to ensure your progress
583
+ handlers do not throw exceptions.
584
+
585
+ This gives you the opportunity to transform progress events at each step in the
586
+ chain so that they are meaningful to the next step. It also allows you to choose
587
+ not to transform them, and simply let them propagate untransformed, by not
588
+ registering a progress handler.
589
+
590
+ ``` php
591
+ $deferred = new React\Promise\Deferred();
592
+
593
+ $deferred->promise()
594
+ ->then(null, null, function ($update) {
595
+ return $update + 1;
596
+ })
597
+ ->then(null, null, function ($update) {
598
+ echo 'Progress ' . $update; // 2
599
+ });
600
+
601
+ $deferred->progress(1); // Prints "Progress 2"
602
+ ```
603
+
604
+ Credits
605
+ -------
606
+
607
+ React/Promise is a port of [when.js](https://github.com/cujojs/when)
608
+ by [Brian Cavalier](https://github.com/briancavalier).
609
+
610
+ Also, large parts of the documentation have been ported from the when.js
611
+ [Wiki](https://github.com/cujojs/when/wiki) and the
612
+ [API docs](https://github.com/cujojs/when/blob/master/docs/api.md).
613
+
614
+ License
615
+ -------
616
+
617
+ React/Promise is released under the [MIT](https://github.com/reactphp/promise/blob/master/LICENSE) license.
backend/vendor/react/promise/composer.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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@googlemail.com"}
7
+ ],
8
+ "require": {
9
+ "php": ">=5.4.0"
10
+ },
11
+ "autoload": {
12
+ "psr-4": {
13
+ "React\\Promise\\": "src/"
14
+ },
15
+ "files": ["src/functions.php"]
16
+ },
17
+ "extra": {
18
+ "branch-alias": {
19
+ "dev-master": "2.0-dev"
20
+ }
21
+ }
22
+ }
backend/vendor/react/promise/phpunit.xml.dist ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <phpunit backupGlobals="false"
4
+ backupStaticAttributes="false"
5
+ colors="true"
6
+ convertErrorsToExceptions="true"
7
+ convertNoticesToExceptions="true"
8
+ convertWarningsToExceptions="true"
9
+ processIsolation="false"
10
+ stopOnFailure="false"
11
+ syntaxCheck="false"
12
+ bootstrap="tests/bootstrap.php"
13
+ >
14
+ <testsuites>
15
+ <testsuite name="Promise Test Suite">
16
+ <directory>./tests/</directory>
17
+ </testsuite>
18
+ </testsuites>
19
+
20
+ <filter>
21
+ <whitelist>
22
+ <directory>./src/</directory>
23
+ </whitelist>
24
+ </filter>
25
+ </phpunit>
backend/vendor/react/promise/src/CancellablePromiseInterface.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ interface CancellablePromiseInterface extends PromiseInterface
6
+ {
7
+ /**
8
+ * @return void
9
+ */
10
+ public function cancel();
11
+ }
backend/vendor/react/promise/src/Deferred.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 $progressCallback;
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, $progress) {
22
+ $this->resolveCallback = $resolve;
23
+ $this->rejectCallback = $reject;
24
+ $this->progressCallback = $progress;
25
+ }, $this->canceller);
26
+ }
27
+
28
+ return $this->promise;
29
+ }
30
+
31
+ public function resolve($value = null)
32
+ {
33
+ $this->promise();
34
+
35
+ call_user_func($this->resolveCallback, $value);
36
+ }
37
+
38
+ public function reject($reason = null)
39
+ {
40
+ $this->promise();
41
+
42
+ call_user_func($this->rejectCallback, $reason);
43
+ }
44
+
45
+ public function progress($update = null)
46
+ {
47
+ $this->promise();
48
+
49
+ call_user_func($this->progressCallback, $update);
50
+ }
51
+ }
backend/vendor/react/promise/src/FulfilledPromise.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class FulfilledPromise implements CancellablePromiseInterface
6
+ {
7
+ private $value;
8
+
9
+ public function __construct($value = null)
10
+ {
11
+ if ($value instanceof PromiseInterface) {
12
+ throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.');
13
+ }
14
+
15
+ $this->value = $value;
16
+ }
17
+
18
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
19
+ {
20
+ try {
21
+ $value = $this->value;
22
+
23
+ if (null !== $onFulfilled) {
24
+ $value = $onFulfilled($value);
25
+ }
26
+
27
+ return resolve($value);
28
+ } catch (\Exception $exception) {
29
+ return new RejectedPromise($exception);
30
+ }
31
+ }
32
+
33
+ public function cancel()
34
+ {
35
+ }
36
+ }
backend/vendor/react/promise/src/LazyPromise.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class LazyPromise implements CancellablePromiseInterface
6
+ {
7
+ private $factory;
8
+ private $promise;
9
+
10
+ public function __construct(callable $factory)
11
+ {
12
+ $this->factory = $factory;
13
+ }
14
+
15
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
16
+ {
17
+ return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
18
+ }
19
+
20
+ public function cancel()
21
+ {
22
+ return $this->promise()->cancel();
23
+ }
24
+
25
+ private function promise()
26
+ {
27
+ if (null === $this->promise) {
28
+ try {
29
+ $this->promise = resolve(call_user_func($this->factory));
30
+ } catch (\Exception $exception) {
31
+ $this->promise = new RejectedPromise($exception);
32
+ }
33
+ }
34
+
35
+ return $this->promise;
36
+ }
37
+ }
backend/vendor/react/promise/src/Promise.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class Promise implements 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
+ $this->call($resolver);
20
+ }
21
+
22
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
23
+ {
24
+ if (null !== $this->result) {
25
+ return $this->result->then($onFulfilled, $onRejected, $onProgress);
26
+ }
27
+
28
+ if (null === $this->canceller) {
29
+ return new static($this->resolver($onFulfilled, $onRejected, $onProgress));
30
+ }
31
+
32
+ $this->requiredCancelRequests++;
33
+
34
+ return new static($this->resolver($onFulfilled, $onRejected, $onProgress), function ($resolve, $reject, $progress) {
35
+ if (++$this->cancelRequests < $this->requiredCancelRequests) {
36
+ return;
37
+ }
38
+
39
+ $this->cancel();
40
+ });
41
+ }
42
+
43
+ public function cancel()
44
+ {
45
+ if (null === $this->canceller || null !== $this->result) {
46
+ return;
47
+ }
48
+
49
+ $this->call($this->canceller);
50
+ }
51
+
52
+ private function resolver(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
53
+ {
54
+ return function ($resolve, $reject, $progress) use ($onFulfilled, $onRejected, $onProgress) {
55
+ if ($onProgress) {
56
+ $progressHandler = function ($update) use ($progress, $onProgress) {
57
+ try {
58
+ $progress($onProgress($update));
59
+ } catch (\Exception $e) {
60
+ $progress($e);
61
+ }
62
+ };
63
+ } else {
64
+ $progressHandler = $progress;
65
+ }
66
+
67
+ $this->handlers[] = function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) {
68
+ $promise
69
+ ->then($onFulfilled, $onRejected)
70
+ ->then($resolve, $reject, $progressHandler);
71
+ };
72
+
73
+ $this->progressHandlers[] = $progressHandler;
74
+ };
75
+ }
76
+
77
+ private function resolve($value = null)
78
+ {
79
+ if (null !== $this->result) {
80
+ return;
81
+ }
82
+
83
+ $this->settle(resolve($value));
84
+ }
85
+
86
+ private function reject($reason = null)
87
+ {
88
+ if (null !== $this->result) {
89
+ return;
90
+ }
91
+
92
+ $this->settle(reject($reason));
93
+ }
94
+
95
+ private function progress($update = null)
96
+ {
97
+ if (null !== $this->result) {
98
+ return;
99
+ }
100
+
101
+ foreach ($this->progressHandlers as $handler) {
102
+ $handler($update);
103
+ }
104
+ }
105
+
106
+ private function settle(PromiseInterface $result)
107
+ {
108
+ foreach ($this->handlers as $handler) {
109
+ $handler($result);
110
+ }
111
+
112
+ $this->progressHandlers = $this->handlers = [];
113
+
114
+ $this->result = $result;
115
+ }
116
+
117
+ private function call(callable $callback)
118
+ {
119
+ try {
120
+ $callback(
121
+ function ($value = null) {
122
+ $this->resolve($value);
123
+ },
124
+ function ($reason = null) {
125
+ $this->reject($reason);
126
+ },
127
+ function ($update = null) {
128
+ $this->progress($update);
129
+ }
130
+ );
131
+ } catch (\Exception $e) {
132
+ $this->reject($e);
133
+ }
134
+ }
135
+ }
backend/vendor/react/promise/src/PromiseInterface.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ interface PromiseInterface
6
+ {
7
+ /**
8
+ * @return PromiseInterface
9
+ */
10
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
11
+ }
backend/vendor/react/promise/src/PromisorInterface.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ interface PromisorInterface
6
+ {
7
+ /**
8
+ * @return PromiseInterface
9
+ */
10
+ public function promise();
11
+ }
backend/vendor/react/promise/src/RejectedPromise.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ class RejectedPromise implements CancellablePromiseInterface
6
+ {
7
+ private $reason;
8
+
9
+ public function __construct($reason = null)
10
+ {
11
+ if ($reason instanceof PromiseInterface) {
12
+ throw new \InvalidArgumentException('You cannot create React\Promise\RejectedPromise with a promise. Use React\Promise\reject($promiseOrValue) instead.');
13
+ }
14
+
15
+ $this->reason = $reason;
16
+ }
17
+
18
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
19
+ {
20
+ try {
21
+ if (null === $onRejected) {
22
+ return new RejectedPromise($this->reason);
23
+ }
24
+
25
+ return resolve($onRejected($this->reason));
26
+ } catch (\Exception $exception) {
27
+ return new RejectedPromise($exception);
28
+ }
29
+ }
30
+
31
+ public function cancel()
32
+ {
33
+ }
34
+ }
backend/vendor/react/promise/src/functions.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace React\Promise;
4
+
5
+ function resolve($promiseOrValue = null)
6
+ {
7
+ if ($promiseOrValue instanceof PromiseInterface) {
8
+ return $promiseOrValue;
9
+ }
10
+
11
+ return new FulfilledPromise($promiseOrValue);
12
+ }
13
+
14
+ function reject($promiseOrValue = null)
15
+ {
16
+ if ($promiseOrValue instanceof PromiseInterface) {
17
+ return $promiseOrValue->then(function ($value) {
18
+ return new RejectedPromise($value);
19
+ });
20
+ }
21
+
22
+ return new RejectedPromise($promiseOrValue);
23
+ }
24
+
25
+ function all($promisesOrValues)
26
+ {
27
+ return map($promisesOrValues, function ($val) {
28
+ return $val;
29
+ });
30
+ }
31
+
32
+ function race($promisesOrValues)
33
+ {
34
+ return resolve($promisesOrValues)
35
+ ->then(function ($array) {
36
+ if (!is_array($array) || !$array) {
37
+ return resolve();
38
+ }
39
+
40
+ return new Promise(function ($resolve, $reject, $progress) use ($array) {
41
+ foreach ($array as $promiseOrValue) {
42
+ resolve($promiseOrValue)
43
+ ->then($resolve, $reject, $progress);
44
+ }
45
+ });
46
+ });
47
+ }
48
+
49
+ function any($promisesOrValues)
50
+ {
51
+ return some($promisesOrValues, 1)
52
+ ->then(function ($val) {
53
+ return array_shift($val);
54
+ });
55
+ }
56
+
57
+ function some($promisesOrValues, $howMany)
58
+ {
59
+ return resolve($promisesOrValues)
60
+ ->then(function ($array) use ($howMany) {
61
+ if (!is_array($array) || !$array || $howMany < 1) {
62
+ return resolve([]);
63
+ }
64
+
65
+ return new Promise(function ($resolve, $reject, $progress) use ($array, $howMany) {
66
+ $len = count($array);
67
+ $toResolve = min($howMany, $len);
68
+ $toReject = ($len - $toResolve) + 1;
69
+ $values = [];
70
+ $reasons = [];
71
+
72
+ foreach ($array as $i => $promiseOrValue) {
73
+ $fulfiller = function ($val) use ($i, &$values, &$toResolve, $toReject, $resolve) {
74
+ if ($toResolve < 1 || $toReject < 1) {
75
+ return;
76
+ }
77
+
78
+ $values[$i] = $val;
79
+
80
+ if (0 === --$toResolve) {
81
+ $resolve($values);
82
+ }
83
+ };
84
+
85
+ $rejecter = function ($reason) use ($i, &$reasons, &$toReject, $toResolve, $reject) {
86
+ if ($toResolve < 1 || $toReject < 1) {
87
+ return;
88
+ }
89
+
90
+ $reasons[$i] = $reason;
91
+
92
+ if (0 === --$toReject) {
93
+ $reject($reasons);
94
+ }
95
+ };
96
+
97
+ resolve($promiseOrValue)
98
+ ->then($fulfiller, $rejecter, $progress);
99
+ }
100
+ });
101
+ });
102
+ }
103
+
104
+ function map($promisesOrValues, callable $mapFunc)
105
+ {
106
+ return resolve($promisesOrValues)
107
+ ->then(function ($array) use ($mapFunc) {
108
+ if (!is_array($array) || !$array) {
109
+ return resolve([]);
110
+ }
111
+
112
+ return new Promise(function ($resolve, $reject, $progress) use ($array, $mapFunc) {
113
+ $toResolve = count($array);
114
+ $values = [];
115
+
116
+ foreach ($array as $i => $promiseOrValue) {
117
+ resolve($promiseOrValue)
118
+ ->then($mapFunc)
119
+ ->then(
120
+ function ($mapped) use ($i, &$values, &$toResolve, $resolve) {
121
+ $values[$i] = $mapped;
122
+
123
+ if (0 === --$toResolve) {
124
+ $resolve($values);
125
+ }
126
+ },
127
+ $reject,
128
+ $progress
129
+ );
130
+ }
131
+ });
132
+ });
133
+ }
134
+
135
+ function reduce($promisesOrValues, callable $reduceFunc , $initialValue = null)
136
+ {
137
+ return resolve($promisesOrValues)
138
+ ->then(function ($array) use ($reduceFunc, $initialValue) {
139
+ if (!is_array($array)) {
140
+ $array = [];
141
+ }
142
+
143
+ $total = count($array);
144
+ $i = 0;
145
+
146
+ // Wrap the supplied $reduceFunc with one that handles promises and then
147
+ // delegates to the supplied.
148
+ $wrappedReduceFunc = function ($current, $val) use ($reduceFunc, $total, &$i) {
149
+ return resolve($current)
150
+ ->then(function ($c) use ($reduceFunc, $total, &$i, $val) {
151
+ return resolve($val)
152
+ ->then(function ($value) use ($reduceFunc, $total, &$i, $c) {
153
+ return $reduceFunc($c, $value, $i++, $total);
154
+ });
155
+ });
156
+ };
157
+
158
+ return array_reduce($array, $wrappedReduceFunc, $initialValue);
159
+ });
160
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/CONTRIBUTING.md ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ # CONTRIBUTING
2
+
3
+ Please don't open pull requests against this repository, please use https://github.com/zendframework/zf2.
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/BadMethodCallException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class BadMethodCallException extends \BadMethodCallException implements
13
+ ExceptionInterface
14
+ {
15
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/ExceptionInterface.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ interface ExceptionInterface
13
+ {
14
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/ExtensionNotLoadedException.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class ExtensionNotLoadedException extends RuntimeException
13
+ {
14
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/InvalidArgumentException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class InvalidArgumentException extends \InvalidArgumentException implements
13
+ ExceptionInterface
14
+ {
15
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/LogicException.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class LogicException extends \LogicException implements ExceptionInterface
13
+ {
14
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/MissingDependencyException.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class MissingDependencyException extends RuntimeException
13
+ {
14
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/MissingKeyException.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class MissingKeyException extends RuntimeException
13
+ {
14
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/OutOfSpaceException.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class OutOfSpaceException extends \OverflowException implements ExceptionInterface
13
+ {
14
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/RuntimeException.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class RuntimeException extends \RuntimeException implements ExceptionInterface
13
+ {
14
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/UnexpectedValueException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class UnexpectedValueException extends \UnexpectedValueException implements
13
+ ExceptionInterface
14
+ {
15
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Exception/UnsupportedMethodCallException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Exception;
11
+
12
+ class UnsupportedMethodCallException extends \BadMethodCallException implements
13
+ ExceptionInterface
14
+ {
15
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/AbstractPattern.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ use Zend\Cache\Exception;
13
+
14
+ abstract class AbstractPattern implements PatternInterface
15
+ {
16
+ /**
17
+ * @var PatternOptions
18
+ */
19
+ protected $options;
20
+
21
+ /**
22
+ * Set pattern options
23
+ *
24
+ * @param PatternOptions $options
25
+ * @return AbstractPattern
26
+ * @throws Exception\InvalidArgumentException
27
+ */
28
+ public function setOptions(PatternOptions $options)
29
+ {
30
+ if (!$options instanceof PatternOptions) {
31
+ $options = new PatternOptions($options);
32
+ }
33
+
34
+ $this->options = $options;
35
+ return $this;
36
+ }
37
+
38
+ /**
39
+ * Get all pattern options
40
+ *
41
+ * @return PatternOptions
42
+ */
43
+ public function getOptions()
44
+ {
45
+ if (null === $this->options) {
46
+ $this->setOptions(new PatternOptions());
47
+ }
48
+ return $this->options;
49
+ }
50
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/CallbackCache.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ use Zend\Cache\Exception;
13
+ use Zend\Stdlib\ErrorHandler;
14
+
15
+ class CallbackCache extends AbstractPattern
16
+ {
17
+ /**
18
+ * Set options
19
+ *
20
+ * @param PatternOptions $options
21
+ * @return CallbackCache
22
+ * @throws Exception\InvalidArgumentException if missing storage option
23
+ */
24
+ public function setOptions(PatternOptions $options)
25
+ {
26
+ parent::setOptions($options);
27
+
28
+ if (!$options->getStorage()) {
29
+ throw new Exception\InvalidArgumentException("Missing option 'storage'");
30
+ }
31
+ return $this;
32
+ }
33
+
34
+ /**
35
+ * Call the specified callback or get the result from cache
36
+ *
37
+ * @param callable $callback A valid callback
38
+ * @param array $args Callback arguments
39
+ * @return mixed Result
40
+ * @throws Exception\RuntimeException if invalid cached data
41
+ * @throws \Exception
42
+ */
43
+ public function call($callback, array $args = array())
44
+ {
45
+ $options = $this->getOptions();
46
+ $storage = $options->getStorage();
47
+ $success = null;
48
+ $key = $this->generateCallbackKey($callback, $args);
49
+ $result = $storage->getItem($key, $success);
50
+ if ($success) {
51
+ if (!array_key_exists(0, $result)) {
52
+ throw new Exception\RuntimeException("Invalid cached data for key '{$key}'");
53
+ }
54
+
55
+ echo isset($result[1]) ? $result[1] : '';
56
+ return $result[0];
57
+ }
58
+
59
+ $cacheOutput = $options->getCacheOutput();
60
+ if ($cacheOutput) {
61
+ ob_start();
62
+ ob_implicit_flush(false);
63
+ }
64
+
65
+ // TODO: do not cache on errors using [set|restore]_error_handler
66
+
67
+ try {
68
+ if ($args) {
69
+ $ret = call_user_func_array($callback, $args);
70
+ } else {
71
+ $ret = call_user_func($callback);
72
+ }
73
+ } catch (\Exception $e) {
74
+ if ($cacheOutput) {
75
+ ob_end_flush();
76
+ }
77
+ throw $e;
78
+ }
79
+
80
+ if ($cacheOutput) {
81
+ $data = array($ret, ob_get_flush());
82
+ } else {
83
+ $data = array($ret);
84
+ }
85
+
86
+ $storage->setItem($key, $data);
87
+
88
+ return $ret;
89
+ }
90
+
91
+ /**
92
+ * function call handler
93
+ *
94
+ * @param string $function Function name to call
95
+ * @param array $args Function arguments
96
+ * @return mixed
97
+ * @throws Exception\RuntimeException
98
+ * @throws \Exception
99
+ */
100
+ public function __call($function, array $args)
101
+ {
102
+ return $this->call($function, $args);
103
+ }
104
+
105
+ /**
106
+ * Generate a unique key in base of a key representing the callback part
107
+ * and a key representing the arguments part.
108
+ *
109
+ * @param callable $callback A valid callback
110
+ * @param array $args Callback arguments
111
+ * @return string
112
+ * @throws Exception\RuntimeException
113
+ * @throws Exception\InvalidArgumentException
114
+ */
115
+ public function generateKey($callback, array $args = array())
116
+ {
117
+ return $this->generateCallbackKey($callback, $args);
118
+ }
119
+
120
+ /**
121
+ * Generate a unique key in base of a key representing the callback part
122
+ * and a key representing the arguments part.
123
+ *
124
+ * @param callable $callback A valid callback
125
+ * @param array $args Callback arguments
126
+ * @throws Exception\RuntimeException if callback not serializable
127
+ * @throws Exception\InvalidArgumentException if invalid callback
128
+ * @return string
129
+ */
130
+ protected function generateCallbackKey($callback, array $args)
131
+ {
132
+ if (!is_callable($callback, false, $callbackKey)) {
133
+ throw new Exception\InvalidArgumentException('Invalid callback');
134
+ }
135
+
136
+ // functions, methods and classnames are case-insensitive
137
+ $callbackKey = strtolower($callbackKey);
138
+
139
+ // generate a unique key of object callbacks
140
+ if (is_object($callback)) { // Closures & __invoke
141
+ $object = $callback;
142
+ } elseif (isset($callback[0])) { // array($object, 'method')
143
+ $object = $callback[0];
144
+ }
145
+ if (isset($object)) {
146
+ ErrorHandler::start();
147
+ try {
148
+ $serializedObject = serialize($object);
149
+ } catch (\Exception $e) {
150
+ ErrorHandler::stop();
151
+ throw new Exception\RuntimeException("Can't serialize callback: see previous exception", 0, $e);
152
+ }
153
+ $error = ErrorHandler::stop();
154
+
155
+ if (!$serializedObject) {
156
+ throw new Exception\RuntimeException(
157
+ sprintf('Cannot serialize callback%s', ($error ? ': ' . $error->getMessage() : '')),
158
+ 0,
159
+ $error
160
+ );
161
+ }
162
+ $callbackKey.= $serializedObject;
163
+ }
164
+
165
+ return md5($callbackKey) . $this->generateArgumentsKey($args);
166
+ }
167
+
168
+ /**
169
+ * Generate a unique key of the argument part.
170
+ *
171
+ * @param array $args
172
+ * @throws Exception\RuntimeException
173
+ * @return string
174
+ */
175
+ protected function generateArgumentsKey(array $args)
176
+ {
177
+ if (!$args) {
178
+ return '';
179
+ }
180
+
181
+ ErrorHandler::start();
182
+ try {
183
+ $serializedArgs = serialize(array_values($args));
184
+ } catch (\Exception $e) {
185
+ ErrorHandler::stop();
186
+ throw new Exception\RuntimeException("Can't serialize arguments: see previous exception", 0, $e);
187
+ }
188
+ $error = ErrorHandler::stop();
189
+
190
+ if (!$serializedArgs) {
191
+ throw new Exception\RuntimeException(
192
+ sprintf('Cannot serialize arguments%s', ($error ? ': ' . $error->getMessage() : '')),
193
+ 0,
194
+ $error
195
+ );
196
+ }
197
+
198
+ return md5($serializedArgs);
199
+ }
200
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/CaptureCache.php ADDED
@@ -0,0 +1,389 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ use Zend\Cache\Exception;
13
+ use Zend\Stdlib\ErrorHandler;
14
+
15
+ class CaptureCache extends AbstractPattern
16
+ {
17
+ /**
18
+ * Start the cache
19
+ *
20
+ * @param string $pageId Page identifier
21
+ * @return void
22
+ */
23
+ public function start($pageId = null)
24
+ {
25
+ if ($pageId === null) {
26
+ $pageId = $this->detectPageId();
27
+ }
28
+
29
+ $that = $this;
30
+ ob_start(function ($content) use ($that, $pageId) {
31
+ $that->set($content, $pageId);
32
+
33
+ // http://php.net/manual/function.ob-start.php
34
+ // -> If output_callback returns FALSE original input is sent to the browser.
35
+ return false;
36
+ });
37
+
38
+ ob_implicit_flush(false);
39
+ }
40
+
41
+ /**
42
+ * Write content to page identity
43
+ *
44
+ * @param string $content
45
+ * @param null|string $pageId
46
+ * @throws Exception\LogicException
47
+ */
48
+ public function set($content, $pageId = null)
49
+ {
50
+ $publicDir = $this->getOptions()->getPublicDir();
51
+ if ($publicDir === null) {
52
+ throw new Exception\LogicException("Option 'public_dir' no set");
53
+ }
54
+
55
+ if ($pageId === null) {
56
+ $pageId = $this->detectPageId();
57
+ }
58
+
59
+ $path = $this->pageId2Path($pageId);
60
+ $file = $path . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
61
+
62
+ $this->createDirectoryStructure($publicDir . DIRECTORY_SEPARATOR . $path);
63
+ $this->putFileContent($publicDir . DIRECTORY_SEPARATOR . $file, $content);
64
+ }
65
+
66
+ /**
67
+ * Get from cache
68
+ *
69
+ * @param null|string $pageId
70
+ * @return string|null
71
+ * @throws Exception\LogicException
72
+ * @throws Exception\RuntimeException
73
+ */
74
+ public function get($pageId = null)
75
+ {
76
+ $publicDir = $this->getOptions()->getPublicDir();
77
+ if ($publicDir === null) {
78
+ throw new Exception\LogicException("Option 'public_dir' no set");
79
+ }
80
+
81
+ if ($pageId === null) {
82
+ $pageId = $this->detectPageId();
83
+ }
84
+
85
+ $file = $publicDir
86
+ . DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
87
+ . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
88
+
89
+ if (file_exists($file)) {
90
+ ErrorHandler::start();
91
+ $content = file_get_contents($file);
92
+ $error = ErrorHandler::stop();
93
+ if ($content === false) {
94
+ throw new Exception\RuntimeException("Failed to read cached pageId '{$pageId}'", 0, $error);
95
+ }
96
+ return $content;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Checks if a cache with given id exists
102
+ *
103
+ * @param null|string $pageId
104
+ * @throws Exception\LogicException
105
+ * @return bool
106
+ */
107
+ public function has($pageId = null)
108
+ {
109
+ $publicDir = $this->getOptions()->getPublicDir();
110
+ if ($publicDir === null) {
111
+ throw new Exception\LogicException("Option 'public_dir' no set");
112
+ }
113
+
114
+ if ($pageId === null) {
115
+ $pageId = $this->detectPageId();
116
+ }
117
+
118
+ $file = $publicDir
119
+ . DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
120
+ . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
121
+
122
+ return file_exists($file);
123
+ }
124
+
125
+ /**
126
+ * Remove from cache
127
+ *
128
+ * @param null|string $pageId
129
+ * @throws Exception\LogicException
130
+ * @throws Exception\RuntimeException
131
+ * @return bool
132
+ */
133
+ public function remove($pageId = null)
134
+ {
135
+ $publicDir = $this->getOptions()->getPublicDir();
136
+ if ($publicDir === null) {
137
+ throw new Exception\LogicException("Option 'public_dir' no set");
138
+ }
139
+
140
+ if ($pageId === null) {
141
+ $pageId = $this->detectPageId();
142
+ }
143
+
144
+ $file = $publicDir
145
+ . DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
146
+ . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
147
+
148
+ if (file_exists($file)) {
149
+ ErrorHandler::start();
150
+ $res = unlink($file);
151
+ $err = ErrorHandler::stop();
152
+ if (!$res) {
153
+ throw new Exception\RuntimeException("Failed to remove cached pageId '{$pageId}'", 0, $err);
154
+ }
155
+ return true;
156
+ }
157
+
158
+ return false;
159
+ }
160
+
161
+ /**
162
+ * Clear cached pages matching glob pattern
163
+ *
164
+ * @param string $pattern
165
+ * @throws Exception\LogicException
166
+ */
167
+ public function clearByGlob($pattern = '**')
168
+ {
169
+ $publicDir = $this->getOptions()->getPublicDir();
170
+ if ($publicDir === null) {
171
+ throw new Exception\LogicException("Option 'public_dir' no set");
172
+ }
173
+
174
+ $it = new \GlobIterator(
175
+ $publicDir . '/' . $pattern,
176
+ \GlobIterator::CURRENT_AS_SELF | \GlobIterator::SKIP_DOTS | \GlobIterator::UNIX_PATHS
177
+ );
178
+ foreach ($it as $pathname => $entry) {
179
+ if ($entry->isFile()) {
180
+ unlink($pathname);
181
+ }
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Determine the page to save from the request
187
+ *
188
+ * @throws Exception\RuntimeException
189
+ * @return string
190
+ */
191
+ protected function detectPageId()
192
+ {
193
+ if (!isset($_SERVER['REQUEST_URI'])) {
194
+ throw new Exception\RuntimeException("Can't auto-detect current page identity");
195
+ }
196
+
197
+ return $_SERVER['REQUEST_URI'];
198
+ }
199
+
200
+ /**
201
+ * Get filename for page id
202
+ *
203
+ * @param string $pageId
204
+ * @return string
205
+ */
206
+ protected function pageId2Filename($pageId)
207
+ {
208
+ if (substr($pageId, -1) === '/') {
209
+ return $this->getOptions()->getIndexFilename();
210
+ }
211
+
212
+ return basename($pageId);
213
+ }
214
+
215
+ /**
216
+ * Get path for page id
217
+ *
218
+ * @param string $pageId
219
+ * @return string
220
+ */
221
+ protected function pageId2Path($pageId)
222
+ {
223
+ if (substr($pageId, -1) == '/') {
224
+ $path = rtrim($pageId, '/');
225
+ } else {
226
+ $path = dirname($pageId);
227
+ }
228
+
229
+ // convert requested "/" to the valid local directory separator
230
+ if ('/' != DIRECTORY_SEPARATOR) {
231
+ $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
232
+ }
233
+
234
+ return $path;
235
+ }
236
+
237
+ /**
238
+ * Write content to a file
239
+ *
240
+ * @param string $file File complete path
241
+ * @param string $data Data to write
242
+ * @return void
243
+ * @throws Exception\RuntimeException
244
+ */
245
+ protected function putFileContent($file, $data)
246
+ {
247
+ $options = $this->getOptions();
248
+ $locking = $options->getFileLocking();
249
+ $perm = $options->getFilePermission();
250
+ $umask = $options->getUmask();
251
+ if ($umask !== false && $perm !== false) {
252
+ $perm = $perm & ~$umask;
253
+ }
254
+
255
+ ErrorHandler::start();
256
+
257
+ $umask = ($umask !== false) ? umask($umask) : false;
258
+ $rs = file_put_contents($file, $data, $locking ? LOCK_EX : 0);
259
+ if ($umask) {
260
+ umask($umask);
261
+ }
262
+
263
+ if ($rs === false) {
264
+ $err = ErrorHandler::stop();
265
+ throw new Exception\RuntimeException("Error writing file '{$file}'", 0, $err);
266
+ }
267
+
268
+ if ($perm !== false && !chmod($file, $perm)) {
269
+ $oct = decoct($perm);
270
+ $err = ErrorHandler::stop();
271
+ throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
272
+ }
273
+
274
+ ErrorHandler::stop();
275
+ }
276
+
277
+ /**
278
+ * Creates directory if not already done.
279
+ *
280
+ * @param string $pathname
281
+ * @return void
282
+ * @throws Exception\RuntimeException
283
+ */
284
+ protected function createDirectoryStructure($pathname)
285
+ {
286
+ // Directory structure already exists
287
+ if (file_exists($pathname)) {
288
+ return;
289
+ }
290
+
291
+ $options = $this->getOptions();
292
+ $perm = $options->getDirPermission();
293
+ $umask = $options->getUmask();
294
+ if ($umask !== false && $perm !== false) {
295
+ $perm = $perm & ~$umask;
296
+ }
297
+
298
+ ErrorHandler::start();
299
+
300
+ if ($perm === false) {
301
+ // build-in mkdir function is enough
302
+
303
+ $umask = ($umask !== false) ? umask($umask) : false;
304
+ $res = mkdir($pathname, ($perm !== false) ? $perm : 0777, true);
305
+
306
+ if ($umask !== false) {
307
+ umask($umask);
308
+ }
309
+
310
+ if (!$res) {
311
+ $oct = ($perm === false) ? '777' : decoct($perm);
312
+ $err = ErrorHandler::stop();
313
+ throw new Exception\RuntimeException("mkdir('{$pathname}', 0{$oct}, true) failed", 0, $err);
314
+ }
315
+
316
+ if ($perm !== false && !chmod($pathname, $perm)) {
317
+ $oct = decoct($perm);
318
+ $err = ErrorHandler::stop();
319
+ throw new Exception\RuntimeException("chmod('{$pathname}', 0{$oct}) failed", 0, $err);
320
+ }
321
+
322
+ } else {
323
+ // build-in mkdir function sets permission together with current umask
324
+ // which doesn't work well on multo threaded webservers
325
+ // -> create directories one by one and set permissions
326
+
327
+ // find existing path and missing path parts
328
+ $parts = array();
329
+ $path = $pathname;
330
+ while (!file_exists($path)) {
331
+ array_unshift($parts, basename($path));
332
+ $nextPath = dirname($path);
333
+ if ($nextPath === $path) {
334
+ break;
335
+ }
336
+ $path = $nextPath;
337
+ }
338
+
339
+ // make all missing path parts
340
+ foreach ($parts as $part) {
341
+ $path.= DIRECTORY_SEPARATOR . $part;
342
+
343
+ // create a single directory, set and reset umask immediately
344
+ $umask = ($umask !== false) ? umask($umask) : false;
345
+ $res = mkdir($path, ($perm === false) ? 0777 : $perm, false);
346
+ if ($umask !== false) {
347
+ umask($umask);
348
+ }
349
+
350
+ if (!$res) {
351
+ $oct = ($perm === false) ? '777' : decoct($perm);
352
+ ErrorHandler::stop();
353
+ throw new Exception\RuntimeException(
354
+ "mkdir('{$path}', 0{$oct}, false) failed"
355
+ );
356
+ }
357
+
358
+ if ($perm !== false && !chmod($path, $perm)) {
359
+ $oct = decoct($perm);
360
+ ErrorHandler::stop();
361
+ throw new Exception\RuntimeException(
362
+ "chmod('{$path}', 0{$oct}) failed"
363
+ );
364
+ }
365
+ }
366
+ }
367
+
368
+ ErrorHandler::stop();
369
+ }
370
+
371
+ /**
372
+ * Returns the generated file name.
373
+ *
374
+ * @param null|string $pageId
375
+ * @return string
376
+ */
377
+ public function getFilename($pageId = null)
378
+ {
379
+ if ($pageId === null) {
380
+ $pageId = $this->detectPageId();
381
+ }
382
+
383
+ $publicDir = $this->getOptions()->getPublicDir();
384
+ $path = $this->pageId2Path($pageId);
385
+ $file = $path . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
386
+
387
+ return $publicDir . $file;
388
+ }
389
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/ClassCache.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ use Zend\Cache;
13
+ use Zend\Cache\Exception;
14
+
15
+ class ClassCache extends CallbackCache
16
+ {
17
+ /**
18
+ * Set options
19
+ *
20
+ * @param PatternOptions $options
21
+ * @return ClassCache
22
+ * @throws Exception\InvalidArgumentException if missing 'class' or 'storage' options
23
+ */
24
+ public function setOptions(PatternOptions $options)
25
+ {
26
+ parent::setOptions($options);
27
+
28
+ if (!$options->getClass()) {
29
+ throw new Exception\InvalidArgumentException("Missing option 'class'");
30
+ } elseif (!$options->getStorage()) {
31
+ throw new Exception\InvalidArgumentException("Missing option 'storage'");
32
+ }
33
+ return $this;
34
+ }
35
+
36
+ /**
37
+ * Call and cache a class method
38
+ *
39
+ * @param string $method Method name to call
40
+ * @param array $args Method arguments
41
+ * @return mixed
42
+ * @throws Exception\RuntimeException
43
+ * @throws \Exception
44
+ */
45
+ public function call($method, array $args = array())
46
+ {
47
+ $options = $this->getOptions();
48
+ $classname = $options->getClass();
49
+ $method = strtolower($method);
50
+ $callback = $classname . '::' . $method;
51
+
52
+ $cache = $options->getCacheByDefault();
53
+ if ($cache) {
54
+ $cache = !in_array($method, $options->getClassNonCacheMethods());
55
+ } else {
56
+ $cache = in_array($method, $options->getClassCacheMethods());
57
+ }
58
+
59
+ if (!$cache) {
60
+ if ($args) {
61
+ return call_user_func_array($callback, $args);
62
+ } else {
63
+ return $classname::$method();
64
+ }
65
+ }
66
+
67
+ return parent::call($callback, $args);
68
+ }
69
+
70
+ /**
71
+ * Generate a unique key in base of a key representing the callback part
72
+ * and a key representing the arguments part.
73
+ *
74
+ * @param string $method The method
75
+ * @param array $args Callback arguments
76
+ * @return string
77
+ * @throws Exception\RuntimeException
78
+ */
79
+ public function generateKey($method, array $args = array())
80
+ {
81
+ return $this->generateCallbackKey(
82
+ $this->getOptions()->getClass() . '::' . $method,
83
+ $args
84
+ );
85
+ }
86
+
87
+ /**
88
+ * Generate a unique key in base of a key representing the callback part
89
+ * and a key representing the arguments part.
90
+ *
91
+ * @param callable $callback A valid callback
92
+ * @param array $args Callback arguments
93
+ * @return string
94
+ * @throws Exception\RuntimeException
95
+ */
96
+ protected function generateCallbackKey($callback, array $args)
97
+ {
98
+ $callbackKey = md5(strtolower($callback));
99
+ $argumentKey = $this->generateArgumentsKey($args);
100
+ return $callbackKey . $argumentKey;
101
+ }
102
+
103
+ /**
104
+ * Calling a method of the entity.
105
+ *
106
+ * @param string $method Method name to call
107
+ * @param array $args Method arguments
108
+ * @return mixed
109
+ * @throws Exception\RuntimeException
110
+ * @throws \Exception
111
+ */
112
+ public function __call($method, array $args)
113
+ {
114
+ return $this->call($method, $args);
115
+ }
116
+
117
+ /**
118
+ * Set a static property
119
+ *
120
+ * @param string $name
121
+ * @param mixed $value
122
+ * @return void
123
+ * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
124
+ */
125
+ public function __set($name, $value)
126
+ {
127
+ $class = $this->getOptions()->getClass();
128
+ $class::$name = $value;
129
+ }
130
+
131
+ /**
132
+ * Get a static property
133
+ *
134
+ * @param string $name
135
+ * @return mixed
136
+ * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
137
+ */
138
+ public function __get($name)
139
+ {
140
+ $class = $this->getOptions()->getClass();
141
+ return $class::$name;
142
+ }
143
+
144
+ /**
145
+ * Is a static property exists.
146
+ *
147
+ * @param string $name
148
+ * @return bool
149
+ */
150
+ public function __isset($name)
151
+ {
152
+ $class = $this->getOptions()->getClass();
153
+ return isset($class::$name);
154
+ }
155
+
156
+ /**
157
+ * Unset a static property
158
+ *
159
+ * @param string $name
160
+ * @return void
161
+ */
162
+ public function __unset($name)
163
+ {
164
+ $class = $this->getOptions()->getClass();
165
+ unset($class::$name);
166
+ }
167
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/ObjectCache.php ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ use Zend\Cache\Exception;
13
+
14
+ class ObjectCache extends CallbackCache
15
+ {
16
+ /**
17
+ * Set options
18
+ *
19
+ * @param PatternOptions $options
20
+ * @return void
21
+ * @throws Exception\InvalidArgumentException
22
+ */
23
+ public function setOptions(PatternOptions $options)
24
+ {
25
+ parent::setOptions($options);
26
+
27
+ if (!$options->getObject()) {
28
+ throw new Exception\InvalidArgumentException("Missing option 'object'");
29
+ } elseif (!$options->getStorage()) {
30
+ throw new Exception\InvalidArgumentException("Missing option 'storage'");
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Call and cache a class method
36
+ *
37
+ * @param string $method Method name to call
38
+ * @param array $args Method arguments
39
+ * @return mixed
40
+ * @throws Exception\RuntimeException
41
+ * @throws \Exception
42
+ */
43
+ public function call($method, array $args = array())
44
+ {
45
+ $options = $this->getOptions();
46
+ $object = $options->getObject();
47
+ $method = strtolower($method);
48
+
49
+ // handle magic methods
50
+ switch ($method) {
51
+ case '__set':
52
+ $property = array_shift($args);
53
+ $value = array_shift($args);
54
+
55
+ $object->{$property} = $value;
56
+
57
+ if (!$options->getObjectCacheMagicProperties()
58
+ || property_exists($object, $property)
59
+ ) {
60
+ // no caching if property isn't magic
61
+ // or caching magic properties is disabled
62
+ return;
63
+ }
64
+
65
+ // remove cached __get and __isset
66
+ $removeKeys = null;
67
+ if (method_exists($object, '__get')) {
68
+ $removeKeys[] = $this->generateKey('__get', array($property));
69
+ }
70
+ if (method_exists($object, '__isset')) {
71
+ $removeKeys[] = $this->generateKey('__isset', array($property));
72
+ }
73
+ if ($removeKeys) {
74
+ $options->getStorage()->removeItems($removeKeys);
75
+ }
76
+ return;
77
+
78
+ case '__get':
79
+ $property = array_shift($args);
80
+
81
+ if (!$options->getObjectCacheMagicProperties()
82
+ || property_exists($object, $property)
83
+ ) {
84
+ // no caching if property isn't magic
85
+ // or caching magic properties is disabled
86
+ return $object->{$property};
87
+ }
88
+
89
+ array_unshift($args, $property);
90
+ return parent::call(array($object, '__get'), $args);
91
+
92
+ case '__isset':
93
+ $property = array_shift($args);
94
+
95
+ if (!$options->getObjectCacheMagicProperties()
96
+ || property_exists($object, $property)
97
+ ) {
98
+ // no caching if property isn't magic
99
+ // or caching magic properties is disabled
100
+ return isset($object->{$property});
101
+ }
102
+
103
+ return parent::call(array($object, '__isset'), array($property));
104
+
105
+ case '__unset':
106
+ $property = array_shift($args);
107
+
108
+ unset($object->{$property});
109
+
110
+ if (!$options->getObjectCacheMagicProperties()
111
+ || property_exists($object, $property)
112
+ ) {
113
+ // no caching if property isn't magic
114
+ // or caching magic properties is disabled
115
+ return;
116
+ }
117
+
118
+ // remove previous cached __get and __isset calls
119
+ $removeKeys = null;
120
+ if (method_exists($object, '__get')) {
121
+ $removeKeys[] = $this->generateKey('__get', array($property));
122
+ }
123
+ if (method_exists($object, '__isset')) {
124
+ $removeKeys[] = $this->generateKey('__isset', array($property));
125
+ }
126
+ if ($removeKeys) {
127
+ $options->getStorage()->removeItems($removeKeys);
128
+ }
129
+ return;
130
+ }
131
+
132
+ $cache = $options->getCacheByDefault();
133
+ if ($cache) {
134
+ $cache = !in_array($method, $options->getObjectNonCacheMethods());
135
+ } else {
136
+ $cache = in_array($method, $options->getObjectCacheMethods());
137
+ }
138
+
139
+ if (!$cache) {
140
+ if ($args) {
141
+ return call_user_func_array(array($object, $method), $args);
142
+ }
143
+ return $object->{$method}();
144
+ }
145
+
146
+ return parent::call(array($object, $method), $args);
147
+ }
148
+
149
+ /**
150
+ * Generate a unique key in base of a key representing the callback part
151
+ * and a key representing the arguments part.
152
+ *
153
+ * @param string $method The method
154
+ * @param array $args Callback arguments
155
+ * @return string
156
+ * @throws Exception\RuntimeException
157
+ */
158
+ public function generateKey($method, array $args = array())
159
+ {
160
+ return $this->generateCallbackKey(
161
+ array($this->getOptions()->getObject(), $method),
162
+ $args
163
+ );
164
+ }
165
+
166
+ /**
167
+ * Generate a unique key in base of a key representing the callback part
168
+ * and a key representing the arguments part.
169
+ *
170
+ * @param callable $callback A valid callback
171
+ * @param array $args Callback arguments
172
+ * @return string
173
+ * @throws Exception\RuntimeException
174
+ */
175
+ protected function generateCallbackKey($callback, array $args = array())
176
+ {
177
+ $callbackKey = md5($this->getOptions()->getObjectKey() . '::' . strtolower($callback[1]));
178
+ $argumentKey = $this->generateArgumentsKey($args);
179
+ return $callbackKey . $argumentKey;
180
+ }
181
+
182
+ /**
183
+ * Class method call handler
184
+ *
185
+ * @param string $method Method name to call
186
+ * @param array $args Method arguments
187
+ * @return mixed
188
+ * @throws Exception\RuntimeException
189
+ * @throws \Exception
190
+ */
191
+ public function __call($method, array $args)
192
+ {
193
+ return $this->call($method, $args);
194
+ }
195
+
196
+ /**
197
+ * Writing data to properties.
198
+ *
199
+ * NOTE:
200
+ * Magic properties will be cached too if the option cacheMagicProperties
201
+ * is enabled and the property doesn't exist in real. If so it calls __set
202
+ * and removes cached data of previous __get and __isset calls.
203
+ *
204
+ * @param string $name
205
+ * @param mixed $value
206
+ * @return void
207
+ * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
208
+ */
209
+ public function __set($name, $value)
210
+ {
211
+ return $this->call('__set', array($name, $value));
212
+ }
213
+
214
+ /**
215
+ * Reading data from properties.
216
+ *
217
+ * NOTE:
218
+ * Magic properties will be cached too if the option cacheMagicProperties
219
+ * is enabled and the property doesn't exist in real. If so it calls __get.
220
+ *
221
+ * @param string $name
222
+ * @return mixed
223
+ * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
224
+ */
225
+ public function __get($name)
226
+ {
227
+ return $this->call('__get', array($name));
228
+ }
229
+
230
+ /**
231
+ * Checking existing properties.
232
+ *
233
+ * NOTE:
234
+ * Magic properties will be cached too if the option cacheMagicProperties
235
+ * is enabled and the property doesn't exist in real. If so it calls __get.
236
+ *
237
+ * @param string $name
238
+ * @return bool
239
+ * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
240
+ */
241
+ public function __isset($name)
242
+ {
243
+ return $this->call('__isset', array($name));
244
+ }
245
+
246
+ /**
247
+ * Unseting a property.
248
+ *
249
+ * NOTE:
250
+ * Magic properties will be cached too if the option cacheMagicProperties
251
+ * is enabled and the property doesn't exist in real. If so it removes
252
+ * previous cached __isset and __get calls.
253
+ *
254
+ * @param string $name
255
+ * @return void
256
+ * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
257
+ */
258
+ public function __unset($name)
259
+ {
260
+ return $this->call('__unset', array($name));
261
+ }
262
+
263
+ /**
264
+ * Handle casting to string
265
+ *
266
+ * @return string
267
+ * @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.tostring
268
+ */
269
+ public function __toString()
270
+ {
271
+ return $this->call('__toString');
272
+ }
273
+
274
+ /**
275
+ * Handle invoke calls
276
+ *
277
+ * @return mixed
278
+ * @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.invoke
279
+ */
280
+ public function __invoke()
281
+ {
282
+ return $this->call('__invoke', func_get_args());
283
+ }
284
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/OutputCache.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ use Zend\Cache\Exception;
13
+
14
+ class OutputCache extends AbstractPattern
15
+ {
16
+ /**
17
+ * The key stack
18
+ *
19
+ * @var array
20
+ */
21
+ protected $keyStack = array();
22
+
23
+ /**
24
+ * Set options
25
+ *
26
+ * @param PatternOptions $options
27
+ * @return OutputCache
28
+ * @throws Exception\InvalidArgumentException
29
+ */
30
+ public function setOptions(PatternOptions $options)
31
+ {
32
+ parent::setOptions($options);
33
+
34
+ if (!$options->getStorage()) {
35
+ throw new Exception\InvalidArgumentException("Missing option 'storage'");
36
+ }
37
+
38
+ return $this;
39
+ }
40
+
41
+ /**
42
+ * if there is a cached item with the given key display it's data and return true
43
+ * else start buffering output until end() is called or the script ends.
44
+ *
45
+ * @param string $key Key
46
+ * @throws Exception\MissingKeyException if key is missing
47
+ * @return bool
48
+ */
49
+ public function start($key)
50
+ {
51
+ if (($key = (string) $key) === '') {
52
+ throw new Exception\MissingKeyException('Missing key to read/write output from cache');
53
+ }
54
+
55
+ $success = null;
56
+ $data = $this->getOptions()->getStorage()->getItem($key, $success);
57
+ if ($success) {
58
+ echo $data;
59
+ return true;
60
+ }
61
+
62
+ ob_start();
63
+ ob_implicit_flush(false);
64
+ $this->keyStack[] = $key;
65
+ return false;
66
+ }
67
+
68
+ /**
69
+ * Stops buffering output, write buffered data to cache using the given key on start()
70
+ * and displays the buffer.
71
+ *
72
+ * @throws Exception\RuntimeException if output cache not started or buffering not active
73
+ * @return bool TRUE on success, FALSE on failure writing to cache
74
+ */
75
+ public function end()
76
+ {
77
+ $key = array_pop($this->keyStack);
78
+ if ($key === null) {
79
+ throw new Exception\RuntimeException('Output cache not started');
80
+ }
81
+
82
+ $output = ob_get_flush();
83
+ if ($output === false) {
84
+ throw new Exception\RuntimeException('Output buffering not active');
85
+ }
86
+
87
+ return $this->getOptions()->getStorage()->setItem($key, $output);
88
+ }
89
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/PatternInterface.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ interface PatternInterface
13
+ {
14
+ /**
15
+ * Set pattern options
16
+ *
17
+ * @param PatternOptions $options
18
+ * @return PatternInterface
19
+ */
20
+ public function setOptions(PatternOptions $options);
21
+
22
+ /**
23
+ * Get all pattern options
24
+ *
25
+ * @return PatternOptions
26
+ */
27
+ public function getOptions();
28
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Pattern/PatternOptions.php ADDED
@@ -0,0 +1,765 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Pattern;
11
+
12
+ use Traversable;
13
+ use Zend\Cache\Exception;
14
+ use Zend\Cache\StorageFactory;
15
+ use Zend\Cache\Storage\StorageInterface as Storage;
16
+ use Zend\Stdlib\AbstractOptions;
17
+
18
+ class PatternOptions extends AbstractOptions
19
+ {
20
+ /**
21
+ * Used by:
22
+ * - ClassCache
23
+ * - ObjectCache
24
+ * @var bool
25
+ */
26
+ protected $cacheByDefault = true;
27
+
28
+ /**
29
+ * Used by:
30
+ * - CallbackCache
31
+ * - ClassCache
32
+ * - ObjectCache
33
+ * @var bool
34
+ */
35
+ protected $cacheOutput = true;
36
+
37
+ /**
38
+ * Used by:
39
+ * - ClassCache
40
+ * @var null|string
41
+ */
42
+ protected $class;
43
+
44
+ /**
45
+ * Used by:
46
+ * - ClassCache
47
+ * @var array
48
+ */
49
+ protected $classCacheMethods = array();
50
+
51
+ /**
52
+ * Used by:
53
+ * - ClassCache
54
+ * @var array
55
+ */
56
+ protected $classNonCacheMethods = array();
57
+
58
+ /**
59
+ * Used by:
60
+ * - CaptureCache
61
+ * @var false|int
62
+ */
63
+ protected $umask = false;
64
+
65
+ /**
66
+ * Used by:
67
+ * - CaptureCache
68
+ * @var false|int
69
+ */
70
+ protected $dirPermission = 0700;
71
+
72
+ /**
73
+ * Used by:
74
+ * - CaptureCache
75
+ * @var false|int
76
+ */
77
+ protected $filePermission = 0600;
78
+
79
+ /**
80
+ * Used by:
81
+ * - CaptureCache
82
+ * @var bool
83
+ */
84
+ protected $fileLocking = true;
85
+
86
+ /**
87
+ * Used by:
88
+ * - CaptureCache
89
+ * @var string
90
+ */
91
+ protected $indexFilename = 'index.html';
92
+
93
+ /**
94
+ * Used by:
95
+ * - ObjectCache
96
+ * @var null|object
97
+ */
98
+ protected $object;
99
+
100
+ /**
101
+ * Used by:
102
+ * - ObjectCache
103
+ * @var bool
104
+ */
105
+ protected $objectCacheMagicProperties = false;
106
+
107
+ /**
108
+ * Used by:
109
+ * - ObjectCache
110
+ * @var array
111
+ */
112
+ protected $objectCacheMethods = array();
113
+
114
+ /**
115
+ * Used by:
116
+ * - ObjectCache
117
+ * @var null|string
118
+ */
119
+ protected $objectKey;
120
+
121
+ /**
122
+ * Used by:
123
+ * - ObjectCache
124
+ * @var array
125
+ */
126
+ protected $objectNonCacheMethods = array('__tostring');
127
+
128
+ /**
129
+ * Used by:
130
+ * - CaptureCache
131
+ * @var null|string
132
+ */
133
+ protected $publicDir;
134
+
135
+ /**
136
+ * Used by:
137
+ * - CallbackCache
138
+ * - ClassCache
139
+ * - ObjectCache
140
+ * - OutputCache
141
+ * @var null|Storage
142
+ */
143
+ protected $storage;
144
+
145
+ /**
146
+ * Constructor
147
+ *
148
+ * @param array|Traversable|null $options
149
+ * @return PatternOptions
150
+ * @throws Exception\InvalidArgumentException
151
+ */
152
+ public function __construct($options = null)
153
+ {
154
+ // disable file/directory permissions by default on windows systems
155
+ if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
156
+ $this->filePermission = false;
157
+ $this->dirPermission = false;
158
+ }
159
+
160
+ parent::__construct($options);
161
+ }
162
+
163
+ /**
164
+ * Set flag indicating whether or not to cache by default
165
+ *
166
+ * Used by:
167
+ * - ClassCache
168
+ * - ObjectCache
169
+ *
170
+ * @param bool $cacheByDefault
171
+ * @return PatternOptions
172
+ */
173
+ public function setCacheByDefault($cacheByDefault)
174
+ {
175
+ $this->cacheByDefault = $cacheByDefault;
176
+ return $this;
177
+ }
178
+
179
+ /**
180
+ * Do we cache by default?
181
+ *
182
+ * Used by:
183
+ * - ClassCache
184
+ * - ObjectCache
185
+ *
186
+ * @return bool
187
+ */
188
+ public function getCacheByDefault()
189
+ {
190
+ return $this->cacheByDefault;
191
+ }
192
+
193
+ /**
194
+ * Set whether or not to cache output
195
+ *
196
+ * Used by:
197
+ * - CallbackCache
198
+ * - ClassCache
199
+ * - ObjectCache
200
+ *
201
+ * @param bool $cacheOutput
202
+ * @return PatternOptions
203
+ */
204
+ public function setCacheOutput($cacheOutput)
205
+ {
206
+ $this->cacheOutput = (bool) $cacheOutput;
207
+ return $this;
208
+ }
209
+
210
+ /**
211
+ * Will we cache output?
212
+ *
213
+ * Used by:
214
+ * - CallbackCache
215
+ * - ClassCache
216
+ * - ObjectCache
217
+ *
218
+ * @return bool
219
+ */
220
+ public function getCacheOutput()
221
+ {
222
+ return $this->cacheOutput;
223
+ }
224
+
225
+ /**
226
+ * Set class name
227
+ *
228
+ * Used by:
229
+ * - ClassCache
230
+ *
231
+ * @param string $class
232
+ * @throws Exception\InvalidArgumentException
233
+ * @return PatternOptions
234
+ */
235
+ public function setClass($class)
236
+ {
237
+ if (!is_string($class)) {
238
+ throw new Exception\InvalidArgumentException('Invalid classname provided; must be a string');
239
+ }
240
+ $this->class = $class;
241
+ return $this;
242
+ }
243
+
244
+ /**
245
+ * Get class name
246
+ *
247
+ * Used by:
248
+ * - ClassCache
249
+ *
250
+ * @return null|string
251
+ */
252
+ public function getClass()
253
+ {
254
+ return $this->class;
255
+ }
256
+
257
+ /**
258
+ * Set list of method return values to cache
259
+ *
260
+ * Used by:
261
+ * - ClassCache
262
+ *
263
+ * @param array $classCacheMethods
264
+ * @return PatternOptions
265
+ */
266
+ public function setClassCacheMethods(array $classCacheMethods)
267
+ {
268
+ $this->classCacheMethods = $this->recursiveStrtolower($classCacheMethods);
269
+ return $this;
270
+ }
271
+
272
+ /**
273
+ * Get list of methods from which to cache return values
274
+ *
275
+ * Used by:
276
+ * - ClassCache
277
+ *
278
+ * @return array
279
+ */
280
+ public function getClassCacheMethods()
281
+ {
282
+ return $this->classCacheMethods;
283
+ }
284
+
285
+ /**
286
+ * Set list of method return values NOT to cache
287
+ *
288
+ * Used by:
289
+ * - ClassCache
290
+ *
291
+ * @param array $classNonCacheMethods
292
+ * @return PatternOptions
293
+ */
294
+ public function setClassNonCacheMethods(array $classNonCacheMethods)
295
+ {
296
+ $this->classNonCacheMethods = $this->recursiveStrtolower($classNonCacheMethods);
297
+ return $this;
298
+ }
299
+
300
+ /**
301
+ * Get list of methods from which NOT to cache return values
302
+ *
303
+ * Used by:
304
+ * - ClassCache
305
+ *
306
+ * @return array
307
+ */
308
+ public function getClassNonCacheMethods()
309
+ {
310
+ return $this->classNonCacheMethods;
311
+ }
312
+
313
+ /**
314
+ * Set directory permission
315
+ *
316
+ * @param false|int $dirPermission
317
+ * @throws Exception\InvalidArgumentException
318
+ * @return PatternOptions
319
+ */
320
+ public function setDirPermission($dirPermission)
321
+ {
322
+ if ($dirPermission !== false) {
323
+ if (is_string($dirPermission)) {
324
+ $dirPermission = octdec($dirPermission);
325
+ } else {
326
+ $dirPermission = (int) $dirPermission;
327
+ }
328
+
329
+ // validate
330
+ if (($dirPermission & 0700) != 0700) {
331
+ throw new Exception\InvalidArgumentException(
332
+ 'Invalid directory permission: need permission to execute, read and write by owner'
333
+ );
334
+ }
335
+ }
336
+
337
+ $this->dirPermission = $dirPermission;
338
+ return $this;
339
+ }
340
+
341
+ /**
342
+ * Gets directory permission
343
+ *
344
+ * @return false|int
345
+ */
346
+ public function getDirPermission()
347
+ {
348
+ return $this->dirPermission;
349
+ }
350
+
351
+ /**
352
+ * Set umask
353
+ *
354
+ * Used by:
355
+ * - CaptureCache
356
+ *
357
+ * @param false|int $umask
358
+ * @throws Exception\InvalidArgumentException
359
+ * @return PatternOptions
360
+ */
361
+ public function setUmask($umask)
362
+ {
363
+ if ($umask !== false) {
364
+ if (is_string($umask)) {
365
+ $umask = octdec($umask);
366
+ } else {
367
+ $umask = (int) $umask;
368
+ }
369
+
370
+ // validate
371
+ if ($umask & 0700) {
372
+ throw new Exception\InvalidArgumentException(
373
+ 'Invalid umask: need permission to execute, read and write by owner'
374
+ );
375
+ }
376
+
377
+ // normalize
378
+ $umask = $umask & 0777;
379
+ }
380
+
381
+ $this->umask = $umask;
382
+ return $this;
383
+ }
384
+
385
+ /**
386
+ * Get umask
387
+ *
388
+ * Used by:
389
+ * - CaptureCache
390
+ *
391
+ * @return false|int
392
+ */
393
+ public function getUmask()
394
+ {
395
+ return $this->umask;
396
+ }
397
+
398
+ /**
399
+ * Set whether or not file locking should be used
400
+ *
401
+ * Used by:
402
+ * - CaptureCache
403
+ *
404
+ * @param bool $fileLocking
405
+ * @return PatternOptions
406
+ */
407
+ public function setFileLocking($fileLocking)
408
+ {
409
+ $this->fileLocking = (bool) $fileLocking;
410
+ return $this;
411
+ }
412
+
413
+ /**
414
+ * Is file locking enabled?
415
+ *
416
+ * Used by:
417
+ * - CaptureCache
418
+ *
419
+ * @return bool
420
+ */
421
+ public function getFileLocking()
422
+ {
423
+ return $this->fileLocking;
424
+ }
425
+
426
+ /**
427
+ * Set file permission
428
+ *
429
+ * @param false|int $filePermission
430
+ * @throws Exception\InvalidArgumentException
431
+ * @return PatternOptions
432
+ */
433
+ public function setFilePermission($filePermission)
434
+ {
435
+ if ($filePermission !== false) {
436
+ if (is_string($filePermission)) {
437
+ $filePermission = octdec($filePermission);
438
+ } else {
439
+ $filePermission = (int) $filePermission;
440
+ }
441
+
442
+ // validate
443
+ if (($filePermission & 0600) != 0600) {
444
+ throw new Exception\InvalidArgumentException(
445
+ 'Invalid file permission: need permission to read and write by owner'
446
+ );
447
+ } elseif ($filePermission & 0111) {
448
+ throw new Exception\InvalidArgumentException(
449
+ "Invalid file permission: Files shoudn't be executable"
450
+ );
451
+ }
452
+ }
453
+
454
+ $this->filePermission = $filePermission;
455
+ return $this;
456
+ }
457
+
458
+ /**
459
+ * Gets file permission
460
+ *
461
+ * @return false|int
462
+ */
463
+ public function getFilePermission()
464
+ {
465
+ return $this->filePermission;
466
+ }
467
+
468
+ /**
469
+ * Set value for index filename
470
+ *
471
+ * @param string $indexFilename
472
+ * @return PatternOptions
473
+ */
474
+ public function setIndexFilename($indexFilename)
475
+ {
476
+ $this->indexFilename = (string) $indexFilename;
477
+ return $this;
478
+ }
479
+
480
+ /**
481
+ * Get value for index filename
482
+ *
483
+ * @return string
484
+ */
485
+ public function getIndexFilename()
486
+ {
487
+ return $this->indexFilename;
488
+ }
489
+
490
+ /**
491
+ * Set object to cache
492
+ *
493
+ * @param mixed $object
494
+ * @throws Exception\InvalidArgumentException
495
+ * @return PatternOptions
496
+ */
497
+ public function setObject($object)
498
+ {
499
+ if (!is_object($object)) {
500
+ throw new Exception\InvalidArgumentException(
501
+ sprintf('%s expects an object; received "%s"', __METHOD__, gettype($object))
502
+ );
503
+ }
504
+ $this->object = $object;
505
+ return $this;
506
+ }
507
+
508
+ /**
509
+ * Get object to cache
510
+ *
511
+ * @return null|object
512
+ */
513
+ public function getObject()
514
+ {
515
+ return $this->object;
516
+ }
517
+
518
+ /**
519
+ * Set flag indicating whether or not to cache magic properties
520
+ *
521
+ * Used by:
522
+ * - ObjectCache
523
+ *
524
+ * @param bool $objectCacheMagicProperties
525
+ * @return PatternOptions
526
+ */
527
+ public function setObjectCacheMagicProperties($objectCacheMagicProperties)
528
+ {
529
+ $this->objectCacheMagicProperties = (bool) $objectCacheMagicProperties;
530
+ return $this;
531
+ }
532
+
533
+ /**
534
+ * Should we cache magic properties?
535
+ *
536
+ * Used by:
537
+ * - ObjectCache
538
+ *
539
+ * @return bool
540
+ */
541
+ public function getObjectCacheMagicProperties()
542
+ {
543
+ return $this->objectCacheMagicProperties;
544
+ }
545
+
546
+ /**
547
+ * Set list of object methods for which to cache return values
548
+ *
549
+ * @param array $objectCacheMethods
550
+ * @return PatternOptions
551
+ * @throws Exception\InvalidArgumentException
552
+ */
553
+ public function setObjectCacheMethods(array $objectCacheMethods)
554
+ {
555
+ $this->objectCacheMethods = $this->normalizeObjectMethods($objectCacheMethods);
556
+ return $this;
557
+ }
558
+
559
+ /**
560
+ * Get list of object methods for which to cache return values
561
+ *
562
+ * @return array
563
+ */
564
+ public function getObjectCacheMethods()
565
+ {
566
+ return $this->objectCacheMethods;
567
+ }
568
+
569
+ /**
570
+ * Set the object key part.
571
+ *
572
+ * Used to generate a callback key in order to speed up key generation.
573
+ *
574
+ * Used by:
575
+ * - ObjectCache
576
+ *
577
+ * @param mixed $objectKey
578
+ * @return PatternOptions
579
+ */
580
+ public function setObjectKey($objectKey)
581
+ {
582
+ if ($objectKey !== null) {
583
+ $this->objectKey = (string) $objectKey;
584
+ } else {
585
+ $this->objectKey = null;
586
+ }
587
+ return $this;
588
+ }
589
+
590
+ /**
591
+ * Get object key
592
+ *
593
+ * Used by:
594
+ * - ObjectCache
595
+ *
596
+ * @return string
597
+ */
598
+ public function getObjectKey()
599
+ {
600
+ if (!$this->objectKey) {
601
+ return get_class($this->getObject());
602
+ }
603
+ return $this->objectKey;
604
+ }
605
+
606
+ /**
607
+ * Set list of object methods for which NOT to cache return values
608
+ *
609
+ * @param array $objectNonCacheMethods
610
+ * @return PatternOptions
611
+ * @throws Exception\InvalidArgumentException
612
+ */
613
+ public function setObjectNonCacheMethods(array $objectNonCacheMethods)
614
+ {
615
+ $this->objectNonCacheMethods = $this->normalizeObjectMethods($objectNonCacheMethods);
616
+ return $this;
617
+ }
618
+
619
+ /**
620
+ * Get list of object methods for which NOT to cache return values
621
+ *
622
+ * @return array
623
+ */
624
+ public function getObjectNonCacheMethods()
625
+ {
626
+ return $this->objectNonCacheMethods;
627
+ }
628
+
629
+ /**
630
+ * Set location of public directory
631
+ *
632
+ * Used by:
633
+ * - CaptureCache
634
+ *
635
+ * @param string $publicDir
636
+ * @throws Exception\InvalidArgumentException
637
+ * @return PatternOptions
638
+ */
639
+ public function setPublicDir($publicDir)
640
+ {
641
+ $publicDir = (string) $publicDir;
642
+
643
+ if (!is_dir($publicDir)) {
644
+ throw new Exception\InvalidArgumentException(
645
+ "Public directory '{$publicDir}' not found or not a directory"
646
+ );
647
+ } elseif (!is_writable($publicDir)) {
648
+ throw new Exception\InvalidArgumentException(
649
+ "Public directory '{$publicDir}' not writable"
650
+ );
651
+ } elseif (!is_readable($publicDir)) {
652
+ throw new Exception\InvalidArgumentException(
653
+ "Public directory '{$publicDir}' not readable"
654
+ );
655
+ }
656
+
657
+ $this->publicDir = rtrim(realpath($publicDir), DIRECTORY_SEPARATOR);
658
+ return $this;
659
+ }
660
+
661
+ /**
662
+ * Get location of public directory
663
+ *
664
+ * Used by:
665
+ * - CaptureCache
666
+ *
667
+ * @return null|string
668
+ */
669
+ public function getPublicDir()
670
+ {
671
+ return $this->publicDir;
672
+ }
673
+
674
+ /**
675
+ * Set storage adapter
676
+ *
677
+ * Required for the following Pattern classes:
678
+ * - CallbackCache
679
+ * - ClassCache
680
+ * - ObjectCache
681
+ * - OutputCache
682
+ *
683
+ * @param string|array|Storage $storage
684
+ * @return PatternOptions
685
+ */
686
+ public function setStorage($storage)
687
+ {
688
+ $this->storage = $this->storageFactory($storage);
689
+ return $this;
690
+ }
691
+
692
+ /**
693
+ * Get storage adapter
694
+ *
695
+ * Used by:
696
+ * - CallbackCache
697
+ * - ClassCache
698
+ * - ObjectCache
699
+ * - OutputCache
700
+ *
701
+ * @return null|Storage
702
+ */
703
+ public function getStorage()
704
+ {
705
+ return $this->storage;
706
+ }
707
+
708
+ /**
709
+ * Recursively apply strtolower on all values of an array, and return as a
710
+ * list of unique values
711
+ *
712
+ * @param array $array
713
+ * @return array
714
+ */
715
+ protected function recursiveStrtolower(array $array)
716
+ {
717
+ return array_values(array_unique(array_map('strtolower', $array)));
718
+ }
719
+
720
+ /**
721
+ * Normalize object methods
722
+ *
723
+ * Recursively casts values to lowercase, then determines if any are in a
724
+ * list of methods not handled, raising an exception if so.
725
+ *
726
+ * @param array $methods
727
+ * @return array
728
+ * @throws Exception\InvalidArgumentException
729
+ */
730
+ protected function normalizeObjectMethods(array $methods)
731
+ {
732
+ $methods = $this->recursiveStrtolower($methods);
733
+ $intersect = array_intersect(array('__set', '__get', '__unset', '__isset'), $methods);
734
+ if (!empty($intersect)) {
735
+ throw new Exception\InvalidArgumentException(
736
+ "Magic properties are handled by option 'cache_magic_properties'"
737
+ );
738
+ }
739
+ return $methods;
740
+ }
741
+
742
+ /**
743
+ * Create a storage object from a given specification
744
+ *
745
+ * @param array|string|Storage $storage
746
+ * @throws Exception\InvalidArgumentException
747
+ * @return Storage
748
+ */
749
+ protected function storageFactory($storage)
750
+ {
751
+ if (is_array($storage)) {
752
+ $storage = StorageFactory::factory($storage);
753
+ } elseif (is_string($storage)) {
754
+ $storage = StorageFactory::adapterFactory($storage);
755
+ } elseif (!($storage instanceof Storage)) {
756
+ throw new Exception\InvalidArgumentException(
757
+ 'The storage must be an instanceof Zend\Cache\Storage\StorageInterface '
758
+ . 'or an array passed to Zend\Cache\Storage::factory '
759
+ . 'or simply the name of the storage adapter'
760
+ );
761
+ }
762
+
763
+ return $storage;
764
+ }
765
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/PatternFactory.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache;
11
+
12
+ use Traversable;
13
+ use Zend\Stdlib\ArrayUtils;
14
+
15
+ abstract class PatternFactory
16
+ {
17
+ /**
18
+ * The pattern manager
19
+ *
20
+ * @var null|PatternPluginManager
21
+ */
22
+ protected static $plugins = null;
23
+
24
+ /**
25
+ * Instantiate a cache pattern
26
+ *
27
+ * @param string|Pattern\PatternInterface $patternName
28
+ * @param array|Traversable|Pattern\PatternOptions $options
29
+ * @return Pattern\PatternInterface
30
+ * @throws Exception\InvalidArgumentException
31
+ */
32
+ public static function factory($patternName, $options = array())
33
+ {
34
+ if ($options instanceof Traversable) {
35
+ $options = ArrayUtils::iteratorToArray($options);
36
+ }
37
+ if (is_array($options)) {
38
+ $options = new Pattern\PatternOptions($options);
39
+ } elseif (!$options instanceof Pattern\PatternOptions) {
40
+ throw new Exception\InvalidArgumentException(sprintf(
41
+ '%s expects an array, Traversable object, or %s\Pattern\PatternOptions object; received "%s"',
42
+ __METHOD__,
43
+ __NAMESPACE__,
44
+ (is_object($options) ? get_class($options) : gettype($options))
45
+ ));
46
+ }
47
+
48
+ if ($patternName instanceof Pattern\PatternInterface) {
49
+ $patternName->setOptions($options);
50
+ return $patternName;
51
+ }
52
+
53
+ $pattern = static::getPluginManager()->get($patternName);
54
+ $pattern->setOptions($options);
55
+ return $pattern;
56
+ }
57
+
58
+ /**
59
+ * Get the pattern plugin manager
60
+ *
61
+ * @return PatternPluginManager
62
+ */
63
+ public static function getPluginManager()
64
+ {
65
+ if (static::$plugins === null) {
66
+ static::$plugins = new PatternPluginManager();
67
+ }
68
+
69
+ return static::$plugins;
70
+ }
71
+
72
+ /**
73
+ * Set the pattern plugin manager
74
+ *
75
+ * @param PatternPluginManager $plugins
76
+ * @return void
77
+ */
78
+ public static function setPluginManager(PatternPluginManager $plugins)
79
+ {
80
+ static::$plugins = $plugins;
81
+ }
82
+
83
+ /**
84
+ * Reset pattern plugin manager to default
85
+ *
86
+ * @return void
87
+ */
88
+ public static function resetPluginManager()
89
+ {
90
+ static::$plugins = null;
91
+ }
92
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/PatternPluginManager.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache;
11
+
12
+ use Zend\ServiceManager\AbstractPluginManager;
13
+
14
+ /**
15
+ * Plugin manager implementation for cache pattern adapters
16
+ *
17
+ * Enforces that retrieved adapters are instances of
18
+ * Pattern\PatternInterface. Additionally, it registers a number of default
19
+ * patterns available.
20
+ */
21
+ class PatternPluginManager extends AbstractPluginManager
22
+ {
23
+ /**
24
+ * Default set of adapters
25
+ *
26
+ * @var array
27
+ */
28
+ protected $invokableClasses = array(
29
+ 'callback' => 'Zend\Cache\Pattern\CallbackCache',
30
+ 'capture' => 'Zend\Cache\Pattern\CaptureCache',
31
+ 'class' => 'Zend\Cache\Pattern\ClassCache',
32
+ 'object' => 'Zend\Cache\Pattern\ObjectCache',
33
+ 'output' => 'Zend\Cache\Pattern\OutputCache',
34
+ 'page' => 'Zend\Cache\Pattern\PageCache',
35
+ );
36
+
37
+ /**
38
+ * Don't share by default
39
+ *
40
+ * @var array
41
+ */
42
+ protected $shareByDefault = false;
43
+
44
+ /**
45
+ * Validate the plugin
46
+ *
47
+ * Checks that the pattern adapter loaded is an instance of Pattern\PatternInterface.
48
+ *
49
+ * @param mixed $plugin
50
+ * @return void
51
+ * @throws Exception\RuntimeException if invalid
52
+ */
53
+ public function validatePlugin($plugin)
54
+ {
55
+ if ($plugin instanceof Pattern\PatternInterface) {
56
+ // we're okay
57
+ return;
58
+ }
59
+
60
+ throw new Exception\RuntimeException(sprintf(
61
+ 'Plugin of type %s is invalid; must implement %s\Pattern\PatternInterface',
62
+ (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
63
+ __NAMESPACE__
64
+ ));
65
+ }
66
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/README.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Cache Component from ZF2
2
+ ========================
3
+
4
+ This is the Cache component for ZF2.
5
+
6
+ - File issues at https://github.com/zendframework/zf2/issues
7
+ - Create pull requests against https://github.com/zendframework/zf2
8
+ - Documentation is at http://framework.zend.com/docs
9
+
10
+ LICENSE
11
+ -------
12
+
13
+ The files in this archive are released under the [Zend Framework
14
+ license](http://framework.zend.com/license), which is a 3-clause BSD license.
backend/vendor/zendframework/zend-cache/Zend/Cache/Service/StorageCacheAbstractServiceFactory.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Service;
11
+
12
+ use Zend\Cache\StorageFactory;
13
+ use Zend\ServiceManager\AbstractFactoryInterface;
14
+ use Zend\ServiceManager\ServiceLocatorInterface;
15
+
16
+ /**
17
+ * Storage cache factory for multiple caches.
18
+ */
19
+ class StorageCacheAbstractServiceFactory implements AbstractFactoryInterface
20
+ {
21
+ /**
22
+ * @var array
23
+ */
24
+ protected $config;
25
+
26
+ /**
27
+ * Configuration key for cache objects
28
+ *
29
+ * @var string
30
+ */
31
+ protected $configKey = 'caches';
32
+
33
+ /**
34
+ * @param ServiceLocatorInterface $services
35
+ * @param string $name
36
+ * @param string $requestedName
37
+ * @return bool
38
+ */
39
+ public function canCreateServiceWithName(ServiceLocatorInterface $services, $name, $requestedName)
40
+ {
41
+ $config = $this->getConfig($services);
42
+ if (empty($config)) {
43
+ return false;
44
+ }
45
+
46
+ return (isset($config[$requestedName]) && is_array($config[$requestedName]));
47
+ }
48
+
49
+ /**
50
+ * @param ServiceLocatorInterface $services
51
+ * @param string $name
52
+ * @param string $requestedName
53
+ * @return \Zend\Cache\Storage\StorageInterface
54
+ */
55
+ public function createServiceWithName(ServiceLocatorInterface $services, $name, $requestedName)
56
+ {
57
+ $config = $this->getConfig($services);
58
+ $config = $config[$requestedName];
59
+ return StorageFactory::factory($config);
60
+ }
61
+
62
+ /**
63
+ * Retrieve cache configuration, if any
64
+ *
65
+ * @param ServiceLocatorInterface $services
66
+ * @return array
67
+ */
68
+ protected function getConfig(ServiceLocatorInterface $services)
69
+ {
70
+ if ($this->config !== null) {
71
+ return $this->config;
72
+ }
73
+
74
+ if (!$services->has('Config')) {
75
+ $this->config = array();
76
+ return $this->config;
77
+ }
78
+
79
+ $config = $services->get('Config');
80
+ if (!isset($config[$this->configKey])) {
81
+ $this->config = array();
82
+ return $this->config;
83
+ }
84
+
85
+ $this->config = $config[$this->configKey];
86
+ return $this->config;
87
+ }
88
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Service/StorageCacheFactory.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Service;
11
+
12
+ use Zend\Cache\StorageFactory;
13
+ use Zend\ServiceManager\FactoryInterface;
14
+ use Zend\ServiceManager\ServiceLocatorInterface;
15
+
16
+ /**
17
+ * Storage cache factory.
18
+ */
19
+ class StorageCacheFactory implements FactoryInterface
20
+ {
21
+ public function createService(ServiceLocatorInterface $serviceLocator)
22
+ {
23
+ // Configure the cache
24
+ $config = $serviceLocator->get('Config');
25
+ $cacheConfig = isset($config['cache']) ? $config['cache'] : array();
26
+ $cache = StorageFactory::factory($cacheConfig);
27
+
28
+ return $cache;
29
+ }
30
+ }
backend/vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/AbstractAdapter.php ADDED
@@ -0,0 +1,1580 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework (http://framework.zend.com/)
4
+ *
5
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
6
+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
7
+ * @license http://framework.zend.com/license/new-bsd New BSD License
8
+ */
9
+
10
+ namespace Zend\Cache\Storage\Adapter;
11
+
12
+ use ArrayObject;
13
+ use SplObjectStorage;
14
+ use stdClass;
15
+ use Traversable;
16
+ use Zend\Cache\Exception;
17
+ use Zend\Cache\Storage\Capabilities;
18
+ use Zend\Cache\Storage\Event;
19
+ use Zend\Cache\Storage\ExceptionEvent;
20
+ use Zend\Cache\Storage\Plugin;
21
+ use Zend\Cache\Storage\PostEvent;
22
+ use Zend\Cache\Storage\StorageInterface;
23
+ use Zend\EventManager\EventManager;
24
+ use Zend\EventManager\EventManagerInterface;
25
+ use Zend\EventManager\EventsCapableInterface;
26
+
27
+ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterface
28
+ {
29
+ /**
30
+ * The used EventManager if any
31
+ *
32
+ * @var null|EventManagerInterface
33
+ */
34
+ protected $events = null;
35
+
36
+ /**
37
+ * Event handles of this adapter
38
+ * @var array
39
+ */
40
+ protected $eventHandles = array();
41
+
42
+ /**
43
+ * The plugin registry
44
+ *
45
+ * @var SplObjectStorage Registered plugins
46
+ */
47
+ protected $pluginRegistry;
48
+
49
+ /**
50
+ * Capabilities of this adapter
51
+ *
52
+ * @var null|Capabilities
53
+ */
54
+ protected $capabilities = null;
55
+
56
+ /**
57
+ * Marker to change capabilities
58
+ *
59
+ * @var null|object
60
+ */
61
+ protected $capabilityMarker;
62
+
63
+ /**
64
+ * options
65
+ *
66
+ * @var mixed
67
+ */
68
+ protected $options;
69
+
70
+ /**
71
+ * Constructor
72
+ *
73
+ * @param null|array|Traversable|AdapterOptions $options
74
+ * @throws Exception\ExceptionInterface
75
+ */
76
+ public function __construct($options = null)
77
+ {
78
+ if ($options) {
79
+ $this->setOptions($options);
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Destructor
85
+ *
86
+ * detach all registered plugins to free
87
+ * event handles of event manager
88
+ *
89
+ * @return void
90
+ */
91
+ public function __destruct()
92
+ {
93
+ foreach ($this->getPluginRegistry() as $plugin) {
94
+ $this->removePlugin($plugin);
95
+ }
96
+
97
+ if ($this->eventHandles) {
98
+ $events = $this->getEventManager();
99
+ foreach ($this->eventHandles as $handle) {
100
+ $events->detach($handle);
101
+ }
102
+ }
103
+ }
104
+
105
+ /* configuration */
106
+
107
+ /**
108
+ * Set options.
109
+ *
110
+ * @param array|Traversable|AdapterOptions $options
111
+ * @return AbstractAdapter
112
+ * @see getOptions()
113
+ */
114
+ public function setOptions($options)
115
+ {
116
+ if ($this->options !== $options) {
117
+ if (!$options instanceof AdapterOptions) {
118
+ $options = new AdapterOptions($options);
119
+ }
120
+
121
+ if ($this->options) {
122
+ $this->options->setAdapter(null);
123
+ }
124
+ $options->setAdapter($this);
125
+ $this->options = $options;
126
+
127
+ $event = new Event('option', $this, new ArrayObject($options->toArray()));
128
+ $this->getEventManager()->trigger($event);
129
+ }
130
+ return $this;
131
+ }
132
+
133
+ /**
134
+ * Get options.
135
+ *
136
+ * @return AdapterOptions
137
+ * @see setOptions()
138
+ */
139
+ public function getOptions()
140
+ {
141
+ if (!$this->options) {
142
+ $this->setOptions(new AdapterOptions());
143
+ }
144
+ return $this->options;
145
+ }
146
+
147
+ /**
148
+ * Enable/Disable caching.
149
+ *
150
+ * Alias of setWritable and setReadable.
151
+ *
152
+ * @see setWritable()
153
+ * @see setReadable()
154
+ * @param bool $flag
155
+ * @return AbstractAdapter
156
+ */
157
+ public function setCaching($flag)
158
+ {
159
+ $flag = (bool) $flag;
160
+ $options = $this->getOptions();
161
+ $options->setWritable($flag);
162
+ $options->setReadable($flag);
163
+ return $this;
164
+ }
165
+
166
+ /**
167
+ * Get caching enabled.
168
+ *
169
+ * Alias of getWritable and getReadable.
170
+ *
171
+ * @see getWritable()
172
+ * @see getReadable()
173
+ * @return bool
174
+ */
175
+ public function getCaching()
176
+ {
177
+ $options = $this->getOptions();
178
+ return ($options->getWritable() && $options->getReadable());
179
+ }
180
+
181
+ /* Event/Plugin handling */
182
+
183
+ /**
184
+ * Get the event manager
185
+ *
186
+ * @return EventManagerInterface
187
+ */
188
+ public function getEventManager()
189
+ {
190
+ if ($this->events === null) {
191
+ $this->events = new EventManager(array(__CLASS__, get_class($this)));
192
+ }
193
+ return $this->events;
194
+ }
195
+
196
+ /**
197
+ * Trigger a pre event and return the event response collection
198
+ *
199
+ * @param string $eventName
200
+ * @param ArrayObject $args
201
+ * @return \Zend\EventManager\ResponseCollection All handler return values
202
+ */
203
+ protected function triggerPre($eventName, ArrayObject $args)
204
+ {
205
+ return $this->getEventManager()->trigger(new Event($eventName . '.pre', $this, $args));
206
+ }
207
+
208
+ /**
209
+ * Triggers the PostEvent and return the result value.
210
+ *
211
+ * @param string $eventName
212
+ * @param ArrayObject $args
213
+ * @param mixed $result
214
+ * @return mixed
215
+ */
216
+ protected function triggerPost($eventName, ArrayObject $args, & $result)
217
+ {
218
+ $postEvent = new PostEvent($eventName . '.post', $this, $args, $result);
219
+ $eventRs = $this->getEventManager()->trigger($postEvent);
220
+ if ($eventRs->stopped()) {
221
+ return $eventRs->last();
222
+ }
223
+
224
+ return $postEvent->getResult();
225
+ }
226
+
227
+ /**
228
+ * Trigger an exception event
229
+ *
230
+ * If the ExceptionEvent has the flag "throwException" enabled throw the
231
+ * exception after trigger else return the result.
232
+ *
233
+ * @param string $eventName
234
+ * @param ArrayObject $args
235
+ * @param mixed $result
236
+ * @param \Exception $exception
237
+ * @throws Exception\ExceptionInterface
238
+ * @return mixed
239
+ */
240
+ protected function triggerException($eventName, ArrayObject $args, & $result, \Exception $exception)
241
+ {
242
+ $exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $result, $exception);
243
+ $eventRs = $this->getEventManager()->trigger($exceptionEvent);
244
+
245
+ if ($exceptionEvent->getThrowException()) {
246
+ throw $exceptionEvent->getException();
247
+ }
248
+
249
+ if ($eventRs->stopped()) {
250
+ return $eventRs->last();
251
+ }
252
+
253
+ return $exceptionEvent->getResult();
254
+ }
255
+
256
+ /**
257
+ * Check if a plugin is registered
258
+ *
259
+ * @param Plugin\PluginInterface $plugin
260
+ * @return bool
261
+ */
262
+ public function hasPlugin(Plugin\PluginInterface $plugin)
263
+ {
264
+ $registry = $this->getPluginRegistry();
265
+ return $registry->contains($plugin);
266
+ }
267
+
268
+ /**
269
+ * Register a plugin
270
+ *
271
+ * @param Plugin\PluginInterface $plugin
272
+ * @param int $priority
273
+ * @return AbstractAdapter Fluent interface
274
+ * @throws Exception\LogicException
275
+ */
276
+ public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1)
277
+ {
278
+ $registry = $this->getPluginRegistry();
279
+ if ($registry->contains($plugin)) {
280
+ throw new Exception\LogicException(sprintf(
281
+ 'Plugin of type "%s" already registered',
282
+ get_class($plugin)
283
+ ));
284
+ }
285
+
286
+ $plugin->attach($this->getEventManager(), $priority);
287
+ $registry->attach($plugin);
288
+
289
+ return $this;
290
+ }
291
+
292
+ /**
293
+ * Unregister an already registered plugin
294
+ *
295
+ * @param Plugin\PluginInterface $plugin
296
+ * @return AbstractAdapter Fluent interface
297
+ * @throws Exception\LogicException
298
+ */
299
+ public function removePlugin(Plugin\PluginInterface $plugin)
300
+ {
301
+ $registry = $this->getPluginRegistry();
302
+ if ($registry->contains($plugin)) {
303
+ $plugin->detach($this->getEventManager());
304
+ $registry->detach($plugin);
305
+ }
306
+ return $this;
307
+ }
308
+
309
+ /**
310
+ * Return registry of plugins
311
+ *
312
+ * @return SplObjectStorage
313
+ */
314
+ public function getPluginRegistry()
315
+ {
316
+ if (!$this->pluginRegistry instanceof SplObjectStorage) {
317
+ $this->pluginRegistry = new SplObjectStorage();
318
+ }
319
+ return $this->pluginRegistry;
320
+ }
321
+
322
+ /* reading */
323
+
324
+ /**
325
+ * Get an item.
326
+ *
327
+ * @param string $key
328
+ * @param bool $success
329
+ * @param mixed $casToken
330
+ * @return mixed Data on success, null on failure
331
+ * @throws Exception\ExceptionInterface
332
+ *
333
+ * @triggers getItem.pre(PreEvent)
334
+ * @triggers getItem.post(PostEvent)
335
+ * @triggers getItem.exception(ExceptionEvent)
336
+ */
337
+ public function getItem($key, & $success = null, & $casToken = null)
338
+ {
339
+ if (!$this->getOptions()->getReadable()) {
340
+ $success = false;
341
+ return null;
342
+ }
343
+
344
+ $this->normalizeKey($key);
345
+
346
+ $argn = func_num_args();
347
+ $args = array(
348
+ 'key' => & $key,
349
+ );
350
+ if ($argn > 1) {
351
+ $args['success'] = & $success;
352
+ }
353
+ if ($argn > 2) {
354
+ $args['casToken'] = & $casToken;
355
+ }
356
+ $args = new ArrayObject($args);
357
+
358
+ try {
359
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
360
+ if ($eventRs->stopped()) {
361
+ return $eventRs->last();
362
+ }
363
+
364
+ if ($args->offsetExists('success') && $args->offsetExists('casToken')) {
365
+ $result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']);
366
+ } elseif ($args->offsetExists('success')) {
367
+ $result = $this->internalGetItem($args['key'], $args['success']);
368
+ } else {
369
+ $result = $this->internalGetItem($args['key']);
370
+ }
371
+ return $this->triggerPost(__FUNCTION__, $args, $result);
372
+ } catch (\Exception $e) {
373
+ $result = false;
374
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Internal method to get an item.
380
+ *
381
+ * @param string $normalizedKey
382
+ * @param bool $success
383
+ * @param mixed $casToken
384
+ * @return mixed Data on success, null on failure
385
+ * @throws Exception\ExceptionInterface
386
+ */
387
+ abstract protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null);
388
+
389
+ /**
390
+ * Get multiple items.
391
+ *
392
+ * @param array $keys
393
+ * @return array Associative array of keys and values
394
+ * @throws Exception\ExceptionInterface
395
+ *
396
+ * @triggers getItems.pre(PreEvent)
397
+ * @triggers getItems.post(PostEvent)
398
+ * @triggers getItems.exception(ExceptionEvent)
399
+ */
400
+ public function getItems(array $keys)
401
+ {
402
+ if (!$this->getOptions()->getReadable()) {
403
+ return array();
404
+ }
405
+
406
+ $this->normalizeKeys($keys);
407
+ $args = new ArrayObject(array(
408
+ 'keys' => & $keys,
409
+ ));
410
+
411
+ try {
412
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
413
+ if ($eventRs->stopped()) {
414
+ return $eventRs->last();
415
+ }
416
+
417
+ $result = $this->internalGetItems($args['keys']);
418
+ return $this->triggerPost(__FUNCTION__, $args, $result);
419
+ } catch (\Exception $e) {
420
+ $result = array();
421
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
422
+ }
423
+ }
424
+
425
+ /**
426
+ * Internal method to get multiple items.
427
+ *
428
+ * @param array $normalizedKeys
429
+ * @return array Associative array of keys and values
430
+ * @throws Exception\ExceptionInterface
431
+ */
432
+ protected function internalGetItems(array & $normalizedKeys)
433
+ {
434
+ $success = null;
435
+ $result = array();
436
+ foreach ($normalizedKeys as $normalizedKey) {
437
+ $value = $this->internalGetItem($normalizedKey, $success);
438
+ if ($success) {
439
+ $result[$normalizedKey] = $value;
440
+ }
441
+ }
442
+
443
+ return $result;
444
+ }
445
+
446
+ /**
447
+ * Test if an item exists.
448
+ *
449
+ * @param string $key
450
+ * @return bool
451
+ * @throws Exception\ExceptionInterface
452
+ *
453
+ * @triggers hasItem.pre(PreEvent)
454
+ * @triggers hasItem.post(PostEvent)
455
+ * @triggers hasItem.exception(ExceptionEvent)
456
+ */
457
+ public function hasItem($key)
458
+ {
459
+ if (!$this->getOptions()->getReadable()) {
460
+ return false;
461
+ }
462
+
463
+ $this->normalizeKey($key);
464
+ $args = new ArrayObject(array(
465
+ 'key' => & $key,
466
+ ));
467
+
468
+ try {
469
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
470
+ if ($eventRs->stopped()) {
471
+ return $eventRs->last();
472
+ }
473
+
474
+ $result = $this->internalHasItem($args['key']);
475
+ return $this->triggerPost(__FUNCTION__, $args, $result);
476
+ } catch (\Exception $e) {
477
+ $result = false;
478
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Internal method to test if an item exists.
484
+ *
485
+ * @param string $normalizedKey
486
+ * @return bool
487
+ * @throws Exception\ExceptionInterface
488
+ */
489
+ protected function internalHasItem(& $normalizedKey)
490
+ {
491
+ $success = null;
492
+ $this->internalGetItem($normalizedKey, $success);
493
+ return $success;
494
+ }
495
+
496
+ /**
497
+ * Test multiple items.
498
+ *
499
+ * @param array $keys
500
+ * @return array Array of found keys
501
+ * @throws Exception\ExceptionInterface
502
+ *
503
+ * @triggers hasItems.pre(PreEvent)
504
+ * @triggers hasItems.post(PostEvent)
505
+ * @triggers hasItems.exception(ExceptionEvent)
506
+ */
507
+ public function hasItems(array $keys)
508
+ {
509
+ if (!$this->getOptions()->getReadable()) {
510
+ return array();
511
+ }
512
+
513
+ $this->normalizeKeys($keys);
514
+ $args = new ArrayObject(array(
515
+ 'keys' => & $keys,
516
+ ));
517
+
518
+ try {
519
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
520
+ if ($eventRs->stopped()) {
521
+ return $eventRs->last();
522
+ }
523
+
524
+ $result = $this->internalHasItems($args['keys']);
525
+ return $this->triggerPost(__FUNCTION__, $args, $result);
526
+ } catch (\Exception $e) {
527
+ $result = array();
528
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
529
+ }
530
+ }
531
+
532
+ /**
533
+ * Internal method to test multiple items.
534
+ *
535
+ * @param array $normalizedKeys
536
+ * @return array Array of found keys
537
+ * @throws Exception\ExceptionInterface
538
+ */
539
+ protected function internalHasItems(array & $normalizedKeys)
540
+ {
541
+ $result = array();
542
+ foreach ($normalizedKeys as $normalizedKey) {
543
+ if ($this->internalHasItem($normalizedKey)) {
544
+ $result[] = $normalizedKey;
545
+ }
546
+ }
547
+ return $result;
548
+ }
549
+
550
+ /**
551
+ * Get metadata of an item.
552
+ *
553
+ * @param string $key
554
+ * @return array|bool Metadata on success, false on failure
555
+ * @throws Exception\ExceptionInterface
556
+ *
557
+ * @triggers getMetadata.pre(PreEvent)
558
+ * @triggers getMetadata.post(PostEvent)
559
+ * @triggers getMetadata.exception(ExceptionEvent)
560
+ */
561
+ public function getMetadata($key)
562
+ {
563
+ if (!$this->getOptions()->getReadable()) {
564
+ return false;
565
+ }
566
+
567
+ $this->normalizeKey($key);
568
+ $args = new ArrayObject(array(
569
+ 'key' => & $key,
570
+ ));
571
+
572
+ try {
573
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
574
+ if ($eventRs->stopped()) {
575
+ return $eventRs->last();
576
+ }
577
+
578
+ $result = $this->internalGetMetadata($args['key']);
579
+ return $this->triggerPost(__FUNCTION__, $args, $result);
580
+ } catch (\Exception $e) {
581
+ $result = false;
582
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
583
+ }
584
+ }
585
+
586
+ /**
587
+ * Internal method to get metadata of an item.
588
+ *
589
+ * @param string $normalizedKey
590
+ * @return array|bool Metadata on success, false on failure
591
+ * @throws Exception\ExceptionInterface
592
+ */
593
+ protected function internalGetMetadata(& $normalizedKey)
594
+ {
595
+ if (!$this->internalHasItem($normalizedKey)) {
596
+ return false;
597
+ }
598
+
599
+ return array();
600
+ }
601
+
602
+ /**
603
+ * Get multiple metadata
604
+ *
605
+ * @param array $keys
606
+ * @return array Associative array of keys and metadata
607
+ * @throws Exception\ExceptionInterface
608
+ *
609
+ * @triggers getMetadatas.pre(PreEvent)
610
+ * @triggers getMetadatas.post(PostEvent)
611
+ * @triggers getMetadatas.exception(ExceptionEvent)
612
+ */
613
+ public function getMetadatas(array $keys)
614
+ {
615
+ if (!$this->getOptions()->getReadable()) {
616
+ return array();
617
+ }
618
+
619
+ $this->normalizeKeys($keys);
620
+ $args = new ArrayObject(array(
621
+ 'keys' => & $keys,
622
+ ));
623
+
624
+ try {
625
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
626
+ if ($eventRs->stopped()) {
627
+ return $eventRs->last();
628
+ }
629
+
630
+ $result = $this->internalGetMetadatas($args['keys']);
631
+ return $this->triggerPost(__FUNCTION__, $args, $result);
632
+ } catch (\Exception $e) {
633
+ $result = array();
634
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
635
+ }
636
+ }
637
+
638
+ /**
639
+ * Internal method to get multiple metadata
640
+ *
641
+ * @param array $normalizedKeys
642
+ * @return array Associative array of keys and metadata
643
+ * @throws Exception\ExceptionInterface
644
+ */
645
+ protected function internalGetMetadatas(array & $normalizedKeys)
646
+ {
647
+ $result = array();
648
+ foreach ($normalizedKeys as $normalizedKey) {
649
+ $metadata = $this->internalGetMetadata($normalizedKey);
650
+ if ($metadata !== false) {
651
+ $result[$normalizedKey] = $metadata;
652
+ }
653
+ }
654
+ return $result;
655
+ }
656
+
657
+ /* writing */
658
+
659
+ /**
660
+ * Store an item.
661
+ *
662
+ * @param string $key
663
+ * @param mixed $value
664
+ * @return bool
665
+ * @throws Exception\ExceptionInterface
666
+ *
667
+ * @triggers setItem.pre(PreEvent)
668
+ * @triggers setItem.post(PostEvent)
669
+ * @triggers setItem.exception(ExceptionEvent)
670
+ */
671
+ public function setItem($key, $value)
672
+ {
673
+ if (!$this->getOptions()->getWritable()) {
674
+ return false;
675
+ }
676
+
677
+ $this->normalizeKey($key);
678
+ $args = new ArrayObject(array(
679
+ 'key' => & $key,
680
+ 'value' => & $value,
681
+ ));
682
+
683
+ try {
684
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
685
+ if ($eventRs->stopped()) {
686
+ return $eventRs->last();
687
+ }
688
+
689
+ $result = $this->internalSetItem($args['key'], $args['value']);
690
+ return $this->triggerPost(__FUNCTION__, $args, $result);
691
+ } catch (\Exception $e) {
692
+ $result = false;
693
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
694
+ }
695
+ }
696
+
697
+ /**
698
+ * Internal method to store an item.
699
+ *
700
+ * @param string $normalizedKey
701
+ * @param mixed $value
702
+ * @return bool
703
+ * @throws Exception\ExceptionInterface
704
+ */
705
+ abstract protected function internalSetItem(& $normalizedKey, & $value);
706
+
707
+ /**
708
+ * Store multiple items.
709
+ *
710
+ * @param array $keyValuePairs
711
+ * @return array Array of not stored keys
712
+ * @throws Exception\ExceptionInterface
713
+ *
714
+ * @triggers setItems.pre(PreEvent)
715
+ * @triggers setItems.post(PostEvent)
716
+ * @triggers setItems.exception(ExceptionEvent)
717
+ */
718
+ public function setItems(array $keyValuePairs)
719
+ {
720
+ if (!$this->getOptions()->getWritable()) {
721
+ return array_keys($keyValuePairs);
722
+ }
723
+
724
+ $this->normalizeKeyValuePairs($keyValuePairs);
725
+ $args = new ArrayObject(array(
726
+ 'keyValuePairs' => & $keyValuePairs,
727
+ ));
728
+
729
+ try {
730
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
731
+ if ($eventRs->stopped()) {
732
+ return $eventRs->last();
733
+ }
734
+
735
+ $result = $this->internalSetItems($args['keyValuePairs']);
736
+ return $this->triggerPost(__FUNCTION__, $args, $result);
737
+ } catch (\Exception $e) {
738
+ $result = array_keys($keyValuePairs);
739
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
740
+ }
741
+ }
742
+
743
+ /**
744
+ * Internal method to store multiple items.
745
+ *
746
+ * @param array $normalizedKeyValuePairs
747
+ * @return array Array of not stored keys
748
+ * @throws Exception\ExceptionInterface
749
+ */
750
+ protected function internalSetItems(array & $normalizedKeyValuePairs)
751
+ {
752
+ $failedKeys = array();
753
+ foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
754
+ if (!$this->internalSetItem($normalizedKey, $value)) {
755
+ $failedKeys[] = $normalizedKey;
756
+ }
757
+ }
758
+ return $failedKeys;
759
+ }
760
+
761
+ /**
762
+ * Add an item.
763
+ *
764
+ * @param string $key
765
+ * @param mixed $value
766
+ * @return bool
767
+ * @throws Exception\ExceptionInterface
768
+ *
769
+ * @triggers addItem.pre(PreEvent)
770
+ * @triggers addItem.post(PostEvent)
771
+ * @triggers addItem.exception(ExceptionEvent)
772
+ */
773
+ public function addItem($key, $value)
774
+ {
775
+ if (!$this->getOptions()->getWritable()) {
776
+ return false;
777
+ }
778
+
779
+ $this->normalizeKey($key);
780
+ $args = new ArrayObject(array(
781
+ 'key' => & $key,
782
+ 'value' => & $value,
783
+ ));
784
+
785
+ try {
786
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
787
+ if ($eventRs->stopped()) {
788
+ return $eventRs->last();
789
+ }
790
+
791
+ $result = $this->internalAddItem($args['key'], $args['value']);
792
+ return $this->triggerPost(__FUNCTION__, $args, $result);
793
+ } catch (\Exception $e) {
794
+ $result = false;
795
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
796
+ }
797
+ }
798
+
799
+ /**
800
+ * Internal method to add an item.
801
+ *
802
+ * @param string $normalizedKey
803
+ * @param mixed $value
804
+ * @return bool
805
+ * @throws Exception\ExceptionInterface
806
+ */
807
+ protected function internalAddItem(& $normalizedKey, & $value)
808
+ {
809
+ if ($this->internalHasItem($normalizedKey)) {
810
+ return false;
811
+ }
812
+ return $this->internalSetItem($normalizedKey, $value);
813
+ }
814
+
815
+ /**
816
+ * Add multiple items.
817
+ *
818
+ * @param array $keyValuePairs
819
+ * @return array Array of not stored keys
820
+ * @throws Exception\ExceptionInterface
821
+ *
822
+ * @triggers addItems.pre(PreEvent)
823
+ * @triggers addItems.post(PostEvent)
824
+ * @triggers addItems.exception(ExceptionEvent)
825
+ */
826
+ public function addItems(array $keyValuePairs)
827
+ {
828
+ if (!$this->getOptions()->getWritable()) {
829
+ return array_keys($keyValuePairs);
830
+ }
831
+
832
+ $this->normalizeKeyValuePairs($keyValuePairs);
833
+ $args = new ArrayObject(array(
834
+ 'keyValuePairs' => & $keyValuePairs,
835
+ ));
836
+
837
+ try {
838
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
839
+ if ($eventRs->stopped()) {
840
+ return $eventRs->last();
841
+ }
842
+
843
+ $result = $this->internalAddItems($args['keyValuePairs']);
844
+ return $this->triggerPost(__FUNCTION__, $args, $result);
845
+ } catch (\Exception $e) {
846
+ $result = array_keys($keyValuePairs);
847
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
848
+ }
849
+ }
850
+
851
+ /**
852
+ * Internal method to add multiple items.
853
+ *
854
+ * @param array $normalizedKeyValuePairs
855
+ * @return array Array of not stored keys
856
+ * @throws Exception\ExceptionInterface
857
+ */
858
+ protected function internalAddItems(array & $normalizedKeyValuePairs)
859
+ {
860
+ $result = array();
861
+ foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
862
+ if (!$this->internalAddItem($normalizedKey, $value)) {
863
+ $result[] = $normalizedKey;
864
+ }
865
+ }
866
+ return $result;
867
+ }
868
+
869
+ /**
870
+ * Replace an existing item.
871
+ *
872
+ * @param string $key
873
+ * @param mixed $value
874
+ * @return bool
875
+ * @throws Exception\ExceptionInterface
876
+ *
877
+ * @triggers replaceItem.pre(PreEvent)
878
+ * @triggers replaceItem.post(PostEvent)
879
+ * @triggers replaceItem.exception(ExceptionEvent)
880
+ */
881
+ public function replaceItem($key, $value)
882
+ {
883
+ if (!$this->getOptions()->getWritable()) {
884
+ return false;
885
+ }
886
+
887
+ $this->normalizeKey($key);
888
+ $args = new ArrayObject(array(
889
+ 'key' => & $key,
890
+ 'value' => & $value,
891
+ ));
892
+
893
+ try {
894
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
895
+ if ($eventRs->stopped()) {
896
+ return $eventRs->last();
897
+ }
898
+
899
+ $result = $this->internalReplaceItem($args['key'], $args['value']);
900
+ return $this->triggerPost(__FUNCTION__, $args, $result);
901
+ } catch (\Exception $e) {
902
+ $result = false;
903
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
904
+ }
905
+ }
906
+
907
+ /**
908
+ * Internal method to replace an existing item.
909
+ *
910
+ * @param string $normalizedKey
911
+ * @param mixed $value
912
+ * @return bool
913
+ * @throws Exception\ExceptionInterface
914
+ */
915
+ protected function internalReplaceItem(& $normalizedKey, & $value)
916
+ {
917
+ if (!$this->internalhasItem($normalizedKey)) {
918
+ return false;
919
+ }
920
+
921
+ return $this->internalSetItem($normalizedKey, $value);
922
+ }
923
+
924
+ /**
925
+ * Replace multiple existing items.
926
+ *
927
+ * @param array $keyValuePairs
928
+ * @return array Array of not stored keys
929
+ * @throws Exception\ExceptionInterface
930
+ *
931
+ * @triggers replaceItems.pre(PreEvent)
932
+ * @triggers replaceItems.post(PostEvent)
933
+ * @triggers replaceItems.exception(ExceptionEvent)
934
+ */
935
+ public function replaceItems(array $keyValuePairs)
936
+ {
937
+ if (!$this->getOptions()->getWritable()) {
938
+ return array_keys($keyValuePairs);
939
+ }
940
+
941
+ $this->normalizeKeyValuePairs($keyValuePairs);
942
+ $args = new ArrayObject(array(
943
+ 'keyValuePairs' => & $keyValuePairs,
944
+ ));
945
+
946
+ try {
947
+ $eventRs = $this->triggerPre(__FUNCTION__, $args);
948
+ if ($eventRs->stopped()) {
949
+ return $eventRs->last();
950
+ }
951
+
952
+ $result = $this->internalReplaceItems($args['keyValuePairs']);
953
+ return $this->triggerPost(__FUNCTION__, $args, $result);
954
+ } catch (\Exception $e) {
955
+ $result = array_keys($keyValuePairs);
956
+ return $this->triggerException(__FUNCTION__, $args, $result, $e);
957
+ }
958
+ }
959
+
960
+ /**
961
+ * Internal method to replace multiple existing items.
962
+ *
963
+ * @param array $normalizedKeyValuePairs
964
+ * @return array Array of not stored keys
965
+ * @throws Exception\ExceptionInterface
966
+ */
967
+ protected function internalReplaceItems(array & $normalizedKeyValuePairs)
968
+ {
969
+ $result = array();
970
+ foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
971
+ if (!$this->internalReplaceItem($normalizedKey, $value)) {
972
+ $result[] = $normalizedKey