Mollie Payments for WooCommerce - Version 5.4.1

Version Description

  • 05-12-2019 =

  • Fix - Mollie Components request multiple times the merchant profile ID via API

Download this release

Release Info

Developer wido
Plugin Icon wp plugin Mollie Payments for WooCommerce
Version 5.4.1
Comparing to
See all releases

Code changes from version 5.4.0 to 5.4.1

inc/utils.php CHANGED
@@ -49,7 +49,7 @@ function merchantProfile()
49
  {
50
  static $profile = null;
51
 
52
- if (null === $profile) {
53
  $isTestMode = isTestModeEnabled();
54
 
55
  $apiHelper = Mollie_WC_Plugin::getApiHelper();
@@ -67,9 +67,31 @@ function merchantProfile()
67
  */
68
  function merchantProfileId()
69
  {
70
- $merchantProfile = merchantProfile();
 
71
 
72
- return isset($merchantProfile->id) ? $merchantProfile->id : 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  }
74
 
75
  /**
49
  {
50
  static $profile = null;
51
 
52
+ if ($profile === null) {
53
  $isTestMode = isTestModeEnabled();
54
 
55
  $apiHelper = Mollie_WC_Plugin::getApiHelper();
67
  */
68
  function merchantProfileId()
69
  {
70
+ static $merchantProfileId = null;
71
+ $merchantProfileIdOptionKey = Mollie_WC_Plugin::PLUGIN_ID . '_merchant_profile_id';
72
 
73
+ if ($merchantProfileId === null) {
74
+ $merchantProfileId = get_option($merchantProfileIdOptionKey, '');
75
+
76
+ /*
77
+ * Try to retrieve the merchant profile ID from an Api Request if not stored already,
78
+ * then store it into the database
79
+ */
80
+ if (!$merchantProfileId) {
81
+ try {
82
+ $merchantProfile = merchantProfile();
83
+ $merchantProfileId = isset($merchantProfile->id) ? $merchantProfile->id : '';
84
+ } catch (ApiException $exception) {
85
+ $merchantProfileId = '';
86
+ }
87
+
88
+ if ($merchantProfileId) {
89
+ update_option($merchantProfileIdOptionKey, $merchantProfileId, false);
90
+ }
91
+ }
92
+ }
93
+
94
+ return $merchantProfileId;
95
  }
96
 
97
  /**
mollie-payments-for-woocommerce.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Mollie Payments for WooCommerce
4
  * Plugin URI: https://www.mollie.com
5
  * Description: Accept payments in WooCommerce with the official Mollie plugin
6
- * Version: 5.4.0
7
  * Author: Mollie
8
  * Author URI: https://www.mollie.com
9
  * Requires at least: 3.8
3
  * Plugin Name: Mollie Payments for WooCommerce
4
  * Plugin URI: https://www.mollie.com
5
  * Description: Accept payments in WooCommerce with the official Mollie plugin
6
+ * Version: 5.4.1
7
  * Author: Mollie
8
  * Author URI: https://www.mollie.com
9
  * Requires at least: 3.8
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: daanvm, danielhuesken, davdebcom, dinamiko, inpsyde, l.vangunst, n
3
  Tags: mollie, payments, payment gateway, woocommerce, credit card, ideal, bancontact, klarna, sofort, giropay, woocommerce subscriptions
4
  Requires at least: 3.8
5
  Tested up to: 5.3
6
- Stable tag: 5.4.0
7
  Requires PHP: 5.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -181,6 +181,10 @@ Automatic updates should work like a charm; as always though, ensure you backup
181
 
182
  == Changelog ==
183
 
 
 
 
 
184
  = 5.4.0 - 04-12-2019 =
185
 
186
  * Fix - Apple Pay Gateway is removed from available gateways during WooCommerce Api calls
3
  Tags: mollie, payments, payment gateway, woocommerce, credit card, ideal, bancontact, klarna, sofort, giropay, woocommerce subscriptions
4
  Requires at least: 3.8
5
  Tested up to: 5.3
6
+ Stable tag: 5.4.1
7
  Requires PHP: 5.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
181
 
182
  == Changelog ==
183
 
184
+ = 5.4.1 - 05-12-2019 =
185
+
186
+ * Fix - Mollie Components request multiple times the merchant profile ID via API
187
+
188
  = 5.4.0 - 04-12-2019 =
189
 
190
  * Fix - Apple Pay Gateway is removed from available gateways during WooCommerce Api calls
src/Mollie/WC/Helper/Settings.php CHANGED
@@ -1,4 +1,7 @@
1
  <?php
 
 
 
2
  class Mollie_WC_Helper_Settings
3
  {
4
  const FILTER_ALLOWED_LANGUAGE_CODE_SETTING = 'mollie.allowed_language_code_setting';
@@ -51,7 +54,14 @@ class Mollie_WC_Helper_Settings
51
  {
52
  $setting_id = $test_mode ? 'test_api_key' : 'live_api_key';
53
 
54
- return trim(get_option($this->getSettingId($setting_id)));
 
 
 
 
 
 
 
55
  }
56
 
57
  /**
@@ -133,11 +143,37 @@ class Mollie_WC_Helper_Settings
133
  /**
134
  * @return string
135
  */
136
- public function getLogsUrl ()
137
  {
138
  return admin_url('admin.php?page=wc-status&tab=logs');
139
  }
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  /**
142
  * Get plugin status
143
  *
@@ -146,16 +182,18 @@ class Mollie_WC_Helper_Settings
146
  *
147
  * @return string
148
  */
149
- protected function getPluginStatus ()
150
  {
151
  $status = Mollie_WC_Plugin::getStatusHelper();
152
 
153
- if (!$status->isCompatible())
154
- {
155
  // Just stop here!
156
  return ''
157
  . '<div class="notice notice-error">'
158
- . '<p><strong>' . __('Error', 'mollie-payments-for-woocommerce') . ':</strong> ' . implode('<br/>', $status->getErrors())
 
 
 
159
  . '</p></div>';
160
  }
161
 
1
  <?php
2
+
3
+ use Mollie\Api\Exceptions\ApiException;
4
+
5
  class Mollie_WC_Helper_Settings
6
  {
7
  const FILTER_ALLOWED_LANGUAGE_CODE_SETTING = 'mollie.allowed_language_code_setting';
54
  {
55
  $setting_id = $test_mode ? 'test_api_key' : 'live_api_key';
56
 
57
+ $apiKeyId = $this->getSettingId($setting_id);
58
+ $apiKey = get_option($apiKeyId);
59
+
60
+ if (!$apiKey && is_admin()) {
61
+ $apiKey = filter_input(INPUT_POST, $apiKeyId, FILTER_SANITIZE_STRING);
62
+ }
63
+
64
+ return trim($apiKey);
65
  }
66
 
67
  /**
143
  /**
144
  * @return string
145
  */
146
+ public function getLogsUrl()
147
  {
148
  return admin_url('admin.php?page=wc-status&tab=logs');
149
  }
150
 
151
+ public function updateMerchantIdOnApiKeyChanges($optionValue, $optionName)
152
+ {
153
+ $optionId = isset($optionName['id']) ? $optionName['id'] : '';
154
+ $allowedOptionsId = [
155
+ $this->getSettingId('live_api_key'),
156
+ $this->getSettingId('test_api_key'),
157
+ ];
158
+
159
+ if (!in_array($optionId, $allowedOptionsId, true)) {
160
+ return $optionValue;
161
+ }
162
+
163
+ $merchantProfileIdOptionKey = Mollie_WC_Plugin::PLUGIN_ID . '_merchant_profile_id';
164
+
165
+ try {
166
+ $merchantProfile = merchantProfile();
167
+ $merchantProfileId = isset($merchantProfile->id) ? $merchantProfile->id : '';
168
+ } catch (ApiException $exception) {
169
+ $merchantProfileId = '';
170
+ }
171
+
172
+ update_option($merchantProfileIdOptionKey, $merchantProfileId, false);
173
+
174
+ return $optionValue;
175
+ }
176
+
177
  /**
178
  * Get plugin status
179
  *
182
  *
183
  * @return string
184
  */
185
+ protected function getPluginStatus()
186
  {
187
  $status = Mollie_WC_Plugin::getStatusHelper();
188
 
189
+ if (!$status->isCompatible()) {
 
190
  // Just stop here!
191
  return ''
192
  . '<div class="notice notice-error">'
193
+ . '<p><strong>' . __(
194
+ 'Error',
195
+ 'mollie-payments-for-woocommerce'
196
+ ) . ':</strong> ' . implode('<br/>', $status->getErrors())
197
  . '</p></div>';
198
  }
199
 
src/Mollie/WC/Plugin.php CHANGED
@@ -8,7 +8,7 @@ class Mollie_WC_Plugin
8
  {
9
  const PLUGIN_ID = 'mollie-payments-for-woocommerce';
10
  const PLUGIN_TITLE = 'Mollie Payments for WooCommerce';
11
- const PLUGIN_VERSION = '5.4.0';
12
 
13
  const DB_VERSION = '1.0';
14
  const DB_VERSION_PARAM_NAME = 'mollie-db-version';
@@ -205,6 +205,12 @@ class Mollie_WC_Plugin
205
  }
206
  }
207
  );
 
 
 
 
 
 
208
 
209
  // Add settings link to plugins page
210
  add_filter( 'plugin_action_links_' . $plugin_basename, array ( __CLASS__, 'addPluginActionLinks' ) );
8
  {
9
  const PLUGIN_ID = 'mollie-payments-for-woocommerce';
10
  const PLUGIN_TITLE = 'Mollie Payments for WooCommerce';
11
+ const PLUGIN_VERSION = '5.4.1';
12
 
13
  const DB_VERSION = '1.0';
14
  const DB_VERSION_PARAM_NAME = 'mollie-db-version';
205
  }
206
  }
207
  );
208
+ add_action(
209
+ 'woocommerce_admin_settings_sanitize_option',
210
+ [$settings_helper, 'updateMerchantIdOnApiKeyChanges'],
211
+ 10,
212
+ 2
213
+ );
214
 
215
  // Add settings link to plugins page
216
  add_filter( 'plugin_action_links_' . $plugin_basename, array ( __CLASS__, 'addPluginActionLinks' ) );
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit3ea1880a2740a3571db7cff67650474a::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit822e8679465379306e77c697814f1c55::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit3ea1880a2740a3571db7cff67650474a
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit3ea1880a2740a3571db7cff67650474a
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit3ea1880a2740a3571db7cff67650474a', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit3ea1880a2740a3571db7cff67650474a', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit3ea1880a2740a3571db7cff67650474a::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit3ea1880a2740a3571db7cff67650474a
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInit3ea1880a2740a3571db7cff67650474a::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequire3ea1880a2740a3571db7cff67650474a($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequire3ea1880a2740a3571db7cff67650474a($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit822e8679465379306e77c697814f1c55
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit822e8679465379306e77c697814f1c55', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit822e8679465379306e77c697814f1c55', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit822e8679465379306e77c697814f1c55::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit822e8679465379306e77c697814f1c55::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire822e8679465379306e77c697814f1c55($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequire822e8679465379306e77c697814f1c55($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit3ea1880a2740a3571db7cff67650474a
8
  {
9
  public static $files = array (
10
  '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
@@ -286,10 +286,10 @@ class ComposerStaticInit3ea1880a2740a3571db7cff67650474a
286
  public static function getInitializer(ClassLoader $loader)
287
  {
288
  return \Closure::bind(function () use ($loader) {
289
- $loader->prefixLengthsPsr4 = ComposerStaticInit3ea1880a2740a3571db7cff67650474a::$prefixLengthsPsr4;
290
- $loader->prefixDirsPsr4 = ComposerStaticInit3ea1880a2740a3571db7cff67650474a::$prefixDirsPsr4;
291
- $loader->prefixesPsr0 = ComposerStaticInit3ea1880a2740a3571db7cff67650474a::$prefixesPsr0;
292
- $loader->classMap = ComposerStaticInit3ea1880a2740a3571db7cff67650474a::$classMap;
293
 
294
  }, null, ClassLoader::class);
295
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit822e8679465379306e77c697814f1c55
8
  {
9
  public static $files = array (
10
  '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
286
  public static function getInitializer(ClassLoader $loader)
287
  {
288
  return \Closure::bind(function () use ($loader) {
289
+ $loader->prefixLengthsPsr4 = ComposerStaticInit822e8679465379306e77c697814f1c55::$prefixLengthsPsr4;
290
+ $loader->prefixDirsPsr4 = ComposerStaticInit822e8679465379306e77c697814f1c55::$prefixDirsPsr4;
291
+ $loader->prefixesPsr0 = ComposerStaticInit822e8679465379306e77c697814f1c55::$prefixesPsr0;
292
+ $loader->classMap = ComposerStaticInit822e8679465379306e77c697814f1c55::$classMap;
293
 
294
  }, null, ClassLoader::class);
295
  }
vendor/guzzlehttp/promises/README.md ADDED
@@ -0,0 +1,504 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Guzzle Promises
2
+
3
+ [Promises/A+](https://promisesaplus.com/) implementation that handles promise
4
+ chaining and resolution iteratively, allowing for "infinite" promise chaining
5
+ while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/)
6
+ for a general introduction to promises.
7
+
8
+ - [Features](#features)
9
+ - [Quick start](#quick-start)
10
+ - [Synchronous wait](#synchronous-wait)
11
+ - [Cancellation](#cancellation)
12
+ - [API](#api)
13
+ - [Promise](#promise)
14
+ - [FulfilledPromise](#fulfilledpromise)
15
+ - [RejectedPromise](#rejectedpromise)
16
+ - [Promise interop](#promise-interop)
17
+ - [Implementation notes](#implementation-notes)
18
+
19
+
20
+ # Features
21
+
22
+ - [Promises/A+](https://promisesaplus.com/) implementation.
23
+ - Promise resolution and chaining is handled iteratively, allowing for
24
+ "infinite" promise chaining.
25
+ - Promises have a synchronous `wait` method.
26
+ - Promises can be cancelled.
27
+ - Works with any object that has a `then` function.
28
+ - C# style async/await coroutine promises using
29
+ `GuzzleHttp\Promise\coroutine()`.
30
+
31
+
32
+ # Quick start
33
+
34
+ A *promise* represents the eventual result of an asynchronous operation. The
35
+ primary way of interacting with a promise is through its `then` method, which
36
+ registers callbacks to receive either a promise's eventual value or the reason
37
+ why the promise cannot be fulfilled.
38
+
39
+
40
+ ## Callbacks
41
+
42
+ Callbacks are registered with the `then` method by providing an optional
43
+ `$onFulfilled` followed by an optional `$onRejected` function.
44
+
45
+
46
+ ```php
47
+ use GuzzleHttp\Promise\Promise;
48
+
49
+ $promise = new Promise();
50
+ $promise->then(
51
+ // $onFulfilled
52
+ function ($value) {
53
+ echo 'The promise was fulfilled.';
54
+ },
55
+ // $onRejected
56
+ function ($reason) {
57
+ echo 'The promise was rejected.';
58
+ }
59
+ );
60
+ ```
61
+
62
+ *Resolving* a promise means that you either fulfill a promise with a *value* or
63
+ reject a promise with a *reason*. Resolving a promises triggers callbacks
64
+ registered with the promises's `then` method. These callbacks are triggered
65
+ only once and in the order in which they were added.
66
+
67
+
68
+ ## Resolving a promise
69
+
70
+ Promises are fulfilled using the `resolve($value)` method. Resolving a promise
71
+ with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger
72
+ all of the onFulfilled callbacks (resolving a promise with a rejected promise
73
+ will reject the promise and trigger the `$onRejected` callbacks).
74
+
75
+ ```php
76
+ use GuzzleHttp\Promise\Promise;
77
+
78
+ $promise = new Promise();
79
+ $promise
80
+ ->then(function ($value) {
81
+ // Return a value and don't break the chain
82
+ return "Hello, " . $value;
83
+ })
84
+ // This then is executed after the first then and receives the value
85
+ // returned from the first then.
86
+ ->then(function ($value) {
87
+ echo $value;
88
+ });
89
+
90
+ // Resolving the promise triggers the $onFulfilled callbacks and outputs
91
+ // "Hello, reader."
92
+ $promise->resolve('reader.');
93
+ ```
94
+
95
+
96
+ ## Promise forwarding
97
+
98
+ Promises can be chained one after the other. Each then in the chain is a new
99
+ promise. The return value of a promise is what's forwarded to the next
100
+ promise in the chain. Returning a promise in a `then` callback will cause the
101
+ subsequent promises in the chain to only be fulfilled when the returned promise
102
+ has been fulfilled. The next promise in the chain will be invoked with the
103
+ resolved value of the promise.
104
+
105
+ ```php
106
+ use GuzzleHttp\Promise\Promise;
107
+
108
+ $promise = new Promise();
109
+ $nextPromise = new Promise();
110
+
111
+ $promise
112
+ ->then(function ($value) use ($nextPromise) {
113
+ echo $value;
114
+ return $nextPromise;
115
+ })
116
+ ->then(function ($value) {
117
+ echo $value;
118
+ });
119
+
120
+ // Triggers the first callback and outputs "A"
121
+ $promise->resolve('A');
122
+ // Triggers the second callback and outputs "B"
123
+ $nextPromise->resolve('B');
124
+ ```
125
+
126
+ ## Promise rejection
127
+
128
+ When a promise is rejected, the `$onRejected` callbacks are invoked with the
129
+ rejection reason.
130
+
131
+ ```php
132
+ use GuzzleHttp\Promise\Promise;
133
+
134
+ $promise = new Promise();
135
+ $promise->then(null, function ($reason) {
136
+ echo $reason;
137
+ });
138
+
139
+ $promise->reject('Error!');
140
+ // Outputs "Error!"
141
+ ```
142
+
143
+ ## Rejection forwarding
144
+
145
+ If an exception is thrown in an `$onRejected` callback, subsequent
146
+ `$onRejected` callbacks are invoked with the thrown exception as the reason.
147
+
148
+ ```php
149
+ use GuzzleHttp\Promise\Promise;
150
+
151
+ $promise = new Promise();
152
+ $promise->then(null, function ($reason) {
153
+ throw new \Exception($reason);
154
+ })->then(null, function ($reason) {
155
+ assert($reason->getMessage() === 'Error!');
156
+ });
157
+
158
+ $promise->reject('Error!');
159
+ ```
160
+
161
+ You can also forward a rejection down the promise chain by returning a
162
+ `GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or
163
+ `$onRejected` callback.
164
+
165
+ ```php
166
+ use GuzzleHttp\Promise\Promise;
167
+ use GuzzleHttp\Promise\RejectedPromise;
168
+
169
+ $promise = new Promise();
170
+ $promise->then(null, function ($reason) {
171
+ return new RejectedPromise($reason);
172
+ })->then(null, function ($reason) {
173
+ assert($reason === 'Error!');
174
+ });
175
+
176
+ $promise->reject('Error!');
177
+ ```
178
+
179
+ If an exception is not thrown in a `$onRejected` callback and the callback
180
+ does not return a rejected promise, downstream `$onFulfilled` callbacks are
181
+ invoked using the value returned from the `$onRejected` callback.
182
+
183
+ ```php
184
+ use GuzzleHttp\Promise\Promise;
185
+ use GuzzleHttp\Promise\RejectedPromise;
186
+
187
+ $promise = new Promise();
188
+ $promise
189
+ ->then(null, function ($reason) {
190
+ return "It's ok";
191
+ })
192
+ ->then(function ($value) {
193
+ assert($value === "It's ok");
194
+ });
195
+
196
+ $promise->reject('Error!');
197
+ ```
198
+
199
+ # Synchronous wait
200
+
201
+ You can synchronously force promises to complete using a promise's `wait`
202
+ method. When creating a promise, you can provide a wait function that is used
203
+ to synchronously force a promise to complete. When a wait function is invoked
204
+ it is expected to deliver a value to the promise or reject the promise. If the
205
+ wait function does not deliver a value, then an exception is thrown. The wait
206
+ function provided to a promise constructor is invoked when the `wait` function
207
+ of the promise is called.
208
+
209
+ ```php
210
+ $promise = new Promise(function () use (&$promise) {
211
+ $promise->resolve('foo');
212
+ });
213
+
214
+ // Calling wait will return the value of the promise.
215
+ echo $promise->wait(); // outputs "foo"
216
+ ```
217
+
218
+ If an exception is encountered while invoking the wait function of a promise,
219
+ the promise is rejected with the exception and the exception is thrown.
220
+
221
+ ```php
222
+ $promise = new Promise(function () use (&$promise) {
223
+ throw new \Exception('foo');
224
+ });
225
+
226
+ $promise->wait(); // throws the exception.
227
+ ```
228
+
229
+ Calling `wait` on a promise that has been fulfilled will not trigger the wait
230
+ function. It will simply return the previously resolved value.
231
+
232
+ ```php
233
+ $promise = new Promise(function () { die('this is not called!'); });
234
+ $promise->resolve('foo');
235
+ echo $promise->wait(); // outputs "foo"
236
+ ```
237
+
238
+ Calling `wait` on a promise that has been rejected will throw an exception. If
239
+ the rejection reason is an instance of `\Exception` the reason is thrown.
240
+ Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason
241
+ can be obtained by calling the `getReason` method of the exception.
242
+
243
+ ```php
244
+ $promise = new Promise();
245
+ $promise->reject('foo');
246
+ $promise->wait();
247
+ ```
248
+
249
+ > PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'
250
+
251
+
252
+ ## Unwrapping a promise
253
+
254
+ When synchronously waiting on a promise, you are joining the state of the
255
+ promise into the current state of execution (i.e., return the value of the
256
+ promise if it was fulfilled or throw an exception if it was rejected). This is
257
+ called "unwrapping" the promise. Waiting on a promise will by default unwrap
258
+ the promise state.
259
+
260
+ You can force a promise to resolve and *not* unwrap the state of the promise
261
+ by passing `false` to the first argument of the `wait` function:
262
+
263
+ ```php
264
+ $promise = new Promise();
265
+ $promise->reject('foo');
266
+ // This will not throw an exception. It simply ensures the promise has
267
+ // been resolved.
268
+ $promise->wait(false);
269
+ ```
270
+
271
+ When unwrapping a promise, the resolved value of the promise will be waited
272
+ upon until the unwrapped value is not a promise. This means that if you resolve
273
+ promise A with a promise B and unwrap promise A, the value returned by the
274
+ wait function will be the value delivered to promise B.
275
+
276
+ **Note**: when you do not unwrap the promise, no value is returned.
277
+
278
+
279
+ # Cancellation
280
+
281
+ You can cancel a promise that has not yet been fulfilled using the `cancel()`
282
+ method of a promise. When creating a promise you can provide an optional
283
+ cancel function that when invoked cancels the action of computing a resolution
284
+ of the promise.
285
+
286
+
287
+ # API
288
+
289
+
290
+ ## Promise
291
+
292
+ When creating a promise object, you can provide an optional `$waitFn` and
293
+ `$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is
294
+ expected to resolve the promise. `$cancelFn` is a function with no arguments
295
+ that is expected to cancel the computation of a promise. It is invoked when the
296
+ `cancel()` method of a promise is called.
297
+
298
+ ```php
299
+ use GuzzleHttp\Promise\Promise;
300
+
301
+ $promise = new Promise(
302
+ function () use (&$promise) {
303
+ $promise->resolve('waited');
304
+ },
305
+ function () {
306
+ // do something that will cancel the promise computation (e.g., close
307
+ // a socket, cancel a database query, etc...)
308
+ }
309
+ );
310
+
311
+ assert('waited' === $promise->wait());
312
+ ```
313
+
314
+ A promise has the following methods:
315
+
316
+ - `then(callable $onFulfilled, callable $onRejected) : PromiseInterface`
317
+
318
+ Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.
319
+
320
+ - `otherwise(callable $onRejected) : PromiseInterface`
321
+
322
+ Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
323
+
324
+ - `wait($unwrap = true) : mixed`
325
+
326
+ Synchronously waits on the promise to complete.
327
+
328
+ `$unwrap` controls whether or not the value of the promise is returned for a
329
+ fulfilled promise or if an exception is thrown if the promise is rejected.
330
+ This is set to `true` by default.
331
+
332
+ - `cancel()`
333
+
334
+ Attempts to cancel the promise if possible. The promise being cancelled and
335
+ the parent most ancestor that has not yet been resolved will also be
336
+ cancelled. Any promises waiting on the cancelled promise to resolve will also
337
+ be cancelled.
338
+
339
+ - `getState() : string`
340
+
341
+ Returns the state of the promise. One of `pending`, `fulfilled`, or
342
+ `rejected`.
343
+
344
+ - `resolve($value)`
345
+
346
+ Fulfills the promise with the given `$value`.
347
+
348
+ - `reject($reason)`
349
+
350
+ Rejects the promise with the given `$reason`.
351
+
352
+
353
+ ## FulfilledPromise
354
+
355
+ A fulfilled promise can be created to represent a promise that has been
356
+ fulfilled.
357
+
358
+ ```php
359
+ use GuzzleHttp\Promise\FulfilledPromise;
360
+
361
+ $promise = new FulfilledPromise('value');
362
+
363
+ // Fulfilled callbacks are immediately invoked.
364
+ $promise->then(function ($value) {
365
+ echo $value;
366
+ });
367
+ ```
368
+
369
+
370
+ ## RejectedPromise
371
+
372
+ A rejected promise can be created to represent a promise that has been
373
+ rejected.
374
+
375
+ ```php
376
+ use GuzzleHttp\Promise\RejectedPromise;
377
+
378
+ $promise = new RejectedPromise('Error');
379
+
380
+ // Rejected callbacks are immediately invoked.
381
+ $promise->then(null, function ($reason) {
382
+ echo $reason;
383
+ });
384
+ ```
385
+
386
+
387
+ # Promise interop
388
+
389
+ This library works with foreign promises that have a `then` method. This means
390
+ you can use Guzzle promises with [React promises](https://github.com/reactphp/promise)
391
+ for example. When a foreign promise is returned inside of a then method
392
+ callback, promise resolution will occur recursively.
393
+
394
+ ```php
395
+ // Create a React promise
396
+ $deferred = new React\Promise\Deferred();
397
+ $reactPromise = $deferred->promise();
398
+
399
+ // Create a Guzzle promise that is fulfilled with a React promise.
400
+ $guzzlePromise = new \GuzzleHttp\Promise\Promise();
401
+ $guzzlePromise->then(function ($value) use ($reactPromise) {
402
+ // Do something something with the value...
403
+ // Return the React promise
404
+ return $reactPromise;
405
+ });
406
+ ```
407
+
408
+ Please note that wait and cancel chaining is no longer possible when forwarding
409
+ a foreign promise. You will need to wrap a third-party promise with a Guzzle
410
+ promise in order to utilize wait and cancel functions with foreign promises.
411
+
412
+
413
+ ## Event Loop Integration
414
+
415
+ In order to keep the stack size constant, Guzzle promises are resolved
416
+ asynchronously using a task queue. When waiting on promises synchronously, the
417
+ task queue will be automatically run to ensure that the blocking promise and
418
+ any forwarded promises are resolved. When using promises asynchronously in an
419
+ event loop, you will need to run the task queue on each tick of the loop. If
420
+ you do not run the task queue, then promises will not be resolved.
421
+
422
+ You can run the task queue using the `run()` method of the global task queue
423
+ instance.
424
+
425
+ ```php
426
+ // Get the global task queue
427
+ $queue = \GuzzleHttp\Promise\queue();
428
+ $queue->run();
429
+ ```
430
+
431
+ For example, you could use Guzzle promises with React using a periodic timer:
432
+
433
+ ```php
434
+ $loop = React\EventLoop\Factory::create();
435
+ $loop->addPeriodicTimer(0, [$queue, 'run']);
436
+ ```
437
+
438
+ *TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
439
+
440
+
441
+ # Implementation notes
442
+
443
+
444
+ ## Promise resolution and chaining is handled iteratively
445
+
446
+ By shuffling pending handlers from one owner to another, promises are
447
+ resolved iteratively, allowing for "infinite" then chaining.
448
+
449
+ ```php
450
+ <?php
451
+ require 'vendor/autoload.php';
452
+
453
+ use GuzzleHttp\Promise\Promise;
454
+
455
+ $parent = new Promise();
456
+ $p = $parent;
457
+
458
+ for ($i = 0; $i < 1000; $i++) {
459
+ $p = $p->then(function ($v) {
460
+ // The stack size remains constant (a good thing)
461
+ echo xdebug_get_stack_depth() . ', ';
462
+ return $v + 1;
463
+ });
464
+ }
465
+
466
+ $parent->resolve(0);
467
+ var_dump($p->wait()); // int(1000)
468
+
469
+ ```
470
+
471
+ When a promise is fulfilled or rejected with a non-promise value, the promise
472
+ then takes ownership of the handlers of each child promise and delivers values
473
+ down the chain without using recursion.
474
+
475
+ When a promise is resolved with another promise, the original promise transfers
476
+ all of its pending handlers to the new promise. When the new promise is
477
+ eventually resolved, all of the pending handlers are delivered the forwarded
478
+ value.
479
+
480
+
481
+ ## A promise is the deferred.
482
+
483
+ Some promise libraries implement promises using a deferred object to represent
484
+ a computation and a promise object to represent the delivery of the result of
485
+ the computation. This is a nice separation of computation and delivery because
486
+ consumers of the promise cannot modify the value that will be eventually
487
+ delivered.
488
+
489
+ One side effect of being able to implement promise resolution and chaining
490
+ iteratively is that you need to be able for one promise to reach into the state
491
+ of another promise to shuffle around ownership of handlers. In order to achieve
492
+ this without making the handlers of a promise publicly mutable, a promise is
493
+ also the deferred value, allowing promises of the same parent class to reach
494
+ into and modify the private properties of promises of the same type. While this
495
+ does allow consumers of the value to modify the resolution or rejection of the
496
+ deferred, it is a small price to pay for keeping the stack size constant.
497
+
498
+ ```php
499
+ $promise = new Promise();
500
+ $promise->then(function ($value) { echo $value; });
501
+ // The promise is the deferred value, so you can deliver a value to it.
502
+ $promise->resolve('foo');
503
+ // prints "foo"
504
+ ```
vendor/guzzlehttp/psr7/README.md ADDED
@@ -0,0 +1,745 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PSR-7 Message Implementation
2
+
3
+ This repository contains a full [PSR-7](http://www.php-fig.org/psr/psr-7/)
4
+ message implementation, several stream decorators, and some helpful
5
+ functionality like query string parsing.
6
+
7
+
8
+ [![Build Status](https://travis-ci.org/guzzle/psr7.svg?branch=master)](https://travis-ci.org/guzzle/psr7)
9
+
10
+
11
+ # Stream implementation
12
+
13
+ This package comes with a number of stream implementations and stream
14
+ decorators.
15
+
16
+
17
+ ## AppendStream
18
+
19
+ `GuzzleHttp\Psr7\AppendStream`
20
+
21
+ Reads from multiple streams, one after the other.
22
+
23
+ ```php
24
+ use GuzzleHttp\Psr7;
25
+
26
+ $a = Psr7\stream_for('abc, ');
27
+ $b = Psr7\stream_for('123.');
28
+ $composed = new Psr7\AppendStream([$a, $b]);
29
+
30
+ $composed->addStream(Psr7\stream_for(' Above all listen to me'));
31
+
32
+ echo $composed; // abc, 123. Above all listen to me.
33
+ ```
34
+
35
+
36
+ ## BufferStream
37
+
38
+ `GuzzleHttp\Psr7\BufferStream`
39
+
40
+ Provides a buffer stream that can be written to fill a buffer, and read
41
+ from to remove bytes from the buffer.
42
+
43
+ This stream returns a "hwm" metadata value that tells upstream consumers
44
+ what the configured high water mark of the stream is, or the maximum
45
+ preferred size of the buffer.
46
+
47
+ ```php
48
+ use GuzzleHttp\Psr7;
49
+
50
+ // When more than 1024 bytes are in the buffer, it will begin returning
51
+ // false to writes. This is an indication that writers should slow down.
52
+ $buffer = new Psr7\BufferStream(1024);
53
+ ```
54
+
55
+
56
+ ## CachingStream
57
+
58
+ The CachingStream is used to allow seeking over previously read bytes on
59
+ non-seekable streams. This can be useful when transferring a non-seekable
60
+ entity body fails due to needing to rewind the stream (for example, resulting
61
+ from a redirect). Data that is read from the remote stream will be buffered in
62
+ a PHP temp stream so that previously read bytes are cached first in memory,
63
+ then on disk.
64
+
65
+ ```php
66
+ use GuzzleHttp\Psr7;
67
+
68
+ $original = Psr7\stream_for(fopen('http://www.google.com', 'r'));
69
+ $stream = new Psr7\CachingStream($original);
70
+
71
+ $stream->read(1024);
72
+ echo $stream->tell();
73
+ // 1024
74
+
75
+ $stream->seek(0);
76
+ echo $stream->tell();
77
+ // 0
78
+ ```
79
+
80
+
81
+ ## DroppingStream
82
+
83
+ `GuzzleHttp\Psr7\DroppingStream`
84
+
85
+ Stream decorator that begins dropping data once the size of the underlying
86
+ stream becomes too full.
87
+
88
+ ```php
89
+ use GuzzleHttp\Psr7;
90
+
91
+ // Create an empty stream
92
+ $stream = Psr7\stream_for();
93
+
94
+ // Start dropping data when the stream has more than 10 bytes
95
+ $dropping = new Psr7\DroppingStream($stream, 10);
96
+
97
+ $dropping->write('01234567890123456789');
98
+ echo $stream; // 0123456789
99
+ ```
100
+
101
+
102
+ ## FnStream
103
+
104
+ `GuzzleHttp\Psr7\FnStream`
105
+
106
+ Compose stream implementations based on a hash of functions.
107
+
108
+ Allows for easy testing and extension of a provided stream without needing
109
+ to create a concrete class for a simple extension point.
110
+
111
+ ```php
112
+
113
+ use GuzzleHttp\Psr7;
114
+
115
+ $stream = Psr7\stream_for('hi');
116
+ $fnStream = Psr7\FnStream::decorate($stream, [
117
+ 'rewind' => function () use ($stream) {
118
+ echo 'About to rewind - ';
119
+ $stream->rewind();
120
+ echo 'rewound!';
121
+ }
122
+ ]);
123
+
124
+ $fnStream->rewind();
125
+ // Outputs: About to rewind - rewound!
126
+ ```
127
+
128
+
129
+ ## InflateStream
130
+
131
+ `GuzzleHttp\Psr7\InflateStream`
132
+
133
+ Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
134
+
135
+ This stream decorator skips the first 10 bytes of the given stream to remove
136
+ the gzip header, converts the provided stream to a PHP stream resource,
137
+ then appends the zlib.inflate filter. The stream is then converted back
138
+ to a Guzzle stream resource to be used as a Guzzle stream.
139
+
140
+
141
+ ## LazyOpenStream
142
+
143
+ `GuzzleHttp\Psr7\LazyOpenStream`
144
+
145
+ Lazily reads or writes to a file that is opened only after an IO operation
146
+ take place on the stream.
147
+
148
+ ```php
149
+ use GuzzleHttp\Psr7;
150
+
151
+ $stream = new Psr7\LazyOpenStream('/path/to/file', 'r');
152
+ // The file has not yet been opened...
153
+
154
+ echo $stream->read(10);
155
+ // The file is opened and read from only when needed.
156
+ ```
157
+
158
+
159
+ ## LimitStream
160
+
161
+ `GuzzleHttp\Psr7\LimitStream`
162
+
163
+ LimitStream can be used to read a subset or slice of an existing stream object.
164
+ This can be useful for breaking a large file into smaller pieces to be sent in
165
+ chunks (e.g. Amazon S3's multipart upload API).
166
+
167
+ ```php
168
+ use GuzzleHttp\Psr7;
169
+
170
+ $original = Psr7\stream_for(fopen('/tmp/test.txt', 'r+'));
171
+ echo $original->getSize();
172
+ // >>> 1048576
173
+
174
+ // Limit the size of the body to 1024 bytes and start reading from byte 2048
175
+ $stream = new Psr7\LimitStream($original, 1024, 2048);
176
+ echo $stream->getSize();
177
+ // >>> 1024
178
+ echo $stream->tell();
179
+ // >>> 0
180
+ ```
181
+
182
+
183
+ ## MultipartStream
184
+
185
+ `GuzzleHttp\Psr7\MultipartStream`
186
+
187
+ Stream that when read returns bytes for a streaming multipart or
188
+ multipart/form-data stream.
189
+
190
+
191
+ ## NoSeekStream
192
+
193
+ `GuzzleHttp\Psr7\NoSeekStream`
194
+
195
+ NoSeekStream wraps a stream and does not allow seeking.
196
+
197
+ ```php
198
+ use GuzzleHttp\Psr7;
199
+
200
+ $original = Psr7\stream_for('foo');
201
+ $noSeek = new Psr7\NoSeekStream($original);
202
+
203
+ echo $noSeek->read(3);
204
+ // foo
205
+ var_export($noSeek->isSeekable());
206
+ // false
207
+ $noSeek->seek(0);
208
+ var_export($noSeek->read(3));
209
+ // NULL
210
+ ```
211
+
212
+
213
+ ## PumpStream
214
+
215
+ `GuzzleHttp\Psr7\PumpStream`
216
+
217
+ Provides a read only stream that pumps data from a PHP callable.
218
+
219
+ When invoking the provided callable, the PumpStream will pass the amount of
220
+ data requested to read to the callable. The callable can choose to ignore
221
+ this value and return fewer or more bytes than requested. Any extra data
222
+ returned by the provided callable is buffered internally until drained using
223
+ the read() function of the PumpStream. The provided callable MUST return
224
+ false when there is no more data to read.
225
+
226
+
227
+ ## Implementing stream decorators
228
+
229
+ Creating a stream decorator is very easy thanks to the
230
+ `GuzzleHttp\Psr7\StreamDecoratorTrait`. This trait provides methods that
231
+ implement `Psr\Http\Message\StreamInterface` by proxying to an underlying
232
+ stream. Just `use` the `StreamDecoratorTrait` and implement your custom
233
+ methods.
234
+
235
+ For example, let's say we wanted to call a specific function each time the last
236
+ byte is read from a stream. This could be implemented by overriding the
237
+ `read()` method.
238
+
239
+ ```php
240
+ use Psr\Http\Message\StreamInterface;
241
+ use GuzzleHttp\Psr7\StreamDecoratorTrait;
242
+
243
+ class EofCallbackStream implements StreamInterface
244
+ {
245
+ use StreamDecoratorTrait;
246
+
247
+ private $callback;
248
+
249
+ public function __construct(StreamInterface $stream, callable $cb)
250
+ {
251
+ $this->stream = $stream;
252
+ $this->callback = $cb;
253
+ }
254
+
255
+ public function read($length)
256
+ {
257
+ $result = $this->stream->read($length);
258
+
259
+ // Invoke the callback when EOF is hit.
260
+ if ($this->eof()) {
261
+ call_user_func($this->callback);
262
+ }
263
+
264
+ return $result;
265
+ }
266
+ }
267
+ ```
268
+
269
+ This decorator could be added to any existing stream and used like so:
270
+
271
+ ```php
272
+ use GuzzleHttp\Psr7;
273
+
274
+ $original = Psr7\stream_for('foo');
275
+
276
+ $eofStream = new EofCallbackStream($original, function () {
277
+ echo 'EOF!';
278
+ });
279
+
280
+ $eofStream->read(2);
281
+ $eofStream->read(1);
282
+ // echoes "EOF!"
283
+ $eofStream->seek(0);
284
+ $eofStream->read(3);
285
+ // echoes "EOF!"
286
+ ```
287
+
288
+
289
+ ## PHP StreamWrapper
290
+
291
+ You can use the `GuzzleHttp\Psr7\StreamWrapper` class if you need to use a
292
+ PSR-7 stream as a PHP stream resource.
293
+
294
+ Use the `GuzzleHttp\Psr7\StreamWrapper::getResource()` method to create a PHP
295
+ stream from a PSR-7 stream.
296
+
297
+ ```php
298
+ use GuzzleHttp\Psr7\StreamWrapper;
299
+
300
+ $stream = GuzzleHttp\Psr7\stream_for('hello!');
301
+ $resource = StreamWrapper::getResource($stream);
302
+ echo fread($resource, 6); // outputs hello!
303
+ ```
304
+
305
+
306
+ # Function API
307
+
308
+ There are various functions available under the `GuzzleHttp\Psr7` namespace.
309
+
310
+
311
+ ## `function str`
312
+
313
+ `function str(MessageInterface $message)`
314
+
315
+ Returns the string representation of an HTTP message.
316
+
317
+ ```php
318
+ $request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com');
319
+ echo GuzzleHttp\Psr7\str($request);
320
+ ```
321
+
322
+
323
+ ## `function uri_for`
324
+
325
+ `function uri_for($uri)`
326
+
327
+ This function accepts a string or `Psr\Http\Message\UriInterface` and returns a
328
+ UriInterface for the given value. If the value is already a `UriInterface`, it
329
+ is returned as-is.
330
+
331
+ ```php
332
+ $uri = GuzzleHttp\Psr7\uri_for('http://example.com');
333
+ assert($uri === GuzzleHttp\Psr7\uri_for($uri));
334
+ ```
335
+
336
+
337
+ ## `function stream_for`
338
+
339
+ `function stream_for($resource = '', array $options = [])`
340
+
341
+ Create a new stream based on the input type.
342
+
343
+ Options is an associative array that can contain the following keys:
344
+
345
+ * - metadata: Array of custom metadata.
346
+ * - size: Size of the stream.
347
+
348
+ This method accepts the following `$resource` types:
349
+
350
+ - `Psr\Http\Message\StreamInterface`: Returns the value as-is.
351
+ - `string`: Creates a stream object that uses the given string as the contents.
352
+ - `resource`: Creates a stream object that wraps the given PHP stream resource.
353
+ - `Iterator`: If the provided value implements `Iterator`, then a read-only
354
+ stream object will be created that wraps the given iterable. Each time the
355
+ stream is read from, data from the iterator will fill a buffer and will be
356
+ continuously called until the buffer is equal to the requested read size.
357
+ Subsequent read calls will first read from the buffer and then call `next`
358
+ on the underlying iterator until it is exhausted.
359
+ - `object` with `__toString()`: If the object has the `__toString()` method,
360
+ the object will be cast to a string and then a stream will be returned that
361
+ uses the string value.
362
+ - `NULL`: When `null` is passed, an empty stream object is returned.
363
+ - `callable` When a callable is passed, a read-only stream object will be
364
+ created that invokes the given callable. The callable is invoked with the
365
+ number of suggested bytes to read. The callable can return any number of
366
+ bytes, but MUST return `false` when there is no more data to return. The
367
+ stream object that wraps the callable will invoke the callable until the
368
+ number of requested bytes are available. Any additional bytes will be
369
+ buffered and used in subsequent reads.
370
+
371
+ ```php
372
+ $stream = GuzzleHttp\Psr7\stream_for('foo');
373
+ $stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r'));
374
+
375
+ $generator = function ($bytes) {
376
+ for ($i = 0; $i < $bytes; $i++) {
377
+ yield ' ';
378
+ }
379
+ }
380
+
381
+ $stream = GuzzleHttp\Psr7\stream_for($generator(100));
382
+ ```
383
+
384
+
385
+ ## `function parse_header`
386
+
387
+ `function parse_header($header)`
388
+
389
+ Parse an array of header values containing ";" separated data into an array of
390
+ associative arrays representing the header key value pair data of the header.
391
+ When a parameter does not contain a value, but just contains a key, this
392
+ function will inject a key with a '' string value.
393
+
394
+
395
+ ## `function normalize_header`
396
+
397
+ `function normalize_header($header)`
398
+
399
+ Converts an array of header values that may contain comma separated headers
400
+ into an array of headers with no comma separated values.
401
+
402
+
403
+ ## `function modify_request`
404
+
405
+ `function modify_request(RequestInterface $request, array $changes)`
406
+
407
+ Clone and modify a request with the given changes. This method is useful for
408
+ reducing the number of clones needed to mutate a message.
409
+
410
+ The changes can be one of:
411
+
412
+ - method: (string) Changes the HTTP method.
413
+ - set_headers: (array) Sets the given headers.
414
+ - remove_headers: (array) Remove the given headers.
415
+ - body: (mixed) Sets the given body.
416
+ - uri: (UriInterface) Set the URI.
417
+ - query: (string) Set the query string value of the URI.
418
+ - version: (string) Set the protocol version.
419
+
420
+
421
+ ## `function rewind_body`
422
+
423
+ `function rewind_body(MessageInterface $message)`
424
+
425
+ Attempts to rewind a message body and throws an exception on failure. The body
426
+ of the message will only be rewound if a call to `tell()` returns a value other
427
+ than `0`.
428
+
429
+
430
+ ## `function try_fopen`
431
+
432
+ `function try_fopen($filename, $mode)`
433
+
434
+ Safely opens a PHP stream resource using a filename.
435
+
436
+ When fopen fails, PHP normally raises a warning. This function adds an error
437
+ handler that checks for errors and throws an exception instead.
438
+
439
+
440
+ ## `function copy_to_string`
441
+
442
+ `function copy_to_string(StreamInterface $stream, $maxLen = -1)`
443
+
444
+ Copy the contents of a stream into a string until the given number of bytes
445
+ have been read.
446
+
447
+
448
+ ## `function copy_to_stream`
449
+
450
+ `function copy_to_stream(StreamInterface $source, StreamInterface $dest, $maxLen = -1)`
451
+
452
+ Copy the contents of a stream into another stream until the given number of
453
+ bytes have been read.
454
+
455
+
456
+ ## `function hash`
457
+
458
+ `function hash(StreamInterface $stream, $algo, $rawOutput = false)`
459
+
460
+ Calculate a hash of a Stream. This method reads the entire stream to calculate
461
+ a rolling hash (based on PHP's hash_init functions).
462
+
463
+
464
+ ## `function readline`
465
+
466
+ `function readline(StreamInterface $stream, $maxLength = null)`
467
+
468
+ Read a line from the stream up to the maximum allowed buffer length.
469
+
470
+
471
+ ## `function parse_request`
472
+
473
+ `function parse_request($message)`
474
+
475
+ Parses a request message string into a request object.
476
+
477
+
478
+ ## `function parse_response`
479
+
480
+ `function parse_response($message)`
481
+
482
+ Parses a response message string into a response object.
483
+
484
+
485
+ ## `function parse_query`
486
+
487
+ `function parse_query($str, $urlEncoding = true)`
488
+
489
+ Parse a query string into an associative array.
490
+
491
+ If multiple values are found for the same key, the value of that key value pair
492
+ will become an array. This function does not parse nested PHP style arrays into
493
+ an associative array (e.g., `foo[a]=1&foo[b]=2` will be parsed into
494
+ `['foo[a]' => '1', 'foo[b]' => '2']`).
495
+
496
+
497
+ ## `function build_query`
498
+
499
+ `function build_query(array $params, $encoding = PHP_QUERY_RFC3986)`
500
+
501
+ Build a query string from an array of key value pairs.
502
+
503
+ This function can use the return value of parse_query() to build a query string.
504
+ This function does not modify the provided keys when an array is encountered
505
+ (like http_build_query would).
506
+
507
+
508
+ ## `function mimetype_from_filename`
509
+
510
+ `function mimetype_from_filename($filename)`
511
+
512
+ Determines the mimetype of a file by looking at its extension.
513
+
514
+
515
+ ## `function mimetype_from_extension`
516
+
517
+ `function mimetype_from_extension($extension)`
518
+
519
+ Maps a file extensions to a mimetype.
520
+
521
+
522
+ # Additional URI Methods
523
+
524
+ Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class,
525
+ this library also provides additional functionality when working with URIs as static methods.
526
+
527
+ ## URI Types
528
+
529
+ An instance of `Psr\Http\Message\UriInterface` can either be an absolute URI or a relative reference.
530
+ An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI,
531
+ the base URI. Relative references can be divided into several forms according to
532
+ [RFC 3986 Section 4.2](https://tools.ietf.org/html/rfc3986#section-4.2):
533
+
534
+ - network-path references, e.g. `//example.com/path`
535
+ - absolute-path references, e.g. `/path`
536
+ - relative-path references, e.g. `subpath`
537
+
538
+ The following methods can be used to identify the type of the URI.
539
+
540
+ ### `GuzzleHttp\Psr7\Uri::isAbsolute`
541
+
542
+ `public static function isAbsolute(UriInterface $uri): bool`
543
+
544
+ Whether the URI is absolute, i.e. it has a scheme.
545
+
546
+ ### `GuzzleHttp\Psr7\Uri::isNetworkPathReference`
547
+
548
+ `public static function isNetworkPathReference(UriInterface $uri): bool`
549
+
550
+ Whether the URI is a network-path reference. A relative reference that begins with two slash characters is
551
+ termed an network-path reference.
552
+
553
+ ### `GuzzleHttp\Psr7\Uri::isAbsolutePathReference`
554
+
555
+ `public static function isAbsolutePathReference(UriInterface $uri): bool`
556
+
557
+ Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is
558
+ termed an absolute-path reference.
559
+
560
+ ### `GuzzleHttp\Psr7\Uri::isRelativePathReference`
561
+
562
+ `public static function isRelativePathReference(UriInterface $uri): bool`
563
+
564
+ Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is
565
+ termed a relative-path reference.
566
+
567
+ ### `GuzzleHttp\Psr7\Uri::isSameDocumentReference`
568
+
569
+ `public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool`
570
+
571
+ Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
572
+ fragment component, identical to the base URI. When no base URI is given, only an empty URI reference
573
+ (apart from its fragment) is considered a same-document reference.
574
+
575
+ ## URI Components
576
+
577
+ Additional methods to work with URI components.
578
+
579
+ ### `GuzzleHttp\Psr7\Uri::isDefaultPort`
580
+
581
+ `public static function isDefaultPort(UriInterface $uri): bool`
582
+
583
+ Whether the URI has the default port of the current scheme. `Psr\Http\Message\UriInterface::getPort` may return null
584
+ or the standard port. This method can be used independently of the implementation.
585
+
586
+ ### `GuzzleHttp\Psr7\Uri::composeComponents`
587
+
588
+ `public static function composeComponents($scheme, $authority, $path, $query, $fragment): string`
589
+
590
+ Composes a URI reference string from its various components according to
591
+ [RFC 3986 Section 5.3](https://tools.ietf.org/html/rfc3986#section-5.3). Usually this method does not need to be called
592
+ manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__toString`.
593
+
594
+ ### `GuzzleHttp\Psr7\Uri::fromParts`
595
+
596
+ `public static function fromParts(array $parts): UriInterface`
597
+
598
+ Creates a URI from a hash of [`parse_url`](http://php.net/manual/en/function.parse-url.php) components.
599
+
600
+
601
+ ### `GuzzleHttp\Psr7\Uri::withQueryValue`
602
+
603
+ `public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface`
604
+
605
+ Creates a new URI with a specific query string value. Any existing query string values that exactly match the
606
+ provided key are removed and replaced with the given key value pair. A value of null will set the query string
607
+ key without a value, e.g. "key" instead of "key=value".
608
+
609
+ ### `GuzzleHttp\Psr7\Uri::withQueryValues`
610
+
611
+ `public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface`
612
+
613
+ Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an
614
+ associative array of key => value.
615
+
616
+ ### `GuzzleHttp\Psr7\Uri::withoutQueryValue`
617
+
618
+ `public static function withoutQueryValue(UriInterface $uri, $key): UriInterface`
619
+
620
+ Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
621
+ provided key are removed.
622
+
623
+ ## Reference Resolution
624
+
625
+ `GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according
626
+ to [RFC 3986 Section 5](https://tools.ietf.org/html/rfc3986#section-5). This is for example also what web browsers
627
+ do when resolving a link in a website based on the current request URI.
628
+
629
+ ### `GuzzleHttp\Psr7\UriResolver::resolve`
630
+
631
+ `public static function resolve(UriInterface $base, UriInterface $rel): UriInterface`
632
+
633
+ Converts the relative URI into a new URI that is resolved against the base URI.
634
+
635
+ ### `GuzzleHttp\Psr7\UriResolver::removeDotSegments`
636
+
637
+ `public static function removeDotSegments(string $path): string`
638
+
639
+ Removes dot segments from a path and returns the new path according to
640
+ [RFC 3986 Section 5.2.4](https://tools.ietf.org/html/rfc3986#section-5.2.4).
641
+
642
+ ### `GuzzleHttp\Psr7\UriResolver::relativize`
643
+
644
+ `public static function relativize(UriInterface $base, UriInterface $target): UriInterface`
645
+
646
+ Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve():
647
+
648
+ ```php
649
+ (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
650
+ ```
651
+
652
+ One use-case is to use the current request URI as base URI and then generate relative links in your documents
653
+ to reduce the document size or offer self-contained downloadable document archives.
654
+
655
+ ```php
656
+ $base = new Uri('http://example.com/a/b/');
657
+ echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
658
+ echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
659
+ echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
660
+ echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.
661
+ ```
662
+
663
+ ## Normalization and Comparison
664
+
665
+ `GuzzleHttp\Psr7\UriNormalizer` provides methods to normalize and compare URIs according to
666
+ [RFC 3986 Section 6](https://tools.ietf.org/html/rfc3986#section-6).
667
+
668
+ ### `GuzzleHttp\Psr7\UriNormalizer::normalize`
669
+
670
+ `public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface`
671
+
672
+ Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
673
+ This methods adds additional normalizations that can be configured with the `$flags` parameter which is a bitmask
674
+ of normalizations to apply. The following normalizations are available:
675
+
676
+ - `UriNormalizer::PRESERVING_NORMALIZATIONS`
677
+
678
+ Default normalizations which only include the ones that preserve semantics.
679
+
680
+ - `UriNormalizer::CAPITALIZE_PERCENT_ENCODING`
681
+
682
+ All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
683
+
684
+ Example: `http://example.org/a%c2%b1b` → `http://example.org/a%C2%B1b`
685
+
686
+ - `UriNormalizer::DECODE_UNRESERVED_CHARACTERS`
687
+
688
+ Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of
689
+ ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should
690
+ not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved
691
+ characters by URI normalizers.
692
+
693
+ Example: `http://example.org/%7Eusern%61me/` → `http://example.org/~username/`
694
+
695
+ - `UriNormalizer::CONVERT_EMPTY_PATH`
696
+
697
+ Converts the empty path to "/" for http and https URIs.
698
+
699
+ Example: `http://example.org` → `http://example.org/`
700
+
701
+ - `UriNormalizer::REMOVE_DEFAULT_HOST`
702
+
703
+ Removes the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host
704
+ "localhost". All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` are equivalent according to
705
+ RFC 3986.
706
+
707
+ Example: `file://localhost/myfile` → `file:///myfile`
708
+
709
+ - `UriNormalizer::REMOVE_DEFAULT_PORT`
710
+
711
+ Removes the default port of the given URI scheme from the URI.
712
+
713
+ Example: `http://example.org:80/` → `http://example.org/`
714
+
715
+ - `UriNormalizer::REMOVE_DOT_SEGMENTS`
716
+
717
+ Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would
718
+ change the semantics of the URI reference.
719
+
720
+ Example: `http://example.org/../a/b/../c/./d.html` → `http://example.org/a/c/d.html`
721
+
722
+ - `UriNormalizer::REMOVE_DUPLICATE_SLASHES`
723
+
724
+ Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes
725
+ and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization
726
+ may change the semantics. Encoded slashes (%2F) are not removed.
727
+
728
+ Example: `http://example.org//foo///bar.html` → `http://example.org/foo/bar.html`
729
+
730
+ - `UriNormalizer::SORT_QUERY_PARAMETERS`
731
+
732
+ Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be
733
+ significant (this is not defined by the standard). So this normalization is not safe and may change the semantics
734
+ of the URI.
735
+
736
+ Example: `?lang=en&article=fred` → `?article=fred&lang=en`
737
+
738
+ ### `GuzzleHttp\Psr7\UriNormalizer::isEquivalent`
739
+
740
+ `public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool`
741
+
742
+ Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given
743
+ `$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent.
744
+ This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
745
+ equivalence or difference of relative references does not mean anything.
vendor/ralouphie/getallheaders/composer.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ralouphie/getallheaders",
3
+ "description": "A polyfill for getallheaders.",
4
+ "license": "MIT",
5
+ "authors": [
6
+ {
7
+ "name": "Ralph Khattar",
8
+ "email": "ralph.khattar@gmail.com"
9
+ }
10
+ ],
11
+ "require": {
12
+ "php": ">=5.6"
13
+ },
14
+ "require-dev": {
15
+ "phpunit/phpunit": "^5 || ^6.5",
16
+ "php-coveralls/php-coveralls": "^2.1"
17
+ },
18
+ "autoload": {
19
+ "files": ["src/getallheaders.php"]
20
+ },
21
+ "autoload-dev": {
22
+ "psr-4": {
23
+ "getallheaders\\Tests\\": "tests/"
24
+ }
25
+ }
26
+ }