Version Description
- Welcome page for new installations
- UI improvements
- Bugfixes
Download this release
Release Info
Developer | jasperroel |
Plugin | Call Now Button |
Version | 1.1.11 |
Comparing to | |
See all releases |
Code changes from version 1.1.10 to 1.1.11
- call-now-button.php +2 -2
- readme.txt +6 -1
- resources/images/button-scheduler.png +0 -0
- resources/images/buttonbar.png +0 -0
- resources/images/cnb-icons-actions.png +0 -0
- resources/images/icon-256x256.png +0 -0
- resources/images/multibutton.png +0 -0
- resources/images/whatsapp-modal.png +0 -0
- resources/js/action-type-to-icon-text.js +5 -4
- resources/js/call-now-button.js +2 -2
- resources/js/deactivation.js +6 -4
- resources/js/premium-activation.js +110 -0
- resources/js/preview.js +14 -5
- resources/js/settings.js +7 -106
- resources/style/call-now-button.css +124 -0
- src/CallNowButton.php +40 -6
- src/admin/CnbAdminAjax.php +33 -20
- src/admin/api/CnbDeleteResult.php +4 -3
- src/admin/button/CnbButtonView.php +3 -1
- src/admin/deactivation/Activation.php +55 -3
- src/admin/domain/CnbDomainViewEdit.php +1 -1
- src/admin/domain/partials/CnbDomainViewUpgradeOverview.php +5 -5
- src/admin/getting-started/class-getting-started-controller.php +13 -0
- src/admin/getting-started/class-getting-started-router.php +14 -0
- src/admin/getting-started/class-getting-started-view.php +115 -0
- src/admin/getting-started/index.php +1 -0
- src/admin/legacy/CnbLegacyController.php +0 -9
- src/admin/legacy/CnbLegacyEdit.php +118 -84
- src/admin/legacy/CnbLegacyUpgrade.php +21 -16
- src/admin/partials/CnbFooter.php +4 -4
- src/admin/partials/CnbHeaderNotices.php +19 -14
- src/admin/settings/CnbApiKeyActivatedView.php +6 -6
- src/admin/settings/CnbSettingsController.php +23 -6
- src/admin/settings/CnbSettingsViewEdit.php +15 -24
- src/autoload.php +3 -0
- src/composer.json +0 -6
- src/composer.lock +0 -1884
- src/utils/CnbUtils.php +5 -0
- src/utils/class-cnb-sentry.php +3 -14
- src/vendor/composer/InstalledVersions.php +7 -7
- src/vendor/composer/autoload_files.php +1 -1
- src/vendor/composer/autoload_psr4.php +3 -7
- src/vendor/composer/autoload_static.php +10 -30
- src/vendor/composer/installed.json +98 -454
- src/vendor/composer/installed.php +43 -95
- src/vendor/composer/platform_check.php +2 -2
- src/vendor/guzzlehttp/psr7/CHANGELOG.md +11 -4
- src/vendor/guzzlehttp/psr7/README.md +17 -3
- src/vendor/guzzlehttp/psr7/composer.json +1 -1
- src/vendor/guzzlehttp/psr7/src/CachingStream.php +5 -0
- src/vendor/guzzlehttp/psr7/src/DroppingStream.php +3 -0
- src/vendor/guzzlehttp/psr7/src/FnStream.php +1 -0
- src/vendor/guzzlehttp/psr7/src/InflateStream.php +3 -0
- src/vendor/guzzlehttp/psr7/src/LazyOpenStream.php +1 -0
- src/vendor/guzzlehttp/psr7/src/LimitStream.php +3 -0
- src/vendor/guzzlehttp/psr7/src/MultipartStream.php +3 -0
- src/vendor/guzzlehttp/psr7/src/NoSeekStream.php +3 -0
- src/vendor/guzzlehttp/psr7/src/UriComparator.php +52 -0
- src/vendor/http-interop/http-factory-guzzle/.github/workflows/ci.yaml +0 -60
- src/vendor/http-interop/http-factory-guzzle/LICENSE +0 -21
- src/vendor/http-interop/http-factory-guzzle/README.md +0 -7
- src/vendor/http-interop/http-factory-guzzle/composer.json +0 -37
- src/vendor/http-interop/http-factory-guzzle/src/RequestFactory.php +0 -15
- src/vendor/http-interop/http-factory-guzzle/src/ResponseFactory.php +0 -15
- src/vendor/http-interop/http-factory-guzzle/src/ServerRequestFactory.php +0 -24
- src/vendor/http-interop/http-factory-guzzle/src/StreamFactory.php +0 -26
- src/vendor/http-interop/http-factory-guzzle/src/UploadedFileFactory.php +0 -25
- src/vendor/http-interop/http-factory-guzzle/src/UriFactory.php +0 -15
- src/vendor/php-http/curl-client/.github/workflows/Build-Test.yml +81 -0
- src/vendor/php-http/curl-client/.php_cs +9 -0
- src/vendor/php-http/curl-client/CHANGELOG.md +211 -0
- src/vendor/{symfony/service-contracts → php-http/curl-client}/LICENSE +1 -1
- src/vendor/php-http/curl-client/README.md +42 -0
- src/vendor/php-http/curl-client/composer.json +57 -0
- src/vendor/php-http/curl-client/puli.json +242 -0
- src/vendor/php-http/curl-client/src/Client.php +398 -0
- src/vendor/php-http/curl-client/src/CurlPromise.php +111 -0
- src/vendor/php-http/curl-client/src/MultiRunner.php +131 -0
- src/vendor/php-http/curl-client/src/PromiseCore.php +252 -0
- src/vendor/php-http/curl-client/src/ResponseBuilder.php +24 -0
- src/vendor/php-http/discovery/CHANGELOG.md +4 -0
- src/vendor/php-http/discovery/src/Exception.php +3 -1
- src/vendor/psr/container/.gitignore +0 -3
- src/vendor/psr/container/LICENSE +0 -21
- src/vendor/psr/container/README.md +0 -13
- src/vendor/psr/container/composer.json +0 -22
- src/vendor/psr/container/src/ContainerExceptionInterface.php +0 -12
- src/vendor/psr/container/src/ContainerInterface.php +0 -36
- src/vendor/psr/container/src/NotFoundExceptionInterface.php +0 -10
- src/vendor/sentry/sentry/CHANGELOG.md +9 -0
- src/vendor/sentry/sentry/composer.json +1 -1
- src/vendor/sentry/sentry/src/Monolog/Handler.php +27 -1
- src/vendor/sentry/sentry/src/State/Scope.php +2 -6
- src/vendor/sentry/sentry/src/Tracing/GuzzleTracingMiddleware.php +1 -1
- src/vendor/sentry/sentry/src/Tracing/Span.php +21 -7
- src/vendor/sentry/sentry/src/Tracing/Transaction.php +1 -0
- src/vendor/symfony/http-client-contracts/.gitignore +0 -3
- src/vendor/symfony/http-client-contracts/CHANGELOG.md +0 -5
- src/vendor/symfony/http-client-contracts/ChunkInterface.php +0 -71
- src/vendor/symfony/http-client-contracts/Exception/ClientExceptionInterface.php +0 -21
- src/vendor/symfony/http-client-contracts/Exception/DecodingExceptionInterface.php +0 -21
- src/vendor/symfony/http-client-contracts/Exception/ExceptionInterface.php +0 -21
- src/vendor/symfony/http-client-contracts/Exception/HttpExceptionInterface.php +0 -24
- src/vendor/symfony/http-client-contracts/Exception/RedirectionExceptionInterface.php +0 -21
- src/vendor/symfony/http-client-contracts/Exception/ServerExceptionInterface.php +0 -21
- src/vendor/symfony/http-client-contracts/Exception/TimeoutExceptionInterface.php +0 -21
- src/vendor/symfony/http-client-contracts/Exception/TransportExceptionInterface.php +0 -21
- src/vendor/symfony/http-client-contracts/HttpClientInterface.php +0 -95
- src/vendor/symfony/http-client-contracts/LICENSE +0 -19
- src/vendor/symfony/http-client-contracts/README.md +0 -9
- src/vendor/symfony/http-client-contracts/ResponseInterface.php +0 -109
- src/vendor/symfony/http-client-contracts/ResponseStreamInterface.php +0 -26
- src/vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php +0 -192
- src/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php +0 -1132
- src/vendor/symfony/http-client-contracts/Test/TestHttpServer.php +0 -46
- src/vendor/symfony/http-client-contracts/composer.json +0 -37
- src/vendor/symfony/http-client/AmpHttpClient.php +0 -176
- src/vendor/symfony/http-client/AsyncDecoratorTrait.php +0 -48
- src/vendor/symfony/http-client/CHANGELOG.md +0 -54
- src/vendor/symfony/http-client/CachingHttpClient.php +0 -152
- src/vendor/symfony/http-client/Chunk/DataChunk.php +0 -87
- src/vendor/symfony/http-client/Chunk/ErrorChunk.php +0 -140
- src/vendor/symfony/http-client/Chunk/FirstChunk.php +0 -28
- src/vendor/symfony/http-client/Chunk/InformationalChunk.php +0 -35
- src/vendor/symfony/http-client/Chunk/LastChunk.php +0 -28
- src/vendor/symfony/http-client/Chunk/ServerSentEvent.php +0 -79
- src/vendor/symfony/http-client/CurlHttpClient.php +0 -551
- src/vendor/symfony/http-client/DataCollector/HttpClientDataCollector.php +0 -170
- src/vendor/symfony/http-client/DecoratorTrait.php +0 -66
- src/vendor/symfony/http-client/DependencyInjection/HttpClientPass.php +0 -51
- src/vendor/symfony/http-client/EventSourceHttpClient.php +0 -159
- src/vendor/symfony/http-client/Exception/ClientException.php +0 -24
- src/vendor/symfony/http-client/Exception/EventSourceException.php +0 -21
- src/vendor/symfony/http-client/Exception/HttpExceptionTrait.php +0 -78
- src/vendor/symfony/http-client/Exception/InvalidArgumentException.php +0 -21
- src/vendor/symfony/http-client/Exception/JsonException.php +0 -23
- src/vendor/symfony/http-client/Exception/RedirectionException.php +0 -24
- src/vendor/symfony/http-client/Exception/ServerException.php +0 -24
- src/vendor/symfony/http-client/Exception/TimeoutException.php +0 -21
- src/vendor/symfony/http-client/Exception/TransportException.php +0 -21
- src/vendor/symfony/http-client/HttpClient.php +0 -78
- src/vendor/symfony/http-client/HttpClientTrait.php +0 -684
- src/vendor/symfony/http-client/HttpOptions.php +0 -331
- src/vendor/symfony/http-client/HttplugClient.php +0 -271
- src/vendor/symfony/http-client/Internal/AmpBody.php +0 -142
- src/vendor/symfony/http-client/Internal/AmpClientState.php +0 -217
- src/vendor/symfony/http-client/Internal/AmpListener.php +0 -183
- src/vendor/symfony/http-client/Internal/AmpResolver.php +0 -52
- src/vendor/symfony/http-client/Internal/Canary.php +0 -40
- src/vendor/symfony/http-client/Internal/ClientState.php +0 -26
- src/vendor/symfony/http-client/Internal/CurlClientState.php +0 -148
- src/vendor/symfony/http-client/Internal/DnsCache.php +0 -39
- src/vendor/symfony/http-client/Internal/HttplugWaitLoop.php +0 -141
- src/vendor/symfony/http-client/Internal/NativeClientState.php +0 -47
- src/vendor/symfony/http-client/Internal/PushedResponse.php +0 -41
- src/vendor/symfony/http-client/LICENSE +0 -19
- src/vendor/symfony/http-client/MockHttpClient.php +0 -124
- src/vendor/symfony/http-client/NativeHttpClient.php +0 -468
- src/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php +0 -132
- src/vendor/symfony/http-client/Psr18Client.php +0 -239
- src/vendor/symfony/http-client/README.md +0 -27
- src/vendor/symfony/http-client/Response/AmpResponse.php +0 -461
- src/vendor/symfony/http-client/Response/AsyncContext.php +0 -189
- src/vendor/symfony/http-client/Response/AsyncResponse.php +0 -478
- src/vendor/symfony/http-client/Response/CommonResponseTrait.php +0 -185
- src/vendor/symfony/http-client/Response/CurlResponse.php +0 -474
- src/vendor/symfony/http-client/Response/HttplugPromise.php +0 -80
- src/vendor/symfony/http-client/Response/MockResponse.php +0 -339
- src/vendor/symfony/http-client/Response/NativeResponse.php +0 -376
- src/vendor/symfony/http-client/Response/ResponseStream.php +0 -54
- src/vendor/symfony/http-client/Response/StreamWrapper.php +0 -304
- src/vendor/symfony/http-client/Response/StreamableInterface.php +0 -35
- src/vendor/symfony/http-client/Response/TraceableResponse.php +0 -219
- src/vendor/symfony/http-client/Response/TransportResponseTrait.php +0 -312
- src/vendor/symfony/http-client/Retry/GenericRetryStrategy.php +0 -115
- src/vendor/symfony/http-client/Retry/RetryStrategyInterface.php +0 -36
- src/vendor/symfony/http-client/RetryableHttpClient.php +0 -169
- src/vendor/symfony/http-client/ScopingHttpClient.php +0 -131
- src/vendor/symfony/http-client/TraceableHttpClient.php +0 -120
- src/vendor/symfony/http-client/composer.json +0 -53
- src/vendor/symfony/service-contracts/.gitignore +0 -3
- src/vendor/symfony/service-contracts/Attribute/Required.php +0 -25
- src/vendor/symfony/service-contracts/Attribute/SubscribedService.php +0 -33
- src/vendor/symfony/service-contracts/CHANGELOG.md +0 -5
- src/vendor/symfony/service-contracts/README.md +0 -9
- src/vendor/symfony/service-contracts/ResetInterface.php +0 -30
- src/vendor/symfony/service-contracts/ServiceLocatorTrait.php +0 -128
- src/vendor/symfony/service-contracts/ServiceProviderInterface.php +0 -36
- src/vendor/symfony/service-contracts/ServiceSubscriberInterface.php +0 -53
- src/vendor/symfony/service-contracts/ServiceSubscriberTrait.php +0 -115
- src/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php +0 -95
- src/vendor/symfony/service-contracts/composer.json +0 -42
call-now-button.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Call Now Button
|
4 |
Plugin URI: https://callnowbutton.com
|
5 |
Description: Mobile visitors will see a <strong>Call Now Button</strong> on your website. Easy to use but flexible to meet more demanding requirements. Change placement and color, hide on specific pages, track how many people click them or conversions of your Google Ads campaigns. It's all optional but possible.
|
6 |
-
Version: 1.1.
|
7 |
Author: Jerry Rietveld
|
8 |
Author URI: https://www.callnowbutton.com
|
9 |
GitHub Plugin URI: https://github.com/callnowbutton/wp-plugin
|
@@ -26,7 +26,7 @@ License: GPL2
|
|
26 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
27 |
*/
|
28 |
|
29 |
-
define('CNB_VERSION', '1.1.
|
30 |
define('CNB_NAME', 'Call Now Button');
|
31 |
define('CNB_BASENAME', plugin_basename(__FILE__));
|
32 |
define('CNB_BASEFOLDER', plugin_basename(dirname(__FILE__)));
|
3 |
Plugin Name: Call Now Button
|
4 |
Plugin URI: https://callnowbutton.com
|
5 |
Description: Mobile visitors will see a <strong>Call Now Button</strong> on your website. Easy to use but flexible to meet more demanding requirements. Change placement and color, hide on specific pages, track how many people click them or conversions of your Google Ads campaigns. It's all optional but possible.
|
6 |
+
Version: 1.1.11
|
7 |
Author: Jerry Rietveld
|
8 |
Author URI: https://www.callnowbutton.com
|
9 |
GitHub Plugin URI: https://github.com/callnowbutton/wp-plugin
|
26 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
27 |
*/
|
28 |
|
29 |
+
define('CNB_VERSION', '1.1.11');
|
30 |
define('CNB_NAME', 'Call Now Button');
|
31 |
define('CNB_BASENAME', plugin_basename(__FILE__));
|
32 |
define('CNB_BASEFOLDER', plugin_basename(dirname(__FILE__)));
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: call button, click to call, convert, call now button, contact button
|
|
5 |
Requires at least: 3.9
|
6 |
Requires PHP: 5.4
|
7 |
Tested up to: 6.0
|
8 |
-
Stable tag: 1.1.
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
|
@@ -111,6 +111,11 @@ Yes, you can upgrade to Premium to enable tons of extra features. Checkout [call
|
|
111 |
|
112 |
|
113 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
114 |
= 1.1.10 =
|
115 |
* Introduced geo targeting (Premium PRO)
|
116 |
* New PRO feature: Reveal at scroll height (Premium PRO)
|
5 |
Requires at least: 3.9
|
6 |
Requires PHP: 5.4
|
7 |
Tested up to: 6.0
|
8 |
+
Stable tag: 1.1.11
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
|
111 |
|
112 |
|
113 |
== Changelog ==
|
114 |
+
= 1.1.11 =
|
115 |
+
* Welcome page for new installations
|
116 |
+
* UI improvements
|
117 |
+
* Bugfixes
|
118 |
+
|
119 |
= 1.1.10 =
|
120 |
* Introduced geo targeting (Premium PRO)
|
121 |
* New PRO feature: Reveal at scroll height (Premium PRO)
|
resources/images/button-scheduler.png
ADDED
Binary file
|
resources/images/buttonbar.png
ADDED
Binary file
|
resources/images/cnb-icons-actions.png
ADDED
Binary file
|
resources/images/icon-256x256.png
ADDED
Binary file
|
resources/images/multibutton.png
ADDED
Binary file
|
resources/images/whatsapp-modal.png
ADDED
Binary file
|
resources/js/action-type-to-icon-text.js
CHANGED
@@ -25,9 +25,9 @@ function cnbActiontypeToIcontext(actionType) {
|
|
25 |
}
|
26 |
}
|
27 |
|
28 |
-
function cnb_trigger_rerender(jEle) {
|
|
|
29 |
jEle.trigger('change')
|
30 |
-
|
31 |
}
|
32 |
/**
|
33 |
* Updates the iconText property (and rerenders the preview)
|
@@ -51,7 +51,8 @@ function cnb_change_icon_text(ele) {
|
|
51 |
cnb_action_icon_type.val(jQuery(ele).data('icon-type'))
|
52 |
|
53 |
// Force an update to the preview
|
54 |
-
|
|
|
55 |
} else {
|
56 |
// Maybe it's the button-edit multibutton options
|
57 |
// If so, get the parent and find if the 2 data attributes are set
|
@@ -63,7 +64,7 @@ function cnb_change_icon_text(ele) {
|
|
63 |
const iconTypeEle = jQuery('#' + iconType)
|
64 |
iconTypeEle.val(jQuery(ele).data('icon-type'))
|
65 |
iconTextEle.val(val)
|
66 |
-
iconTextEle
|
67 |
}
|
68 |
}
|
69 |
return false
|
25 |
}
|
26 |
}
|
27 |
|
28 |
+
function cnb_trigger_rerender(jEle, doNotExpand = false) {
|
29 |
+
window.cnbMultiDoNotExpand = doNotExpand
|
30 |
jEle.trigger('change')
|
|
|
31 |
}
|
32 |
/**
|
33 |
* Updates the iconText property (and rerenders the preview)
|
51 |
cnb_action_icon_type.val(jQuery(ele).data('icon-type'))
|
52 |
|
53 |
// Force an update to the preview
|
54 |
+
// Since the open icon changed, ensure it is CLOSED now (so you can see the change)
|
55 |
+
cnb_trigger_rerender(cnb_action_icon_text, true)
|
56 |
} else {
|
57 |
// Maybe it's the button-edit multibutton options
|
58 |
// If so, get the parent and find if the 2 data attributes are set
|
64 |
const iconTypeEle = jQuery('#' + iconType)
|
65 |
iconTypeEle.val(jQuery(ele).data('icon-type'))
|
66 |
iconTextEle.val(val)
|
67 |
+
cnb_trigger_rerender(iconTextEle)
|
68 |
}
|
69 |
}
|
70 |
return false
|
resources/js/call-now-button.js
CHANGED
@@ -64,13 +64,13 @@ function cnb_hide_on_show_always() {
|
|
64 |
jQuery('.cnb_hide_on_show_always').hide();
|
65 |
|
66 |
// Hide Domain Timezone notice
|
67 |
-
jQuery('
|
68 |
} else {
|
69 |
// Show all items specific for Scheduler
|
70 |
jQuery('.cnb_hide_on_show_always').show();
|
71 |
|
72 |
// Show Domain Timezone notice (and move to the correct place)
|
73 |
-
const domainTimezoneNotice = jQuery('
|
74 |
domainTimezoneNotice.show();
|
75 |
const domainTimezoneNoticePlaceholder = jQuery('#domain-timezone-notice-placeholder');
|
76 |
if (domainTimezoneNoticePlaceholder.length !== 0) {
|
64 |
jQuery('.cnb_hide_on_show_always').hide();
|
65 |
|
66 |
// Hide Domain Timezone notice
|
67 |
+
jQuery('.cnb-notice-domain-timezone-unsupported').parent('.notice').hide();
|
68 |
} else {
|
69 |
// Show all items specific for Scheduler
|
70 |
jQuery('.cnb_hide_on_show_always').show();
|
71 |
|
72 |
// Show Domain Timezone notice (and move to the correct place)
|
73 |
+
const domainTimezoneNotice = jQuery('.cnb-notice-domain-timezone-unsupported').parent('.notice');
|
74 |
domainTimezoneNotice.show();
|
75 |
const domainTimezoneNoticePlaceholder = jQuery('#domain-timezone-notice-placeholder');
|
76 |
if (domainTimezoneNoticePlaceholder.length !== 0) {
|
resources/js/deactivation.js
CHANGED
@@ -1,5 +1,3 @@
|
|
1 |
-
const cnb_tally_deactivate_plugin_form_id = 'waQ6eb'
|
2 |
-
|
3 |
function cnb_add_deactivation_init() {
|
4 |
cnb_add_deactivation_popup_tally()
|
5 |
}
|
@@ -8,9 +6,9 @@ function cnb_add_deactivation_init() {
|
|
8 |
* Called when the Call Now Button plugin's "Deactivate" link is clicked
|
9 |
*/
|
10 |
function cnb_add_deactivation_popup_tally() {
|
|
|
11 |
const original_link = jQuery('#deactivate-call-now-button')
|
12 |
original_link.on('click', (event) => {
|
13 |
-
event.preventDefault()
|
14 |
|
15 |
const options = {
|
16 |
layout: 'modal',
|
@@ -31,7 +29,11 @@ function cnb_add_deactivation_popup_tally() {
|
|
31 |
}, 7000)
|
32 |
},
|
33 |
}
|
34 |
-
Tally
|
|
|
|
|
|
|
|
|
35 |
})
|
36 |
}
|
37 |
|
|
|
|
|
1 |
function cnb_add_deactivation_init() {
|
2 |
cnb_add_deactivation_popup_tally()
|
3 |
}
|
6 |
* Called when the Call Now Button plugin's "Deactivate" link is clicked
|
7 |
*/
|
8 |
function cnb_add_deactivation_popup_tally() {
|
9 |
+
const cnb_tally_deactivate_plugin_form_id = 'waQ6eb'
|
10 |
const original_link = jQuery('#deactivate-call-now-button')
|
11 |
original_link.on('click', (event) => {
|
|
|
12 |
|
13 |
const options = {
|
14 |
layout: 'modal',
|
29 |
}, 7000)
|
30 |
},
|
31 |
}
|
32 |
+
// Check if Tally actually is loaded
|
33 |
+
if (Tally) {
|
34 |
+
event.preventDefault()
|
35 |
+
Tally.openPopup(cnb_tally_deactivate_plugin_form_id, options)
|
36 |
+
}
|
37 |
})
|
38 |
}
|
39 |
|
resources/js/premium-activation.js
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function cnb_email_activation_reenable_fields(form, showSomethingWentWrong = true) {
|
2 |
+
let errorMessage = ''
|
3 |
+
if (showSomethingWentWrong) {
|
4 |
+
errorMessage = '<h3 class="title">Something went wrong!</h3>' +
|
5 |
+
'<p>Something has gone wrong and we do not know why...</p>' +
|
6 |
+
'<p>As unlikely as it is, our service might be experiencing issues (check <a href="https://status.callnowbutton.com" target="_blank">our status page</a>).</p>' +
|
7 |
+
'<p>If you think you\'ve found a bug, please report it at our <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a>.' +
|
8 |
+
'<p>Technical details:</p>'
|
9 |
+
}
|
10 |
+
const errorDetails = '<p style="color:red"><span class="cnb_email_activation_errors"></span></p>'
|
11 |
+
|
12 |
+
const submitButton = jQuery(form).find('[name="cnb_email_activation_submit"]')
|
13 |
+
jQuery(form).find('[name="cnb_email_activation_address"]').removeAttr("disabled")
|
14 |
+
submitButton.removeAttr("disabled")
|
15 |
+
submitButton.val("Activate Premium")
|
16 |
+
jQuery(form).find('.cnb_email_activation_message').html(errorMessage + errorDetails)
|
17 |
+
}
|
18 |
+
|
19 |
+
function cnb_email_activation_taking_too_long(form) {
|
20 |
+
const errorMessage = '<h3 class="title">Hmm, that\'s taking a while...</h3>' +
|
21 |
+
'<p>This call should not take this long. Please try again in a minute or so.</p>' +
|
22 |
+
'<p>As unlikely as it is, our service might be experiencing issues (check <a href="https://status.callnowbutton.com" target="_blank">our status page</a>).</p>' +
|
23 |
+
'<p>If you think you\'ve found a bug, please report it at our <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a>.'
|
24 |
+
const errorDetails = '<p>Technical details:</p><p style="color:red"><span class="cnb_email_activation_errors"></span></p>'
|
25 |
+
|
26 |
+
const submitButton = jQuery(form).find('[name="cnb_email_activation_submit"]')
|
27 |
+
jQuery(form).find('[name="cnb_email_activation_address"]').removeAttr("disabled")
|
28 |
+
submitButton.removeAttr("disabled")
|
29 |
+
submitButton.val("Activate Premium")
|
30 |
+
jQuery(form).find('.cnb_email_activation_message').html(errorMessage + errorDetails)
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* This calls the admin-ajax action called 'cnb_email_activation' (function cnb_admin_cnb_email_activation)
|
35 |
+
*/
|
36 |
+
function cnb_email_activation(form) {
|
37 |
+
const email_address = jQuery(form).find('[name="cnb_email_activation_address"]').val()
|
38 |
+
|
39 |
+
// Prep data
|
40 |
+
const data = {
|
41 |
+
'action': 'cnb_email_activation',
|
42 |
+
'admin_email': email_address
|
43 |
+
}
|
44 |
+
|
45 |
+
// Disable the Email and Button fields (reactivate in case of errors)
|
46 |
+
const submitButton = jQuery(form).find('[name="cnb_email_activation_submit"]')
|
47 |
+
jQuery(form).find('[name="cnb_email_activation_address"]').attr("disabled", "disabled")
|
48 |
+
submitButton.attr("disabled", "disabled")
|
49 |
+
submitButton.val("Check your e-mail")
|
50 |
+
|
51 |
+
// Clear the error fields
|
52 |
+
jQuery(form).find('.cnb_email_activation_message').empty()
|
53 |
+
jQuery(form).find('[name="cnb_email_activation_address"]').empty()
|
54 |
+
|
55 |
+
const statusTimeout = 5000
|
56 |
+
const fn_is_taking_too_long = () => cnb_email_activation_taking_too_long(form)
|
57 |
+
const takingTooLongTimer = setTimeout(fn_is_taking_too_long, statusTimeout)
|
58 |
+
|
59 |
+
// Send remove request
|
60 |
+
jQuery.post(ajaxurl, data)
|
61 |
+
.done((result) => {
|
62 |
+
if (result && result.email) {
|
63 |
+
clearTimeout(takingTooLongTimer)
|
64 |
+
jQuery(form).find('.cnb_email_activation_message').html('<span class="cnb_check_email_message">Check your inbox for an activation email sent to <strong><span class="cnb_email_activation_address"></span></strong>.</span>')
|
65 |
+
jQuery(form).find('span.cnb_email_activation_address').text(result.email)
|
66 |
+
}
|
67 |
+
|
68 |
+
if (result && result.errors) {
|
69 |
+
clearTimeout(takingTooLongTimer)
|
70 |
+
const keys = Object.keys(result.errors)
|
71 |
+
|
72 |
+
let showSomethingWentWrong = true
|
73 |
+
if (keys.length === 1 && (keys[0] === 'CNB_EMAIL_INVALID'|| keys[0] === 'CNB_EMAIL_EMPTY')) {
|
74 |
+
// Skip showing the big block with links, since we know exactly what's going on
|
75 |
+
showSomethingWentWrong = false
|
76 |
+
}
|
77 |
+
cnb_email_activation_reenable_fields(form, showSomethingWentWrong)
|
78 |
+
|
79 |
+
keys.forEach((key) => {
|
80 |
+
// Create Text Nodes to ensure escaping of the content
|
81 |
+
const codeMsg = document.createTextNode(key)
|
82 |
+
const errorMsg = document.createTextNode(result.errors[key])
|
83 |
+
const code = jQuery('<code>').append(codeMsg)
|
84 |
+
jQuery(form).find('.cnb_email_activation_errors').append('<br />', code, ': ', errorMsg)
|
85 |
+
})
|
86 |
+
}
|
87 |
+
})
|
88 |
+
.fail((result) => {
|
89 |
+
clearTimeout(takingTooLongTimer)
|
90 |
+
cnb_email_activation_reenable_fields(form)
|
91 |
+
|
92 |
+
// Create Text Nodes to ensure escaping of the content
|
93 |
+
const codeMsg = document.createTextNode(result.status + ' ' + result.statusText)
|
94 |
+
const errorMsg = document.createTextNode(result.responseText)
|
95 |
+
const code = jQuery('<code>').append(codeMsg)
|
96 |
+
jQuery(form).find('.cnb_email_activation_errors').append('<br />', code, ': ', errorMsg)
|
97 |
+
})
|
98 |
+
return false
|
99 |
+
}
|
100 |
+
|
101 |
+
function cnb_email_activation_init() {
|
102 |
+
jQuery('form.cnb_email_activation').on('submit', (event) => {
|
103 |
+
const form = jQuery(event.target)
|
104 |
+
return cnb_email_activation(form)
|
105 |
+
})
|
106 |
+
}
|
107 |
+
|
108 |
+
jQuery(() => {
|
109 |
+
cnb_email_activation_init()
|
110 |
+
})
|
resources/js/preview.js
CHANGED
@@ -194,9 +194,15 @@ async function livePreview() {
|
|
194 |
// pass "false" to ensure we do NOT add the client's native observers
|
195 |
const result = await CNB.render(cnbData, false)
|
196 |
|
197 |
-
|
|
|
|
|
|
|
|
|
198 |
// The "parsedData.action_id" check is to ensure it does not expand on a FULL or MULTI overview page
|
199 |
-
if
|
|
|
|
|
200 |
const whatsappButton = jQuery('.call-now-button a[data-action-type="WHATSAPP"]')
|
201 |
if (whatsappButton.length > 0) {
|
202 |
whatsappButton[0].dispatchEvent(new window.CustomEvent('toggle'))
|
@@ -204,10 +210,13 @@ async function livePreview() {
|
|
204 |
}
|
205 |
|
206 |
// If there is a Multibutton, expand it (test this AFTER the modal, so we only toggle if it isn't ALREADY expanded)
|
207 |
-
|
208 |
-
|
209 |
-
multiButton
|
|
|
|
|
210 |
}
|
|
|
211 |
|
212 |
// Move the result into a new special div (if found)
|
213 |
const button = jQuery('.cnb-single.call-now-button, .cnb-full.call-now-button, .cnb-multi.call-now-button').detach()
|
194 |
// pass "false" to ensure we do NOT add the client's native observers
|
195 |
const result = await CNB.render(cnbData, false)
|
196 |
|
197 |
+
const isWhatsappEditScreen = parsedData.action_id && parsedData.actions &&
|
198 |
+
parsedData.actions[parsedData.action_id] &&
|
199 |
+
parsedData.actions[parsedData.action_id].actionType === 'WHATSAPP'
|
200 |
+
|
201 |
+
// If there is a Whatsapp modal, trigger it
|
202 |
// The "parsedData.action_id" check is to ensure it does not expand on a FULL or MULTI overview page
|
203 |
+
// We should also NOT expand if the edit screen for the current type is NOT a WhatsApp edit screen
|
204 |
+
// Basically, only expand on a WhatsApp edit screen
|
205 |
+
if (isWhatsappEditScreen) {
|
206 |
const whatsappButton = jQuery('.call-now-button a[data-action-type="WHATSAPP"]')
|
207 |
if (whatsappButton.length > 0) {
|
208 |
whatsappButton[0].dispatchEvent(new window.CustomEvent('toggle'))
|
210 |
}
|
211 |
|
212 |
// If there is a Multibutton, expand it (test this AFTER the modal, so we only toggle if it isn't ALREADY expanded)
|
213 |
+
if (!window.cnbMultiDoNotExpand) {
|
214 |
+
const multiButton = jQuery('.cnb-multi.call-now-button:not(.cnb-expand) .cnb-floating-main')
|
215 |
+
if (multiButton.length > 0) {
|
216 |
+
multiButton[0].dispatchEvent(new window.CustomEvent('toggle'))
|
217 |
+
}
|
218 |
}
|
219 |
+
window.cnbMultiDoNotExpand = undefined
|
220 |
|
221 |
// Move the result into a new special div (if found)
|
222 |
const button = jQuery('.cnb-single.call-now-button, .cnb-full.call-now-button, .cnb-multi.call-now-button').detach()
|
resources/js/settings.js
CHANGED
@@ -1,105 +1,3 @@
|
|
1 |
-
function cnb_email_activation_reenable_fields(showSomethingWentWrong = true) {
|
2 |
-
let errorMessage = ''
|
3 |
-
if (showSomethingWentWrong) {
|
4 |
-
errorMessage = '<h3 class="title">Something went wrong!</h3>' +
|
5 |
-
'<p>Something has gone wrong and we do not know why...</p>' +
|
6 |
-
'<p>As unlikely as it is, our service might be experiencing issues (check <a href="https://status.callnowbutton.com">our status page</a>).</p>' +
|
7 |
-
'<p>If you think you\'ve found a bug, please report it at our <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a>.' +
|
8 |
-
'<p>Technical details:</p>';
|
9 |
-
}
|
10 |
-
const errorDetails = '<p style="color:red"><span id="cnb_email_activation_details"></span></p>';
|
11 |
-
|
12 |
-
const submitButton = jQuery('#cnb_email_activation_alternate')
|
13 |
-
jQuery('#cnb_email_activation_alternate_address').removeAttr("disabled")
|
14 |
-
submitButton.removeAttr("disabled")
|
15 |
-
submitButton.val("Activate Premium")
|
16 |
-
jQuery('#cnb_email_activation').html(errorMessage + errorDetails);
|
17 |
-
}
|
18 |
-
|
19 |
-
function cnb_email_activation_taking_too_long() {
|
20 |
-
const errorMessage = '<h3 class="title">Hmm, that\'s taking a while...</h3>' +
|
21 |
-
'<p>This call should not take this long. Please try again in a minute or so.</p>' +
|
22 |
-
'<p>As unlikely as it is, our service might be experiencing issues (check <a href="https://status.callnowbutton.com">our status page</a>).</p>' +
|
23 |
-
'<p>If you think you\'ve found a bug, please report it at our <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a>.';
|
24 |
-
const errorDetails = '<p>Technical details:</p><p style="color:red"><span id="cnb_email_activation_details"></span></p>';
|
25 |
-
|
26 |
-
const submitButton = jQuery('#cnb_email_activation_alternate')
|
27 |
-
jQuery('#cnb_email_activation_alternate_address').removeAttr("disabled")
|
28 |
-
submitButton.removeAttr("disabled")
|
29 |
-
submitButton.val("Activate Premium")
|
30 |
-
jQuery('#cnb_email_activation').html(errorMessage + errorDetails);
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* This calls the admin-ajax action called 'cnb_email_activation' (function cnb_admin_cnb_email_activation)
|
35 |
-
*/
|
36 |
-
function cnb_email_activation(admin_email) {
|
37 |
-
// Prep data
|
38 |
-
const data = {
|
39 |
-
'action': 'cnb_email_activation',
|
40 |
-
'admin_email': admin_email
|
41 |
-
};
|
42 |
-
|
43 |
-
// Disable the Email and Button fields (reactivate in case of errors)
|
44 |
-
const submitButton = jQuery('#cnb_email_activation_alternate')
|
45 |
-
jQuery('#cnb_email_activation_alternate_address').attr("disabled", "disabled")
|
46 |
-
submitButton.attr("disabled", "disabled")
|
47 |
-
submitButton.val("Check your e-mail")
|
48 |
-
|
49 |
-
// Clear the error fields
|
50 |
-
jQuery('#cnb_email_activation').empty()
|
51 |
-
jQuery('#cnb_email_activation_email').empty()
|
52 |
-
|
53 |
-
const statusTimeout = 5000
|
54 |
-
const takingTooLongTimer = setTimeout(cnb_email_activation_taking_too_long, statusTimeout)
|
55 |
-
|
56 |
-
// Send remove request
|
57 |
-
jQuery.post(ajaxurl, data)
|
58 |
-
.done((result) => {
|
59 |
-
if (result && result.email) {
|
60 |
-
clearTimeout(takingTooLongTimer)
|
61 |
-
jQuery('#cnb_email_activation').html('<span class="cnb_check_email_message">Check your inbox for an activation email sent to <strong><span id="cnb_email_activation_email"></span></strong>.</span>')
|
62 |
-
jQuery('#cnb_email_activation_email').text(result.email)
|
63 |
-
}
|
64 |
-
|
65 |
-
if (result && result.errors) {
|
66 |
-
clearTimeout(takingTooLongTimer)
|
67 |
-
const keys = Object.keys(result.errors)
|
68 |
-
|
69 |
-
let showSomethingWentWrong = true
|
70 |
-
if (keys.length === 1 && (keys[0] === 'CNB_EMAIL_INVALID'|| keys[0] === 'CNB_EMAIL_EMPTY')) {
|
71 |
-
// Skip showing the big block with links, since we know exactly what's going on
|
72 |
-
showSomethingWentWrong = false
|
73 |
-
}
|
74 |
-
cnb_email_activation_reenable_fields(showSomethingWentWrong)
|
75 |
-
|
76 |
-
keys.forEach((key) => {
|
77 |
-
// Create Text Nodes to ensure escaping of the content
|
78 |
-
const codeMsg = document.createTextNode(key)
|
79 |
-
const errorMsg = document.createTextNode(result.errors[key])
|
80 |
-
const code = jQuery('<code>').append(codeMsg)
|
81 |
-
jQuery('#cnb_email_activation_details').append('<br />', code, ': ', errorMsg);
|
82 |
-
})
|
83 |
-
}
|
84 |
-
})
|
85 |
-
.fail((result) => {
|
86 |
-
clearTimeout(takingTooLongTimer)
|
87 |
-
cnb_email_activation_reenable_fields()
|
88 |
-
|
89 |
-
// Create Text Nodes to ensure escaping of the content
|
90 |
-
const codeMsg = document.createTextNode(result.status + ' ' + result.statusText)
|
91 |
-
const errorMsg = document.createTextNode(result.responseText)
|
92 |
-
const code = jQuery('<code>').append(codeMsg)
|
93 |
-
jQuery('#cnb_email_activation_details').append('<br />', code, ': ', errorMsg);
|
94 |
-
});
|
95 |
-
return false;
|
96 |
-
}
|
97 |
-
|
98 |
-
function cnb_email_activation_submit() {
|
99 |
-
const alternate_admin_email = jQuery('#cnb_email_activation_alternate_address').val()
|
100 |
-
return cnb_email_activation(alternate_admin_email);
|
101 |
-
}
|
102 |
-
|
103 |
// Note: IDE marks this as unused, but it is used by settings-edit.php ("Delete API key")
|
104 |
function cnb_delete_apikey() {
|
105 |
const apiKeyField = jQuery(".call-now-button-plugin #cnb_api_key")
|
@@ -136,10 +34,13 @@ function cnb_ask_for_feedback_disable_cloud() {
|
|
136 |
userId: jQuery('#cnb_user_id').text()
|
137 |
}
|
138 |
}
|
139 |
-
if
|
140 |
-
|
141 |
-
|
142 |
-
|
|
|
|
|
|
|
143 |
}
|
144 |
})
|
145 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
// Note: IDE marks this as unused, but it is used by settings-edit.php ("Delete API key")
|
2 |
function cnb_delete_apikey() {
|
3 |
const apiKeyField = jQuery(".call-now-button-plugin #cnb_api_key")
|
34 |
userId: jQuery('#cnb_user_id').text()
|
35 |
}
|
36 |
}
|
37 |
+
// Check if Tally actually is loaded
|
38 |
+
if (Tally) {
|
39 |
+
if (!isChecked) {
|
40 |
+
Tally.openPopup(cnb_tally_deactivate_premium_form_id, options)
|
41 |
+
} else {
|
42 |
+
Tally.closePopup(cnb_tally_deactivate_premium_form_id)
|
43 |
+
}
|
44 |
}
|
45 |
})
|
46 |
}
|
resources/style/call-now-button.css
CHANGED
@@ -1226,3 +1226,127 @@ span.cnb-pro-badge {
|
|
1226 |
color: rgb(0 153 0);
|
1227 |
background: rgba(0, 153, 0, 0.125);
|
1228 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1226 |
color: rgb(0 153 0);
|
1227 |
background: rgba(0, 153, 0, 0.125);
|
1228 |
}
|
1229 |
+
.cnb-welcome-page {
|
1230 |
+
padding-right: 20px;
|
1231 |
+
padding-top: 70px;
|
1232 |
+
}
|
1233 |
+
@media screen and (max-width: 782px) {
|
1234 |
+
.cnb-welcome-page {
|
1235 |
+
padding-right: 10px;
|
1236 |
+
}
|
1237 |
+
}
|
1238 |
+
.cnb-welcome-blocks {
|
1239 |
+
max-width:860px;
|
1240 |
+
box-sizing: border-box;
|
1241 |
+
padding:20px;
|
1242 |
+
margin: 20px auto;
|
1243 |
+
border:1px solid #ccc;
|
1244 |
+
position: relative;
|
1245 |
+
text-align: center;
|
1246 |
+
background-color: #fff;
|
1247 |
+
}
|
1248 |
+
.cnb-welcome-blocks .cnb-logo {
|
1249 |
+
margin-top:calc(-35px - 64px);
|
1250 |
+
padding:15px 15px 13px;
|
1251 |
+
border-radius: 50%;
|
1252 |
+
border:1px solid #ccc;
|
1253 |
+
background: #fff;
|
1254 |
+
}
|
1255 |
+
.cnb-welcome-blocks h3 {
|
1256 |
+
font-weight: normal;
|
1257 |
+
color:#666;
|
1258 |
+
line-height: 1.4;
|
1259 |
+
}
|
1260 |
+
.cnb-welcome-blocks .cnb-divider {
|
1261 |
+
height: 0;
|
1262 |
+
border-top:1px solid #ccc;
|
1263 |
+
margin: 30px 0;
|
1264 |
+
}
|
1265 |
+
.cnb-welcome-blocks .cnb-block .cnb-divider {
|
1266 |
+
border-color:#ddd;
|
1267 |
+
}
|
1268 |
+
.cnb-welcome-blocks .cnb-block {
|
1269 |
+
max-width: 700px;
|
1270 |
+
margin: 20px auto;
|
1271 |
+
text-align: center;
|
1272 |
+
}
|
1273 |
+
.cnb-welcome-blocks .cnb-block img {
|
1274 |
+
max-width: 700px;
|
1275 |
+
width: 100%;
|
1276 |
+
height: auto;
|
1277 |
+
}
|
1278 |
+
.cnb-welcome-blocks .cnb-block img.cnb-width-80 {
|
1279 |
+
max-width: calc(700px * 0.8);
|
1280 |
+
width: 80%;
|
1281 |
+
}
|
1282 |
+
.cnb-welcome-blocks .cnb-block img.cnb-width-70 {
|
1283 |
+
max-width: calc(700px * 0.7);
|
1284 |
+
width: 70%;
|
1285 |
+
}
|
1286 |
+
.cnb-welcome-blocks .cnb-extra-space {
|
1287 |
+
margin-top:30px;
|
1288 |
+
margin-bottom: 30px;
|
1289 |
+
}
|
1290 |
+
.cnb-welcome-blocks .cnb-features-list {
|
1291 |
+
max-width: 80%;
|
1292 |
+
display: flex;
|
1293 |
+
text-align: left;
|
1294 |
+
}
|
1295 |
+
.cnb-welcome-blocks .cnb-features-list .cnb-column {
|
1296 |
+
padding: 0 15px;
|
1297 |
+
box-sizing: border-box;
|
1298 |
+
width: 50%;
|
1299 |
+
}
|
1300 |
+
@media screen and (max-width: 750px) {
|
1301 |
+
.cnb-welcome-blocks .cnb-features-list .cnb-column p {
|
1302 |
+
display: none;
|
1303 |
+
}
|
1304 |
+
.cnb-welcome-blocks .cnb-features-list {
|
1305 |
+
max-width: 100%;
|
1306 |
+
}
|
1307 |
+
}
|
1308 |
+
@media screen and (max-width: 550px) {
|
1309 |
+
.cnb-welcome-blocks .cnb-features-list {
|
1310 |
+
flex-direction: column;
|
1311 |
+
}
|
1312 |
+
.cnb-welcome-blocks .cnb-features-list .cnb-column {
|
1313 |
+
width: 100%;
|
1314 |
+
text-align: center;
|
1315 |
+
}
|
1316 |
+
}
|
1317 |
+
.cnb-welcome-blocks .cnb-signup-box {
|
1318 |
+
max-width:550px;
|
1319 |
+
}
|
1320 |
+
.cnb-welcome-blocks .cnb-signup-box .cnb_activation_input_field {
|
1321 |
+
padding:8.5px 10px;
|
1322 |
+
}
|
1323 |
+
|
1324 |
+
.cnb-welcome-blocks .cnb-features-list p {
|
1325 |
+
font-size:14px;
|
1326 |
+
}
|
1327 |
+
.cnb-welcome-blocks .cnb_activation_input_field {
|
1328 |
+
width: calc(100% - 195px);
|
1329 |
+
}
|
1330 |
+
@media screen and (max-width: 450px) {
|
1331 |
+
.cnb-welcome-blocks .cnb_activation_input_field {
|
1332 |
+
width: 100%;
|
1333 |
+
}
|
1334 |
+
}
|
1335 |
+
.cnb-welcome-blocks .button.button-primary {
|
1336 |
+
background: #009900;
|
1337 |
+
border-color: #009900;
|
1338 |
+
font-size:16px;
|
1339 |
+
padding:5px 30px;
|
1340 |
+
}
|
1341 |
+
.cnb-welcome-blocks .button.button-primary:hover,
|
1342 |
+
.cnb-welcome-blocks .button.button-primary:active {
|
1343 |
+
background: #007700;
|
1344 |
+
border-color: #007700;
|
1345 |
+
}
|
1346 |
+
.cnb-welcome-blocks .button.button-primary:focus {
|
1347 |
+
box-shadow: 0 0 0 1px #fff, 0 0 0 3px #009900;
|
1348 |
+
}
|
1349 |
+
.cnb_disabled_feature,
|
1350 |
+
.cnb_disabled_feature th {
|
1351 |
+
color:rgba(29,35,39,0.5);
|
1352 |
+
}
|
src/CallNowButton.php
CHANGED
@@ -15,10 +15,12 @@ use cnb\admin\button\CnbButtonRouter;
|
|
15 |
use cnb\admin\CnbAdminAjax;
|
16 |
use cnb\admin\condition\CnbConditionController;
|
17 |
use cnb\admin\condition\CnbConditionRouter;
|
|
|
18 |
use cnb\admin\deactivation\Deactivation;
|
19 |
use cnb\admin\domain\CnbDomainController;
|
20 |
use cnb\admin\domain\CnbDomainRouter;
|
21 |
-
use cnb\admin\
|
|
|
22 |
use cnb\admin\legacy\CnbLegacyEdit;
|
23 |
use cnb\admin\legacy\CnbLegacyUpgrade;
|
24 |
use cnb\admin\profile\CnbProfileController;
|
@@ -51,11 +53,9 @@ class CallNowButton {
|
|
51 |
$menu_page_title = 'Call Now Button<span class="awaiting-mod" id="cnb-nav-counter" style="display: none">' . $counter . '</span>';
|
52 |
$menu_page_position = $cnb_cloud_hosting ? 30 : 66;
|
53 |
|
54 |
-
$
|
55 |
-
$
|
56 |
-
if (
|
57 |
-
$counter ++;
|
58 |
-
}
|
59 |
|
60 |
// Detect errors (specific, - Premium enabled, but API key is not present yet)
|
61 |
if ( $cnb_cloud_hosting && ! array_key_exists( 'api_key', $cnb_options ) ) {
|
@@ -132,6 +132,28 @@ class CallNowButton {
|
|
132 |
add_submenu_page( CNB_SLUG, $plugin_title, 'Settings', 'manage_options', CNB_SLUG . '-settings', array( $settings_router, 'render' ) );
|
133 |
}
|
134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
public function plugin_meta( $links, $file ) {
|
136 |
$cnb_options = get_option( 'cnb' );
|
137 |
$cnb_utils = new CnbUtils();
|
@@ -300,6 +322,12 @@ class CallNowButton {
|
|
300 |
array( CNB_SLUG . '-call-now-button' ),
|
301 |
CNB_VERSION,
|
302 |
true );
|
|
|
|
|
|
|
|
|
|
|
|
|
303 |
wp_register_script(
|
304 |
CNB_SLUG . '-action-edit-scheduler',
|
305 |
plugins_url( '../resources/js/action-edit-scheduler.js', __FILE__ ),
|
@@ -395,12 +423,18 @@ class CallNowButton {
|
|
395 |
|
396 |
public function register_global_actions() {
|
397 |
add_action( 'admin_menu', array( $this, 'register_admin_pages' ) );
|
|
|
|
|
|
|
398 |
add_filter( 'plugin_row_meta', array( $this, 'plugin_meta' ), 10, 2 );
|
399 |
add_filter( 'plugin_action_links_' . CNB_BASENAME, array( $this, 'plugin_add_action_link' ) );
|
400 |
|
401 |
add_action( 'admin_init', array( $this, 'options_init' ) );
|
402 |
add_action( 'admin_init', array( $this, 'register_styles_and_scripts' ) );
|
403 |
|
|
|
|
|
|
|
404 |
$deactivation = new Deactivation();
|
405 |
add_action( 'admin_init', array($deactivation, 'register_deactivation_popup' ) );
|
406 |
|
15 |
use cnb\admin\CnbAdminAjax;
|
16 |
use cnb\admin\condition\CnbConditionController;
|
17 |
use cnb\admin\condition\CnbConditionRouter;
|
18 |
+
use cnb\admin\deactivation\Activation;
|
19 |
use cnb\admin\deactivation\Deactivation;
|
20 |
use cnb\admin\domain\CnbDomainController;
|
21 |
use cnb\admin\domain\CnbDomainRouter;
|
22 |
+
use cnb\admin\gettingstarted\GettingStartedController;
|
23 |
+
use cnb\admin\gettingstarted\GettingStartedRouter;
|
24 |
use cnb\admin\legacy\CnbLegacyEdit;
|
25 |
use cnb\admin\legacy\CnbLegacyUpgrade;
|
26 |
use cnb\admin\profile\CnbProfileController;
|
53 |
$menu_page_title = 'Call Now Button<span class="awaiting-mod" id="cnb-nav-counter" style="display: none">' . $counter . '</span>';
|
54 |
$menu_page_position = $cnb_cloud_hosting ? 30 : 66;
|
55 |
|
56 |
+
$header_notices = new CnbHeaderNotices();
|
57 |
+
$has_changelog = $header_notices->upgrade_notice();
|
58 |
+
if ($has_changelog) $counter++;
|
|
|
|
|
59 |
|
60 |
// Detect errors (specific, - Premium enabled, but API key is not present yet)
|
61 |
if ( $cnb_cloud_hosting && ! array_key_exists( 'api_key', $cnb_options ) ) {
|
132 |
add_submenu_page( CNB_SLUG, $plugin_title, 'Settings', 'manage_options', CNB_SLUG . '-settings', array( $settings_router, 'render' ) );
|
133 |
}
|
134 |
|
135 |
+
public function register_welcome_page() {
|
136 |
+
$utils = new CnbUtils();
|
137 |
+
$controller = new GettingStartedController();
|
138 |
+
$menu_slug = $controller->get_slug();
|
139 |
+
|
140 |
+
if ( $utils->get_query_val( 'page' ) === $menu_slug ) {
|
141 |
+
$getting_started_router = new GettingStartedRouter();
|
142 |
+
add_dashboard_page(
|
143 |
+
esc_html__( 'Welcome to Call Now Button' ),
|
144 |
+
esc_html__( 'Call Now Button' ),
|
145 |
+
'manage_options',
|
146 |
+
$menu_slug,
|
147 |
+
array( $getting_started_router, 'render' )
|
148 |
+
);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
public function hide_welcome_page() {
|
153 |
+
$controller = new GettingStartedController();
|
154 |
+
remove_submenu_page('index.php', $controller->get_slug());
|
155 |
+
}
|
156 |
+
|
157 |
public function plugin_meta( $links, $file ) {
|
158 |
$cnb_options = get_option( 'cnb' );
|
159 |
$cnb_utils = new CnbUtils();
|
322 |
array( CNB_SLUG . '-call-now-button' ),
|
323 |
CNB_VERSION,
|
324 |
true );
|
325 |
+
wp_register_script(
|
326 |
+
CNB_SLUG . '-premium-activation',
|
327 |
+
plugins_url( '../resources/js/premium-activation.js', __FILE__ ),
|
328 |
+
array( CNB_SLUG . '-call-now-button' ),
|
329 |
+
CNB_VERSION,
|
330 |
+
true );
|
331 |
wp_register_script(
|
332 |
CNB_SLUG . '-action-edit-scheduler',
|
333 |
plugins_url( '../resources/js/action-edit-scheduler.js', __FILE__ ),
|
423 |
|
424 |
public function register_global_actions() {
|
425 |
add_action( 'admin_menu', array( $this, 'register_admin_pages' ) );
|
426 |
+
add_action( 'admin_menu', array( $this, 'register_welcome_page' ) );
|
427 |
+
add_action( 'admin_head', array( $this, 'hide_welcome_page' ) );
|
428 |
+
|
429 |
add_filter( 'plugin_row_meta', array( $this, 'plugin_meta' ), 10, 2 );
|
430 |
add_filter( 'plugin_action_links_' . CNB_BASENAME, array( $this, 'plugin_add_action_link' ) );
|
431 |
|
432 |
add_action( 'admin_init', array( $this, 'options_init' ) );
|
433 |
add_action( 'admin_init', array( $this, 'register_styles_and_scripts' ) );
|
434 |
|
435 |
+
$activation = new Activation();
|
436 |
+
add_action( 'admin_init', array($activation, 'redirect_to_welcome_page' ) );
|
437 |
+
|
438 |
$deactivation = new Deactivation();
|
439 |
add_action( 'admin_init', array($deactivation, 'register_deactivation_popup' ) );
|
440 |
|
src/admin/CnbAdminAjax.php
CHANGED
@@ -134,30 +134,43 @@ class CnbAdminAjax {
|
|
134 |
$domain_controller = new CnbDomainController();
|
135 |
|
136 |
$plans = CnbAppRemotePayment::cnb_remote_get_plans();
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
$
|
141 |
-
$
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
|
156 |
wp_send_json( array(
|
157 |
'eur_per_month' => $eur_yearly_per_month,
|
158 |
-
'eur_discount' => $
|
159 |
'usd_per_month' => $usd_yearly_per_month,
|
160 |
-
'usd_discount' => $
|
161 |
) );
|
162 |
do_action( 'cnb_finish' );
|
163 |
wp_die();
|
134 |
$domain_controller = new CnbDomainController();
|
135 |
|
136 |
$plans = CnbAppRemotePayment::cnb_remote_get_plans();
|
137 |
+
|
138 |
+
// Hardcoded fallback values in case the API call fails
|
139 |
+
$eur_yearly_per_month = 4.16;
|
140 |
+
$eur_discount = 17;
|
141 |
+
$usd_yearly_per_month = 4.99;
|
142 |
+
$usd_discount = 17;
|
143 |
+
|
144 |
+
if (is_array($plans)) {
|
145 |
+
$eur_yearly_plan = array_filter( $plans, function ( $plan ) {
|
146 |
+
return $plan->nickname === 'powered-by-eur-yearly';
|
147 |
+
} );
|
148 |
+
$eur_yearly_plan = array_pop( $eur_yearly_plan );
|
149 |
+
$eur_yearly_per_month = round( $eur_yearly_plan->price / 12.0, 2 );
|
150 |
+
|
151 |
+
$usd_yearly_plan = array_filter( $plans, function ( $plan ) {
|
152 |
+
return $plan->nickname === 'powered-by-usd-yearly';
|
153 |
+
} );
|
154 |
+
$usd_yearly_plan = array_pop( $usd_yearly_plan );
|
155 |
+
$usd_yearly_per_month = round( $usd_yearly_plan->price / 12.0, 2 );
|
156 |
+
|
157 |
+
$eur_monthly_plan = array_filter( $plans, function ( $plan ) {
|
158 |
+
return $plan->nickname === 'powered-by-eur-monthly';
|
159 |
+
} );
|
160 |
+
$usd_monthly_plan = array_filter( $plans, function ( $plan ) {
|
161 |
+
return $plan->nickname === 'powered-by-usd-monthly';
|
162 |
+
} );
|
163 |
+
|
164 |
+
// Calculate discounts
|
165 |
+
$eur_discount = $domain_controller->get_discount_percentage( $eur_yearly_plan, array_pop( $eur_monthly_plan ) );
|
166 |
+
$usd_discount = $domain_controller->get_discount_percentage( $usd_yearly_plan, array_pop( $usd_monthly_plan ) );
|
167 |
+
}
|
168 |
|
169 |
wp_send_json( array(
|
170 |
'eur_per_month' => $eur_yearly_per_month,
|
171 |
+
'eur_discount' => $eur_discount,
|
172 |
'usd_per_month' => $usd_yearly_per_month,
|
173 |
+
'usd_discount' => $usd_discount,
|
174 |
) );
|
175 |
do_action( 'cnb_finish' );
|
176 |
wp_die();
|
src/admin/api/CnbDeleteResult.php
CHANGED
@@ -33,14 +33,15 @@ class CnbDeleteResult {
|
|
33 |
*
|
34 |
* @param $object stdClass|array|WP_Error|null
|
35 |
*
|
36 |
-
* @return CnbDeleteResult
|
37 |
*/
|
38 |
public static function fromObject( $object ) {
|
|
|
39 |
if ( is_wp_error( $object ) ) {
|
40 |
-
|
|
|
41 |
}
|
42 |
|
43 |
-
$result = new CnbDeleteResult();
|
44 |
// phpcs:ignore PHPCompatibility.FunctionUse
|
45 |
$result->success = boolval( CnbUtils::getPropertyOrNull( $object, 'success' ) );
|
46 |
$result->id = CnbUtils::getPropertyOrNull( $object, 'id' );
|
33 |
*
|
34 |
* @param $object stdClass|array|WP_Error|null
|
35 |
*
|
36 |
+
* @return CnbDeleteResult
|
37 |
*/
|
38 |
public static function fromObject( $object ) {
|
39 |
+
$result = new CnbDeleteResult();
|
40 |
if ( is_wp_error( $object ) ) {
|
41 |
+
$result->object = $object;
|
42 |
+
return $result;
|
43 |
}
|
44 |
|
|
|
45 |
// phpcs:ignore PHPCompatibility.FunctionUse
|
46 |
$result->success = boolval( CnbUtils::getPropertyOrNull( $object, 'success' ) );
|
47 |
$result->id = CnbUtils::getPropertyOrNull( $object, 'id' );
|
src/admin/button/CnbButtonView.php
CHANGED
@@ -87,8 +87,10 @@ class CnbButtonView {
|
|
87 |
// Set filter
|
88 |
$this->set_button_filter( $cnb_cloud_domain, $wp_list_table );
|
89 |
|
90 |
-
// If users come to this page before activating, we need the -settings JS for the activation notice
|
91 |
wp_enqueue_script( CNB_SLUG . '-settings' );
|
|
|
|
|
92 |
add_action( 'cnb_header_name', array( $this, 'header' ) );
|
93 |
|
94 |
$data = $wp_list_table->prepare_items();
|
87 |
// Set filter
|
88 |
$this->set_button_filter( $cnb_cloud_domain, $wp_list_table );
|
89 |
|
90 |
+
// If users come to this page before activating, we need the -settings/-premium-activation JS for the activation notice
|
91 |
wp_enqueue_script( CNB_SLUG . '-settings' );
|
92 |
+
wp_enqueue_script( CNB_SLUG . '-premium-activation' );
|
93 |
+
|
94 |
add_action( 'cnb_header_name', array( $this, 'header' ) );
|
95 |
|
96 |
$data = $wp_list_table->prepare_items();
|
src/admin/deactivation/Activation.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
namespace cnb\admin\deactivation;
|
4 |
|
|
|
5 |
use cnb\CallNowButton;
|
6 |
|
7 |
/**
|
@@ -9,6 +10,17 @@ use cnb\CallNowButton;
|
|
9 |
*/
|
10 |
class Activation {
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* This is called /during/ the activation process.
|
14 |
*
|
@@ -18,12 +30,52 @@ class Activation {
|
|
18 |
* @return void
|
19 |
*/
|
20 |
public static function onActivation() {
|
21 |
-
|
22 |
-
$cnb = new CallNowButton();
|
23 |
-
$cnb->options_init();
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
$options = get_option('cnb');
|
26 |
$options['activation_time'] = time();
|
27 |
update_option( 'cnb', $options );
|
28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
2 |
|
3 |
namespace cnb\admin\deactivation;
|
4 |
|
5 |
+
use cnb\admin\gettingstarted\GettingStartedController;
|
6 |
use cnb\CallNowButton;
|
7 |
|
8 |
/**
|
10 |
*/
|
11 |
class Activation {
|
12 |
|
13 |
+
/**
|
14 |
+
* @var CallNowButton
|
15 |
+
*/
|
16 |
+
private $cnb;
|
17 |
+
|
18 |
+
private $activation_transient = 'call-now-button_activation_redirect';
|
19 |
+
|
20 |
+
public function __construct() {
|
21 |
+
$this->cnb = new CallNowButton();
|
22 |
+
}
|
23 |
+
|
24 |
/**
|
25 |
* This is called /during/ the activation process.
|
26 |
*
|
30 |
* @return void
|
31 |
*/
|
32 |
public static function onActivation() {
|
33 |
+
$activation = new Activation();
|
|
|
|
|
34 |
|
35 |
+
$activation->init_activation();
|
36 |
+
$activation->capture_activation_time();
|
37 |
+
$activation->ensure_redirect();
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* This has to called manually, since Activation is before the `admin_init` stage!
|
42 |
+
*
|
43 |
+
* @return void
|
44 |
+
*/
|
45 |
+
private function init_activation() {
|
46 |
+
$this->cnb->options_init();
|
47 |
+
|
48 |
+
}
|
49 |
+
private function capture_activation_time() {
|
50 |
$options = get_option('cnb');
|
51 |
$options['activation_time'] = time();
|
52 |
update_option( 'cnb', $options );
|
53 |
}
|
54 |
+
|
55 |
+
private function ensure_redirect() {
|
56 |
+
set_transient($this->activation_transient, true);
|
57 |
+
}
|
58 |
+
|
59 |
+
public function redirect_to_welcome_page() {
|
60 |
+
$should_redirect = get_transient($this->activation_transient);
|
61 |
+
if (!$should_redirect) {
|
62 |
+
return;
|
63 |
+
}
|
64 |
+
delete_transient($this->activation_transient);
|
65 |
+
|
66 |
+
$controller = new GettingStartedController();
|
67 |
+
$menu_slug = $controller->get_slug();
|
68 |
+
|
69 |
+
$url = admin_url( 'index.php' );
|
70 |
+
$redirect_link =
|
71 |
+
add_query_arg(
|
72 |
+
array(
|
73 |
+
'page' => $menu_slug,
|
74 |
+
),
|
75 |
+
$url );
|
76 |
+
|
77 |
+
$redirect_url = esc_url_raw( $redirect_link );
|
78 |
+
wp_safe_redirect( $redirect_url );
|
79 |
+
exit;
|
80 |
+
}
|
81 |
}
|
src/admin/domain/CnbDomainViewEdit.php
CHANGED
@@ -80,7 +80,7 @@ class CnbDomainViewEdit {
|
|
80 |
<?php
|
81 |
if ( $domain->type !== 'PRO' && ! empty( $domain->id ) ) {
|
82 |
echo '<a href="' . esc_url( $upgrade_link ) . '">Upgrade!</a>
|
83 |
-
<p class="description">The FREE plan offers all features but adds delicate branding to your buttons.</p>';
|
84 |
}
|
85 |
?>
|
86 |
</td>
|
80 |
<?php
|
81 |
if ( $domain->type !== 'PRO' && ! empty( $domain->id ) ) {
|
82 |
echo '<a href="' . esc_url( $upgrade_link ) . '">Upgrade!</a>
|
83 |
+
<p class="description">The FREE plan offers 99% of all features but adds delicate branding to your buttons.</p>';
|
84 |
}
|
85 |
?>
|
86 |
</td>
|
src/admin/domain/partials/CnbDomainViewUpgradeOverview.php
CHANGED
@@ -38,7 +38,7 @@ class CnbDomainViewUpgradeOverview {
|
|
38 |
* @return void
|
39 |
*/
|
40 |
function render( $domain ) {
|
41 |
-
if ( $domain->type !== 'FREE' ) { ?><p>Your domain is currently on the
|
42 |
<code><?php echo esc_html( $domain->type ) ?></code> plan.</p>
|
43 |
<?php } ?>
|
44 |
|
@@ -147,7 +147,7 @@ class CnbDomainViewUpgradeOverview {
|
|
147 |
?>
|
148 |
<div class="pricebox">
|
149 |
<h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly <span class="cnb-green">Save <?php echo esc_html( $annual_discount ); ?>%!</span></h3>
|
150 |
-
<div class="benefit">🧰 All features from
|
151 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
152 |
<div class="benefit">🌍 Include and exclude countries</div>
|
153 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
@@ -174,7 +174,7 @@ class CnbDomainViewUpgradeOverview {
|
|
174 |
?>
|
175 |
<div class="pricebox">
|
176 |
<h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
|
177 |
-
<div class="benefit">🧰 All features from
|
178 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
179 |
<div class="benefit">🌍 Include and exclude countries</div>
|
180 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
@@ -208,7 +208,7 @@ class CnbDomainViewUpgradeOverview {
|
|
208 |
?>
|
209 |
<div class="pricebox">
|
210 |
<h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly <span class="cnb-green">Save <?php echo esc_html( $annual_discount ); ?>%!</span></h3>
|
211 |
-
<div class="benefit">🧰 All features from
|
212 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
213 |
<div class="benefit">🌍 Include and exclude countries</div>
|
214 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
@@ -234,7 +234,7 @@ class CnbDomainViewUpgradeOverview {
|
|
234 |
?>
|
235 |
<div class="pricebox">
|
236 |
<h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
|
237 |
-
<div class="benefit">🧰 All features from
|
238 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
239 |
<div class="benefit">🌍 Include and exclude countries</div>
|
240 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
38 |
* @return void
|
39 |
*/
|
40 |
function render( $domain ) {
|
41 |
+
if ( $domain->type !== 'FREE' ) { ?><p>Your domain is currently on the
|
42 |
<code><?php echo esc_html( $domain->type ) ?></code> plan.</p>
|
43 |
<?php } ?>
|
44 |
|
147 |
?>
|
148 |
<div class="pricebox">
|
149 |
<h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly <span class="cnb-green">Save <?php echo esc_html( $annual_discount ); ?>%!</span></h3>
|
150 |
+
<div class="benefit">🧰 All features from Cloud</div>
|
151 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
152 |
<div class="benefit">🌍 Include and exclude countries</div>
|
153 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
174 |
?>
|
175 |
<div class="pricebox">
|
176 |
<h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
|
177 |
+
<div class="benefit">🧰 All features from Cloud</div>
|
178 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
179 |
<div class="benefit">🌍 Include and exclude countries</div>
|
180 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
208 |
?>
|
209 |
<div class="pricebox">
|
210 |
<h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly <span class="cnb-green">Save <?php echo esc_html( $annual_discount ); ?>%!</span></h3>
|
211 |
+
<div class="benefit">🧰 All features from Cloud</div>
|
212 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
213 |
<div class="benefit">🌍 Include and exclude countries</div>
|
214 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
234 |
?>
|
235 |
<div class="pricebox">
|
236 |
<h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
|
237 |
+
<div class="benefit">🧰 All features from Cloud</div>
|
238 |
<div class="benefit">✨ "Powered by" notice removed</div>
|
239 |
<div class="benefit">🌍 Include and exclude countries</div>
|
240 |
<div class="benefit">↕️ Set scroll height for buttons to appear</div>
|
src/admin/getting-started/class-getting-started-controller.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace cnb\admin\gettingstarted;
|
4 |
+
|
5 |
+
// don't load directly
|
6 |
+
defined( 'ABSPATH' ) || die( '-1' );
|
7 |
+
|
8 |
+
class GettingStartedController {
|
9 |
+
|
10 |
+
public function get_slug() {
|
11 |
+
return CNB_SLUG . '-getting-started';
|
12 |
+
}
|
13 |
+
}
|
src/admin/getting-started/class-getting-started-router.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace cnb\admin\gettingstarted;
|
4 |
+
|
5 |
+
// don't load directly
|
6 |
+
defined( 'ABSPATH' ) || die( '-1' );
|
7 |
+
|
8 |
+
class GettingStartedRouter {
|
9 |
+
|
10 |
+
public function render() {
|
11 |
+
$view = new GettingStartedView();
|
12 |
+
$view->render();
|
13 |
+
}
|
14 |
+
}
|
src/admin/getting-started/class-getting-started-view.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace cnb\admin\gettingstarted;
|
4 |
+
|
5 |
+
// don't load directly
|
6 |
+
defined( 'ABSPATH' ) || die( '-1' );
|
7 |
+
|
8 |
+
use cnb\CnbHeaderNotices;
|
9 |
+
|
10 |
+
class GettingStartedView {
|
11 |
+
public function render() {
|
12 |
+
|
13 |
+
wp_enqueue_style( CNB_SLUG . '-styling' );
|
14 |
+
wp_enqueue_script( CNB_SLUG . '-premium-activation' );
|
15 |
+
|
16 |
+
// Create link to the regular legacy page
|
17 |
+
$url = admin_url( 'admin.php' );
|
18 |
+
$link =
|
19 |
+
add_query_arg(
|
20 |
+
array(
|
21 |
+
'page' => 'call-now-button'
|
22 |
+
),
|
23 |
+
$url );
|
24 |
+
?>
|
25 |
+
<div class="cnb-welcome-page">
|
26 |
+
<div class="cnb-welcome-blocks cnb-extra-top">
|
27 |
+
|
28 |
+
<img class="cnb-logo" src="<?php echo esc_url(WP_PLUGIN_URL . '/' . CNB_BASEFOLDER . '/resources/images/icon-256x256.png');?>" width="128" height="128" alt="Call Now Button icon" />
|
29 |
+
<h1>Welcome to Call Now Button</h1>
|
30 |
+
<h3>Thank you for choosing Call Now Button - The web's most popular click-to-call button</h3>
|
31 |
+
<div class="cnb-divider"></div>
|
32 |
+
<h2>Create a (free) account to enable additional features:</h2>
|
33 |
+
<div class="cnb-block cnb-features-list">
|
34 |
+
<div class="cnb-column cnb-col-1">
|
35 |
+
<h3>🎁 Additional actions</h3>
|
36 |
+
<p>SMS/Text, Email, Maps, URLs, Scroll to point, WhatsApp, Messenger, Telegram, Signal</p>
|
37 |
+
<h3>🆕 Lots of buttons</h3>
|
38 |
+
<p>Multiple buttons for your website, even on a single page</p>
|
39 |
+
<h3>🗂️ Multi action buttons</h3>
|
40 |
+
<p>Multibutton (expandable) and Buttonbar (full width)</p>
|
41 |
+
<h3>💬 WhatsApp chat modal</h3>
|
42 |
+
<p>A WhatsApp chat panel to slide into the screen</p>
|
43 |
+
</div>
|
44 |
+
|
45 |
+
<div class="cnb-column cnb-col-2">
|
46 |
+
<h3>🖥️ All devices</h3>
|
47 |
+
<p>Desktop/laptop and mobile support</p>
|
48 |
+
<h3>🎯 Advanced page targeting</h3>
|
49 |
+
<p>Create smart rules for your buttons to appear</p>
|
50 |
+
<h3>🕘 Scheduler</h3>
|
51 |
+
<p>Create a weekly schedule for your buttons</p>
|
52 |
+
<h3>👋 Animations</h3>
|
53 |
+
<p>Add extra attention grabbing animations</p>
|
54 |
+
<h3>🎨 Icon picker</h3>
|
55 |
+
<p>Select the right icon for your button</p>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
<div class="cnb-block cnb-signup-box">
|
59 |
+
<h2>Sign up now to get all this and more</h2>
|
60 |
+
<?php echo CnbHeaderNotices::cnb_settings_email_activation_input(); // phpcs:ignore WordPress.Security ?>
|
61 |
+
</div>
|
62 |
+
<div class="cnb-divider"></div>
|
63 |
+
<p><i>Only need a Call button? <a href="<?php echo esc_url( $link ) ?>">Continue without an account</a>.</i></p>
|
64 |
+
</div>
|
65 |
+
<div class="cnb-welcome-blocks">
|
66 |
+
|
67 |
+
<div class="cnb-block">
|
68 |
+
<h1>Why do I need an account?</h1>
|
69 |
+
<h3>With an account you enabable the cloud features from callnowbutton.com.</h3>
|
70 |
+
<p>Here's a close-up of some of the cloud features:</p>
|
71 |
+
<div class="cnb-divider"></div>
|
72 |
+
|
73 |
+
<h2>🎁 More actions and icons 🎁</h2>
|
74 |
+
<img class="cnb-width-80 cnb-extra-space" src="<?php echo esc_url(WP_PLUGIN_URL . '/' . CNB_BASEFOLDER . '/resources/images/cnb-icons-actions.png');?>" alt="WhatsApp modal">
|
75 |
+
<p>New actions include WhatsApp, SMS/Text, Email, Signal, Telegram, Messenger, Location, Link and Smooth scroll to point.</p>
|
76 |
+
|
77 |
+
<div class="cnb-divider"></div>
|
78 |
+
|
79 |
+
<h2>💬 WhatsApp chat modal 💬</h2>
|
80 |
+
<img src="<?php echo esc_url(WP_PLUGIN_URL . '/' . CNB_BASEFOLDER . '/resources/images/whatsapp-modal.png');?>" alt="WhatsApp modal">
|
81 |
+
<p>Start the WhatsApp conversation on your website.</p>
|
82 |
+
|
83 |
+
<div class="cnb-divider"></div>
|
84 |
+
|
85 |
+
<h2>💎 Multibutton 💎</h2>
|
86 |
+
<img class="cnb-width-80" src="<?php echo esc_url(WP_PLUGIN_URL . '/' . CNB_BASEFOLDER . '/resources/images/multibutton.png');?>" alt="Multibutton">
|
87 |
+
<p>Takes up little space but reaveals a treasure of options.</p>
|
88 |
+
|
89 |
+
<div class="cnb-divider"></div>
|
90 |
+
|
91 |
+
<h2>✨ Buttonbar ✨</h2>
|
92 |
+
<img class="cnb-width-80" src="<?php echo esc_url(WP_PLUGIN_URL . '/' . CNB_BASEFOLDER . '/resources/images/buttonbar.png');?>" alt="Buttonbar">
|
93 |
+
<p>Create a web app experience on your website.</p>
|
94 |
+
|
95 |
+
<div class="cnb-divider"></div>
|
96 |
+
|
97 |
+
<h2>🕘 The scheduler 🕔</h2>
|
98 |
+
<img src="<?php echo esc_url(WP_PLUGIN_URL . '/' . CNB_BASEFOLDER . '/resources/images/button-scheduler.png');?>" alt="The scheduler">
|
99 |
+
<p>Control exactly when your buttons are displayed. Maybe a call button during business hours and a mail buttons when you're closed.</p>
|
100 |
+
|
101 |
+
<div class="cnb-divider"></div>
|
102 |
+
<h3>And much more!</h3>
|
103 |
+
</div>
|
104 |
+
</div>
|
105 |
+
<div class="cnb-welcome-blocks">
|
106 |
+
<div class="cnb-block cnb-signup-box">
|
107 |
+
<h2>Create your free account and supercharge your Call Now Button.</h2>
|
108 |
+
<?php echo CnbHeaderNotices::cnb_settings_email_activation_input(); // phpcs:ignore WordPress.Security ?>
|
109 |
+
</div>
|
110 |
+
<div class="cnb-divider"></div>
|
111 |
+
<p><i>Only need a Call button? <a href="<?php echo esc_url( $link ) ?>">Continue without an account</a>.</i></p>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
<?php }
|
115 |
+
}
|
src/admin/getting-started/index.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<?php // Silence is golden
|
src/admin/legacy/CnbLegacyController.php
CHANGED
@@ -5,15 +5,6 @@ namespace cnb\admin\legacy;
|
|
5 |
// don't load directly
|
6 |
defined( 'ABSPATH' ) || die( '-1' );
|
7 |
|
8 |
-
use cnb\notices\CnbAdminNotices;
|
9 |
-
|
10 |
class CnbLegacyController {
|
11 |
|
12 |
-
public function show_welcome_banner() {
|
13 |
-
$dismiss_value = 'welcome-panel';
|
14 |
-
$dismissed_option = CnbAdminNotices::get_instance()->get_dismiss_option_name( $dismiss_value );
|
15 |
-
$is_dismissed = CnbAdminNotices::get_instance()->is_dismissed( $dismissed_option );
|
16 |
-
|
17 |
-
return ! $is_dismissed;
|
18 |
-
}
|
19 |
}
|
5 |
// don't load directly
|
6 |
defined( 'ABSPATH' ) || die( '-1' );
|
7 |
|
|
|
|
|
8 |
class CnbLegacyController {
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
}
|
src/admin/legacy/CnbLegacyEdit.php
CHANGED
@@ -17,7 +17,6 @@ class CnbLegacyEdit {
|
|
17 |
add_action( 'cnb_header_name', array( $this, 'header' ) );
|
18 |
|
19 |
do_action( 'cnb_header' );
|
20 |
-
$this->render_welcome_banner();
|
21 |
$this->render_form();
|
22 |
do_action( 'cnb_footer' );
|
23 |
do_action( 'cnb_finish' );
|
@@ -155,71 +154,6 @@ class CnbLegacyEdit {
|
|
155 |
echo esc_html( CNB_NAME ) . ' <span class="cnb-version">v' . esc_html( CNB_VERSION ) . '</span>';
|
156 |
}
|
157 |
|
158 |
-
private function render_welcome_banner() {
|
159 |
-
$legacyController = new CnbLegacyController();
|
160 |
-
$cnb_utils = new CnbUtils();
|
161 |
-
if ( ! $legacyController->show_welcome_banner() ) {
|
162 |
-
return;
|
163 |
-
}
|
164 |
-
$dismiss_value = 'welcome-panel';
|
165 |
-
|
166 |
-
$url = admin_url( 'admin.php' );
|
167 |
-
$upgrade_link =
|
168 |
-
add_query_arg(
|
169 |
-
array( 'page' => 'call-now-button-upgrade' ),
|
170 |
-
$url );
|
171 |
-
|
172 |
-
$dismiss_url = add_query_arg( array(
|
173 |
-
CNB_SLUG . '_dismiss' => $dismiss_value
|
174 |
-
), $url );
|
175 |
-
|
176 |
-
?>
|
177 |
-
<div id="welcome-banner"
|
178 |
-
class="welcome-banner is-dismissible notice-call-now-button"
|
179 |
-
data-dismiss-url="<?php echo esc_url( $dismiss_url ) ?>">
|
180 |
-
<p id="welcome-banner-notice">🎉 Welcome to <b>Call Now Button</b>! <a class="cnb-expand-link">Click to expand...</a></p>
|
181 |
-
<div class="welcome-banner-content">
|
182 |
-
<h2>Welcome to Call Now Button!</h2>
|
183 |
-
<div class="welcome-banner-column-container">
|
184 |
-
<div class="welcome-banner-column">
|
185 |
-
<h3>Some cool stats!</h3>
|
186 |
-
<div class="welcome-column-box">
|
187 |
-
<p class="cnb-mobile-inline">🎉 The #1 click-to-call button on WordPress for 10 years!</p>
|
188 |
-
<p class="cnb-mobile-inline">🚀 200k+ active installations and growing every day!</p>
|
189 |
-
<p class="cnb-mobile-inline">❤️ Loved by our users and rated 4.9!</p>
|
190 |
-
<p class="cnb-mobile-inline">💎 Call Now Button <strong>Premium</strong> has so much more!
|
191 |
-
</p>
|
192 |
-
</div>
|
193 |
-
</div>
|
194 |
-
<div class="welcome-banner-column">
|
195 |
-
<h3>What's in Premium?</h3>
|
196 |
-
<p class="cnb-mobile-inline">+ Create lots of buttons</p>
|
197 |
-
<p class="cnb-mobile-inline">+ Phone, SMS, Email, Maps, Links, Anchors</p>
|
198 |
-
<p class="cnb-mobile-inline">+ WhatsApp, Signal, Telegram, FB Messenger</p>
|
199 |
-
<p class="cnb-mobile-inline">+ Multi action buttons</p>
|
200 |
-
<p class="cnb-mobile-inline">+ Button scheduler</p>
|
201 |
-
<p class="cnb-mobile-inline">And much more!</p>
|
202 |
-
</div>
|
203 |
-
<div class="welcome-banner-column">
|
204 |
-
<a class="button button-primary button-hero" href="<?php echo esc_url( $upgrade_link ) ?>">Get
|
205 |
-
Premium Free</a>
|
206 |
-
|
207 |
-
<p><a href="<?php echo esc_url( $upgrade_link ) ?>">More info about Premium</a></p>
|
208 |
-
<h3>Other resources</h3>
|
209 |
-
<p>
|
210 |
-
<a href="<?php echo esc_url( $cnb_utils->get_support_url( 'wordpress-free/', 'welcome-banner', 'Help center' ) ) ?>">Help
|
211 |
-
center</a></p>
|
212 |
-
<p>
|
213 |
-
<a href="<?php echo esc_url( $cnb_utils->get_support_url( 'wordpress-free/#faq', 'welcome-banner', 'FAQ' ) ) ?>">FAQ</a>
|
214 |
-
</p>
|
215 |
-
</div>
|
216 |
-
</div>
|
217 |
-
</div>
|
218 |
-
<button type="button" class="notice-dismiss"><span
|
219 |
-
class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.' ) ?></span></button>
|
220 |
-
</div>
|
221 |
-
<?php }
|
222 |
-
|
223 |
private function render_form() {
|
224 |
$cnb_options = get_option( 'cnb' );
|
225 |
$adminFunctions = new CnbAdminFunctions();
|
@@ -236,6 +170,8 @@ class CnbLegacyEdit {
|
|
236 |
<a href="<?php echo esc_url( $this->create_tab_url( 'extra_options' ) ) ?>"
|
237 |
class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'extra_options' ) ) ?>"
|
238 |
data-tab-name="extra_options">Presentation</a>
|
|
|
|
|
239 |
</h2>
|
240 |
|
241 |
<form method="post" action="<?php echo esc_url( admin_url( 'options.php' ) ) ?>"
|
@@ -246,15 +182,39 @@ class CnbLegacyEdit {
|
|
246 |
<tr>
|
247 |
<th colspan="2"></th>
|
248 |
</tr>
|
|
|
249 |
<tr>
|
250 |
<th scope="row"><label for="cnb-active">Button status</label></th>
|
|
|
251 |
<td>
|
252 |
<input type="hidden" name="cnb[active]" value="0"/>
|
253 |
-
<input id="cnb-active" type="checkbox" name="cnb[active]"
|
254 |
-
value="1" <?php checked( '1', $cnb_options['active'] );
|
255 |
-
<label for="cnb-active">
|
|
|
|
|
|
|
256 |
</td>
|
257 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
<tr>
|
259 |
<th scope="row"><label for="cnb-number">Phone number</label> <a
|
260 |
href="<?php echo esc_url( $cnb_utils->get_support_url( 'wordpress-free/basics/phone-number/', 'legacy-basics-question-mark', 'phone-number' ) ) ?>"
|
@@ -396,15 +356,75 @@ class CnbLegacyEdit {
|
|
396 |
value="exclude" <?php checked( 'exclude', $cnb_options['limit'] ); ?> />
|
397 |
<label for="limit2">Exclude these posts and pages.</label>
|
398 |
</div>
|
399 |
-
<br>
|
400 |
-
<div>
|
401 |
-
<input type="hidden" name="cnb[frontpage]" value="0"/>
|
402 |
-
<input id="frontpage" type="checkbox" name="cnb[frontpage]"
|
403 |
-
value="1" <?php checked( '1', $cnb_options['frontpage'] ); ?>>
|
404 |
-
<label title="right" for="frontpage">Hide button on front page</label>
|
405 |
-
</div>
|
406 |
</td>
|
407 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
</table>
|
409 |
<table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'advanced_options' ) ) ?>">
|
410 |
<tr>
|
@@ -437,10 +457,10 @@ class CnbLegacyEdit {
|
|
437 |
<span class="cnb-purple">✓</span> Change icons<br>
|
438 |
<span class="cnb-purple">✓</span> Button animations<br>
|
439 |
<span class="cnb-purple">✓</span> Live previews</p>
|
440 |
-
<p>
|
441 |
'unlock',
|
442 |
'',
|
443 |
-
'
|
444 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
445 |
);
|
446 |
?>
|
@@ -456,8 +476,8 @@ class CnbLegacyEdit {
|
|
456 |
✓ Smooth scroll anchors<br>
|
457 |
✓ Links</p>',
|
458 |
'format-chat',
|
459 |
-
'<strong>
|
460 |
-
'
|
461 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
462 |
);
|
463 |
?>
|
@@ -480,13 +500,27 @@ class CnbLegacyEdit {
|
|
480 |
);
|
481 |
( new CnbAdminFunctions() )->cnb_promobox(
|
482 |
'blue',
|
483 |
-
'
|
484 |
-
'
|
485 |
-
<p>The
|
486 |
<p>Try it out and enjoy scheduling, multiple buttons, more button types, animations and much more!</p>',
|
487 |
'money-alt',
|
488 |
'',
|
489 |
-
'Try
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
491 |
);
|
492 |
?>
|
17 |
add_action( 'cnb_header_name', array( $this, 'header' ) );
|
18 |
|
19 |
do_action( 'cnb_header' );
|
|
|
20 |
$this->render_form();
|
21 |
do_action( 'cnb_footer' );
|
22 |
do_action( 'cnb_finish' );
|
154 |
echo esc_html( CNB_NAME ) . ' <span class="cnb-version">v' . esc_html( CNB_VERSION ) . '</span>';
|
155 |
}
|
156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
private function render_form() {
|
158 |
$cnb_options = get_option( 'cnb' );
|
159 |
$adminFunctions = new CnbAdminFunctions();
|
170 |
<a href="<?php echo esc_url( $this->create_tab_url( 'extra_options' ) ) ?>"
|
171 |
class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'extra_options' ) ) ?>"
|
172 |
data-tab-name="extra_options">Presentation</a>
|
173 |
+
<a href="<?php echo esc_url( $this->create_tab_url( 'scheduler' ) ) ?>" class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'scheduler' ) ) ?> cnb_disabled_feature"
|
174 |
+
data-tab-name="scheduler"><span class="dashicons dashicons-lock"></span> Scheduler</a>
|
175 |
</h2>
|
176 |
|
177 |
<form method="post" action="<?php echo esc_url( admin_url( 'options.php' ) ) ?>"
|
182 |
<tr>
|
183 |
<th colspan="2"></th>
|
184 |
</tr>
|
185 |
+
|
186 |
<tr>
|
187 |
<th scope="row"><label for="cnb-active">Button status</label></th>
|
188 |
+
|
189 |
<td>
|
190 |
<input type="hidden" name="cnb[active]" value="0"/>
|
191 |
+
<input id="cnb-active" class="cnb_toggle_checkbox" type="checkbox" name="cnb[active]"
|
192 |
+
value="1" <?php checked( '1', $cnb_options['active'] ); ?> />
|
193 |
+
<label for="cnb-active" class="cnb_toggle_label">Toggle</label>
|
194 |
+
<span data-cnb_toggle_state_label="cnb-active" class="cnb_toggle_state cnb_toggle_false">(Inactive)</span>
|
195 |
+
<span data-cnb_toggle_state_label="cnb-active"
|
196 |
+
class="cnb_toggle_state cnb_toggle_true">Active</span>
|
197 |
</td>
|
198 |
</tr>
|
199 |
+
<tr>
|
200 |
+
<th scope="row"><label for="cnb_action_type">Button type</label></th>
|
201 |
+
<td>
|
202 |
+
<select>
|
203 |
+
<option selected="selected">Phone</option>
|
204 |
+
<option disabled>Email*</option>
|
205 |
+
<option disabled>SMS/Text*</option>
|
206 |
+
<option disabled>WhatsApp*</option>
|
207 |
+
<option disabled>Messenger*</option>
|
208 |
+
<option disabled>Signal*</option>
|
209 |
+
<option disabled>Telegram*</option>
|
210 |
+
<option disabled>Link*</option>
|
211 |
+
<option disabled>Google Maps*</option>
|
212 |
+
<option disabled>Anchor*</option>
|
213 |
+
</select>
|
214 |
+
<p class="description">*<a href="<?php echo esc_url(( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()); ?>">Create an account</a> to enable these actions</p>
|
215 |
+
</td>
|
216 |
+
</tr>
|
217 |
+
|
218 |
<tr>
|
219 |
<th scope="row"><label for="cnb-number">Phone number</label> <a
|
220 |
href="<?php echo esc_url( $cnb_utils->get_support_url( 'wordpress-free/basics/phone-number/', 'legacy-basics-question-mark', 'phone-number' ) ) ?>"
|
356 |
value="exclude" <?php checked( 'exclude', $cnb_options['limit'] ); ?> />
|
357 |
<label for="limit2">Exclude these posts and pages.</label>
|
358 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
</td>
|
360 |
</tr>
|
361 |
+
<tr class="appearance">
|
362 |
+
<th scope="row"><label for="cnb-show-fp">Show button on front page</label></th>
|
363 |
+
<td>
|
364 |
+
<input type="hidden" name="cnb[frontpage]" value="1"/>
|
365 |
+
<input id="cnb-show-fp" class="cnb_toggle_checkbox" type="checkbox" name="cnb[frontpage]"
|
366 |
+
value="0" <?php checked( '0', $cnb_options['frontpage'] ); ?> />
|
367 |
+
<label for="cnb-show-fp" class="cnb_toggle_label">Toggle</label>
|
368 |
+
<span data-cnb_toggle_state_label="cnb-show-fp" class="cnb_toggle_state cnb_toggle_false">(No)</span>
|
369 |
+
<span data-cnb_toggle_state_label="cnb-show-fp"
|
370 |
+
class="cnb_toggle_state cnb_toggle_true">Yes</span>
|
371 |
+
</td>
|
372 |
+
</tr>
|
373 |
+
|
374 |
+
|
375 |
+
|
376 |
+
</table>
|
377 |
+
<table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'scheduler' ) ) ?>" data-tab-name="scheduler">
|
378 |
+
<tr>
|
379 |
+
<th colspan="2"><a href="<?php echo esc_url(( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()); ?>">Create an account</a> to enable the scheduler.</th>
|
380 |
+
</tr>
|
381 |
+
<tr class="cnb_disabled_feature">
|
382 |
+
<th scope="row">Show at all times</th>
|
383 |
+
<td>
|
384 |
+
<input class="cnb_toggle_checkbox" type="checkbox" checked="checked" disabled>
|
385 |
+
<label for="actions_schedule_show_always" class="cnb_toggle_label" style="background-color:#b3afaf">Toggle</label>
|
386 |
+
<span data-cnb_toggle_state_label="actions_schedule_show_always" class="cnb_toggle_state cnb_toggle_true">Yes</span>
|
387 |
+
<span data-cnb_toggle_state_label="actions_schedule_show_always" class="cnb_toggle_state cnb_toggle_false">(No)</span>
|
388 |
+
</td>
|
389 |
+
</tr>
|
390 |
+
<tr class="cnb_disabled_feature">
|
391 |
+
<th>Set days</th>
|
392 |
+
<td>
|
393 |
+
<input disabled class="cnb_day_selector" id="cnb_weekday_0" type="checkbox">
|
394 |
+
<label title="Monday" class="cnb_day_selector" for="cnb_weekday_0">Mon</label>
|
395 |
+
|
396 |
+
<input disabled class="cnb_day_selector" id="cnb_weekday_1" type="checkbox">
|
397 |
+
<label title="Tuesday" class="cnb_day_selector" for="cnb_weekday_1">Tue</label>
|
398 |
+
|
399 |
+
<input disabled class="cnb_day_selector" id="cnb_weekday_2" type="checkbox">
|
400 |
+
<label title="Wednesday" class="cnb_day_selector" for="cnb_weekday_2">Wed</label>
|
401 |
+
|
402 |
+
<input disabled class="cnb_day_selector" id="cnb_weekday_3" type="checkbox">
|
403 |
+
<label title="Thursday" class="cnb_day_selector" for="cnb_weekday_3">Thu</label>
|
404 |
+
|
405 |
+
<input disabled class="cnb_day_selector" id="cnb_weekday_4" type="checkbox">
|
406 |
+
<label title="Friday" class="cnb_day_selector" for="cnb_weekday_4">Fri</label>
|
407 |
+
|
408 |
+
<input disabled class="cnb_day_selector" id="cnb_weekday_5" type="checkbox">
|
409 |
+
<label title="Saturday" class="cnb_day_selector" for="cnb_weekday_5">Sat</label>
|
410 |
+
|
411 |
+
<input disabled class="cnb_day_selector" id="cnb_weekday_6" type="checkbox">
|
412 |
+
<label title="Sunday" class="cnb_day_selector" for="cnb_weekday_6">Sun</label>
|
413 |
+
</td>
|
414 |
+
</tr>
|
415 |
+
<tr class="cnb_disabled_feature">
|
416 |
+
<th><label for="actions_schedule_outside_hours">After hours</label></th>
|
417 |
+
<td>
|
418 |
+
<input id="actions_schedule_outside_hours" disabled class="cnb_toggle_checkbox" type="checkbox">
|
419 |
+
<label for="actions_schedule_outside_hours" class="cnb_toggle_label">Toggle</label>
|
420 |
+
</td>
|
421 |
+
</tr>
|
422 |
+
<tr class="cnb_disabled_feature">
|
423 |
+
<th>Set times</th>
|
424 |
+
<td class="cnb-scheduler-slider">
|
425 |
+
<p id="cnb-schedule-range-text">From <strong>8:00 am</strong> till <strong>5:00 pm</strong></p>
|
426 |
+
</td>
|
427 |
+
</tr>
|
428 |
</table>
|
429 |
<table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'advanced_options' ) ) ?>">
|
430 |
<tr>
|
457 |
<span class="cnb-purple">✓</span> Change icons<br>
|
458 |
<span class="cnb-purple">✓</span> Button animations<br>
|
459 |
<span class="cnb-purple">✓</span> Live previews</p>
|
460 |
+
<p>Enable <strong>Cloud</strong> to get all of this and more!</p>',
|
461 |
'unlock',
|
462 |
'',
|
463 |
+
'Create account',
|
464 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
465 |
);
|
466 |
?>
|
476 |
✓ Smooth scroll anchors<br>
|
477 |
✓ Links</p>',
|
478 |
'format-chat',
|
479 |
+
'<strong>More everything!</strong>',
|
480 |
+
'Discover Cloud',
|
481 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
482 |
);
|
483 |
?>
|
500 |
);
|
501 |
( new CnbAdminFunctions() )->cnb_promobox(
|
502 |
'blue',
|
503 |
+
'Get more for FREE!',
|
504 |
+
'Cloud adds a ton of extra power to the Call Now Button.</p>
|
505 |
+
<p>The free Cloud plan shows a little branding with your buttons and gives you full access to 99% of all features.</p>
|
506 |
<p>Try it out and enjoy scheduling, multiple buttons, more button types, animations and much more!</p>',
|
507 |
'money-alt',
|
508 |
'',
|
509 |
+
'Try Cloud',
|
510 |
+
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
511 |
+
);
|
512 |
+
?>
|
513 |
+
</div>
|
514 |
+
<div class="cnb-on-active-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'scheduler' ) ) ?>">
|
515 |
+
<?php
|
516 |
+
( new CnbAdminFunctions() )->cnb_promobox(
|
517 |
+
'purple',
|
518 |
+
'Phones off at 6pm?',
|
519 |
+
'<p>Sign up to enable a scheduler that allows you to set the days and hours that you are available.</p>' .
|
520 |
+
'<p>You can even replace it with an email button during your off-hours so people can still contact you.</p>',
|
521 |
+
'clock',
|
522 |
+
'<strong>Use the scheduler!</strong>',
|
523 |
+
'Enable cloud',
|
524 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
525 |
);
|
526 |
?>
|
src/admin/legacy/CnbLegacyUpgrade.php
CHANGED
@@ -11,16 +11,16 @@ use cnb\utils\CnbUtils;
|
|
11 |
|
12 |
class CnbLegacyUpgrade {
|
13 |
function header() {
|
14 |
-
echo '
|
15 |
}
|
16 |
|
17 |
-
function standard_plugin_promobox() {
|
18 |
?>
|
19 |
<div class="cnb-body-column hide-on-mobile">
|
20 |
<?php
|
21 |
( new CnbAdminFunctions() )->cnb_promobox(
|
22 |
'grey',
|
23 |
-
'
|
24 |
'<p>✓ One button<br>
|
25 |
✓ Phone<br><br>
|
26 |
✓ Circular (single action)<br>
|
@@ -48,7 +48,7 @@ class CnbLegacyUpgrade {
|
|
48 |
✓ Flexible z-index<br>
|
49 |
|
50 |
</p>',
|
51 |
-
'
|
52 |
'<strong>Free</strong>',
|
53 |
'Currently active',
|
54 |
'disabled'
|
@@ -57,14 +57,14 @@ class CnbLegacyUpgrade {
|
|
57 |
</div>
|
58 |
<?php }
|
59 |
|
60 |
-
function premium_plugin_promobox() {
|
61 |
$cnb_utils = new CnbUtils();
|
62 |
?>
|
63 |
<div class="cnb-body-column">
|
64 |
<?php
|
65 |
( new CnbAdminFunctions() )->cnb_promobox(
|
66 |
'purple',
|
67 |
-
'
|
68 |
'
|
69 |
<p><strong>✓ Lots of buttons!</strong><br>
|
70 |
✓ Phone, SMS/Text, Email, Maps, URLs, Anchors (with smooth scroll)<br>
|
@@ -106,25 +106,30 @@ class CnbLegacyUpgrade {
|
|
106 |
function upgrade_faq() { ?>
|
107 |
<div style="max-width:600px;margin:0 auto">
|
108 |
<h1 class="cnb-center">FAQ</h1>
|
109 |
-
<h3>
|
110 |
-
<p>Yes. You can use
|
111 |
-
only need an account for that. The difference with the
|
112 |
notice is added to your buttons.</p>
|
113 |
-
<h3>
|
|
|
|
|
114 |
<p>Yes. We want the Call Now Button to be accessible to all website owners. Even those that do not have a
|
115 |
-
WordPress powered website. The
|
116 |
continue to manage your buttons from your WordPress instance, but you could also do this via our web
|
117 |
-
app. And should you ever move to a different CMS, your button(s) will just move with you.</p>
|
118 |
-
<h3>What is the "powered by" notice
|
119 |
-
<p>Call Now Button
|
120 |
-
|
121 |
Now Button". It's very delicate and will not distract the the visitor from your content.</p>
|
|
|
|
|
122 |
</div>
|
123 |
<?php }
|
124 |
|
125 |
public function render() {
|
126 |
do_action( 'cnb_init', __METHOD__ );
|
127 |
wp_enqueue_script( CNB_SLUG . '-settings' );
|
|
|
128 |
|
129 |
add_action( 'cnb_header_name', array( $this, 'header' ) );
|
130 |
do_action( 'cnb_header' );
|
@@ -133,8 +138,8 @@ class CnbLegacyUpgrade {
|
|
133 |
<div class="cnb-one-column-section">
|
134 |
<div class="cnb-body-content">
|
135 |
<div class="cnb-two-promobox-row">
|
136 |
-
<?php $this->standard_plugin_promobox() ?>
|
137 |
<?php $this->premium_plugin_promobox() ?>
|
|
|
138 |
</div>
|
139 |
<?php $this->upgrade_faq() ?>
|
140 |
</div>
|
11 |
|
12 |
class CnbLegacyUpgrade {
|
13 |
function header() {
|
14 |
+
echo 'Activate Cloud to unlock lots of extra features';
|
15 |
}
|
16 |
|
17 |
+
private function standard_plugin_promobox() {
|
18 |
?>
|
19 |
<div class="cnb-body-column hide-on-mobile">
|
20 |
<?php
|
21 |
( new CnbAdminFunctions() )->cnb_promobox(
|
22 |
'grey',
|
23 |
+
'Lite',
|
24 |
'<p>✓ One button<br>
|
25 |
✓ Phone<br><br>
|
26 |
✓ Circular (single action)<br>
|
48 |
✓ Flexible z-index<br>
|
49 |
|
50 |
</p>',
|
51 |
+
'database',
|
52 |
'<strong>Free</strong>',
|
53 |
'Currently active',
|
54 |
'disabled'
|
57 |
</div>
|
58 |
<?php }
|
59 |
|
60 |
+
private function premium_plugin_promobox() {
|
61 |
$cnb_utils = new CnbUtils();
|
62 |
?>
|
63 |
<div class="cnb-body-column">
|
64 |
<?php
|
65 |
( new CnbAdminFunctions() )->cnb_promobox(
|
66 |
'purple',
|
67 |
+
'Cloud',
|
68 |
'
|
69 |
<p><strong>✓ Lots of buttons!</strong><br>
|
70 |
✓ Phone, SMS/Text, Email, Maps, URLs, Anchors (with smooth scroll)<br>
|
106 |
function upgrade_faq() { ?>
|
107 |
<div style="max-width:600px;margin:0 auto">
|
108 |
<h1 class="cnb-center">FAQ</h1>
|
109 |
+
<h3>Is Cloud really free?</h3>
|
110 |
+
<p>Yes. You can use 99% of the cloud features of the Call Now Button for free. No credit card is required. You
|
111 |
+
only need an account for that. The difference with the PRO plan is that a small "Powered by"
|
112 |
notice is added to your buttons.</p>
|
113 |
+
<h3>What's included in PRO?</h3>
|
114 |
+
<p>Upgrading to PRO removes the "Powered by Call Now Button" notice and adds some Premium features such as geo targeting and setting a scroll depth for a button to appear.</p>
|
115 |
+
<h3>Does Cloud require an account?</h3>
|
116 |
<p>Yes. We want the Call Now Button to be accessible to all website owners. Even those that do not have a
|
117 |
+
WordPress powered website. The Cloud version of the Call Now Button can be used by everyone on any website. You can
|
118 |
continue to manage your buttons from your WordPress instance, but you could also do this via our web
|
119 |
+
app on <a href="https://callnowbutton.com" target="_blank">callnowbutton.com</a>. And should you ever move to a different CMS, your button(s) will just move with you.</p>
|
120 |
+
<h3>What is the "powered by" notice?</h3>
|
121 |
+
<p>The cloud version of Call Now Button is available for a small yearly or monthly fee, but there is also a
|
122 |
+
<em>free</em> option. The free option introduces a small notice to your buttons that says "Powered by Call
|
123 |
Now Button". It's very delicate and will not distract the the visitor from your content.</p>
|
124 |
+
<h3>Why is it called Cloud?</h3>
|
125 |
+
<p>It's called Cloud because it is served from remote servers (the cloud) and no longer stored locally on your website. Therefore you need an account to enabled it. WordPress is currently the only platform that has its own interface so you can still manage your buttons from inside WordPress. Other platforms can use the Call Now Button as well but manage their buttons via the web app on app.callnowbutton.com.</p>
|
126 |
</div>
|
127 |
<?php }
|
128 |
|
129 |
public function render() {
|
130 |
do_action( 'cnb_init', __METHOD__ );
|
131 |
wp_enqueue_script( CNB_SLUG . '-settings' );
|
132 |
+
wp_enqueue_script( CNB_SLUG . '-premium-activation' );
|
133 |
|
134 |
add_action( 'cnb_header_name', array( $this, 'header' ) );
|
135 |
do_action( 'cnb_header' );
|
138 |
<div class="cnb-one-column-section">
|
139 |
<div class="cnb-body-content">
|
140 |
<div class="cnb-two-promobox-row">
|
|
|
141 |
<?php $this->premium_plugin_promobox() ?>
|
142 |
+
<?php $this->standard_plugin_promobox() ?>
|
143 |
</div>
|
144 |
<?php $this->upgrade_faq() ?>
|
145 |
</div>
|
src/admin/partials/CnbFooter.php
CHANGED
@@ -43,8 +43,8 @@ class CnbFooter {
|
|
43 |
<p class="cnb-url cnb-center"><a
|
44 |
href="<?php echo esc_url( $cnb_utils->get_website_url( '', 'footer-links', 'branding' ) ) ?>"
|
45 |
target="_blank">Call Now Button<?php if ( $cnb_utils->isCloudActive( $cnb_options ) ) {
|
46 |
-
echo '<span class="cnb_footer_beta">
|
47 |
-
} ?></a></p>
|
48 |
<p class="cnb-center">Version <?php echo esc_attr( CNB_VERSION ) ?>
|
49 |
<p class="cnb-center cnb-spacing">
|
50 |
<a href="<?php echo esc_url( $cnb_utils->get_support_url( '', 'footer-links', 'support' ) ) ?>"
|
@@ -54,7 +54,7 @@ class CnbFooter {
|
|
54 |
target="_blank" title="Feature Requests">Suggestions</a>
|
55 |
<?php if ( ! $cnb_utils->isCloudActive( $cnb_options ) ) { ?>
|
56 |
· <strong><a href="<?php echo esc_url( $upgrade_link ) ?>"
|
57 |
-
title="Unlock features">
|
58 |
<?php } ?>
|
59 |
</p>
|
60 |
</div>
|
@@ -74,7 +74,7 @@ class CnbFooter {
|
|
74 |
private function add_usage_details() {
|
75 |
global $wp_version;
|
76 |
if ($this->utils->is_reporting_enabled()) {
|
77 |
-
echo sprintf('<template
|
78 |
id="cnb-data"
|
79 |
data-wordpress-version="%1$s"
|
80 |
data-wordpress-environment="%2$s"
|
43 |
<p class="cnb-url cnb-center"><a
|
44 |
href="<?php echo esc_url( $cnb_utils->get_website_url( '', 'footer-links', 'branding' ) ) ?>"
|
45 |
target="_blank">Call Now Button<?php if ( $cnb_utils->isCloudActive( $cnb_options ) ) {
|
46 |
+
echo '<span class="cnb_footer_beta">CLOUD</span>';
|
47 |
+
} else { echo '<span class="cnb_footer_beta">Lite</span>'; } ?></a></p>
|
48 |
<p class="cnb-center">Version <?php echo esc_attr( CNB_VERSION ) ?>
|
49 |
<p class="cnb-center cnb-spacing">
|
50 |
<a href="<?php echo esc_url( $cnb_utils->get_support_url( '', 'footer-links', 'support' ) ) ?>"
|
54 |
target="_blank" title="Feature Requests">Suggestions</a>
|
55 |
<?php if ( ! $cnb_utils->isCloudActive( $cnb_options ) ) { ?>
|
56 |
· <strong><a href="<?php echo esc_url( $upgrade_link ) ?>"
|
57 |
+
title="Unlock features">Enable cloud</a></strong>
|
58 |
<?php } ?>
|
59 |
</p>
|
60 |
</div>
|
74 |
private function add_usage_details() {
|
75 |
global $wp_version;
|
76 |
if ($this->utils->is_reporting_enabled()) {
|
77 |
+
echo sprintf('<template
|
78 |
id="cnb-data"
|
79 |
data-wordpress-version="%1$s"
|
80 |
data-wordpress-environment="%2$s"
|
src/admin/partials/CnbHeaderNotices.php
CHANGED
@@ -82,8 +82,8 @@ class CnbHeaderNotices {
|
|
82 |
$register_url = $cnb_utils->get_app_url( 'register', 'upgrade-to-premium-options', 'callnowbutton.com' );
|
83 |
$url = $cnb_utils->get_app_url( '', 'manual_activation', 'sign-up-for-api' );
|
84 |
|
85 |
-
$message = '<h3 class="title cnb-remove-add-new">
|
86 |
-
$message .= '<p>To
|
87 |
$message .= '<h4>Option 1: Email activation (easy and fast!)</h4>';
|
88 |
$message .= self::cnb_settings_email_activation_input();
|
89 |
|
@@ -122,18 +122,23 @@ class CnbHeaderNotices {
|
|
122 |
$adminNotices->warning( $message );
|
123 |
}
|
124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
public static function cnb_settings_email_activation_input() {
|
126 |
$cnb_utils = new CnbUtils();
|
127 |
-
$terms_url = $cnb_utils->get_website_url( 'terms
|
128 |
-
$privacy_url = $cnb_utils->get_website_url( 'privacy
|
129 |
-
$message = '<form class="cnb-container
|
130 |
-
$message .= '<
|
131 |
-
$message .=
|
132 |
-
$message .=
|
133 |
-
|
134 |
-
$message
|
135 |
-
|
136 |
-
$message .= '<p class="nonessential">By clicking <u>Activate Premium</u> an account will be created with your email address on callnowbutton.com and you agree to our <a href="' . esc_url( $terms_url ) . '" target="_blank">Terms & Conditions</a> and <a href="' . esc_url( $privacy_url ) . '" target="_blank">Privacy statement</a>.</p>';
|
137 |
$message .= '</form>';
|
138 |
|
139 |
return $message;
|
@@ -143,7 +148,7 @@ class CnbHeaderNotices {
|
|
143 |
$message = sprintf( '<form action="%1$s" class="cnb-container">', esc_url( admin_url( 'admin.php' ) ) );
|
144 |
$message .= '<input type="hidden" name="page" value="call-now-button-settings" />';
|
145 |
$message .= '<div>';
|
146 |
-
$message .= '<input type="text" class="cnb_activation_input_field" name="api_key" placeholder="Paste API key here"/>';
|
147 |
$message .= get_submit_button( __( 'Store API key' ), 'primary', 'submit', false );
|
148 |
$message .= '</div>';
|
149 |
$message .= '</form>';
|
@@ -387,7 +392,7 @@ class CnbHeaderNotices {
|
|
387 |
),
|
388 |
$url );
|
389 |
$redirect_url = esc_url( $redirect_link );
|
390 |
-
$message = "<p
|
391 |
$message .= '<a href="' . $redirect_url . '">Advanced settings</a> tab ';
|
392 |
$message .= 'to avoid unpredictable behavior when using the scheduler.</p>';
|
393 |
CnbAdminNotices::get_instance()->warning( $message );
|
82 |
$register_url = $cnb_utils->get_app_url( 'register', 'upgrade-to-premium-options', 'callnowbutton.com' );
|
83 |
$url = $cnb_utils->get_app_url( '', 'manual_activation', 'sign-up-for-api' );
|
84 |
|
85 |
+
$message = '<h3 class="title cnb-remove-add-new">Enable cloud features</h3>';
|
86 |
+
$message .= '<p>To enable cloud features, you\'ll need a <a href="' . esc_url( $register_url ) . '" target="_blank">callnowbutton.com</a> account and an API key. There\'s 2 ways to do this:</p>';
|
87 |
$message .= '<h4>Option 1: Email activation (easy and fast!)</h4>';
|
88 |
$message .= self::cnb_settings_email_activation_input();
|
89 |
|
122 |
$adminNotices->warning( $message );
|
123 |
}
|
124 |
|
125 |
+
/**
|
126 |
+
* Returns an HTML form containing all the fields needed for a Premium signup.
|
127 |
+
*
|
128 |
+
* The returned string is already pre-HTML-escaped.
|
129 |
+
*
|
130 |
+
* @return string HTML form with e-mail placeholder and a Submit button
|
131 |
+
*/
|
132 |
public static function cnb_settings_email_activation_input() {
|
133 |
$cnb_utils = new CnbUtils();
|
134 |
+
$terms_url = $cnb_utils->get_website_url( 'legal/terms/', 'email-activation', 'terms' );
|
135 |
+
$privacy_url = $cnb_utils->get_website_url( 'legal/privacy/', 'email-activation', 'privacy' );
|
136 |
+
$message = '<form class="cnb-container cnb_email_activation">';
|
137 |
+
$message .= '<input type="text" required="required" class="cnb_activation_input_field" name="cnb_email_activation_address" placeholder="Your email address" /> ';
|
138 |
+
$message .= get_submit_button( __( 'Create account' ), 'primary', 'cnb_email_activation_submit', false );
|
139 |
+
$message .= '<p class="cnb_email_activation_message"></p>';
|
140 |
+
|
141 |
+
$message .= '<p class="nonessential">By clicking <u>Create account</u> an account will be created with your email address on callnowbutton.com and you agree to our <a href="' . esc_url( $terms_url ) . '" target="_blank">Terms & Conditions</a> and <a href="' . esc_url( $privacy_url ) . '" target="_blank">Privacy statement</a>.</p>';
|
|
|
|
|
142 |
$message .= '</form>';
|
143 |
|
144 |
return $message;
|
148 |
$message = sprintf( '<form action="%1$s" class="cnb-container">', esc_url( admin_url( 'admin.php' ) ) );
|
149 |
$message .= '<input type="hidden" name="page" value="call-now-button-settings" />';
|
150 |
$message .= '<div>';
|
151 |
+
$message .= '<input type="text" required="required" class="cnb_activation_input_field" name="api_key" placeholder="Paste API key here"/>';
|
152 |
$message .= get_submit_button( __( 'Store API key' ), 'primary', 'submit', false );
|
153 |
$message .= '</div>';
|
154 |
$message .= '</form>';
|
392 |
),
|
393 |
$url );
|
394 |
$redirect_url = esc_url( $redirect_link );
|
395 |
+
$message = "<p class='cnb-notice-domain-timezone-unsupported'>Please fix your timezone in the ";
|
396 |
$message .= '<a href="' . $redirect_url . '">Advanced settings</a> tab ';
|
397 |
$message .= 'to avoid unpredictable behavior when using the scheduler.</p>';
|
398 |
CnbAdminNotices::get_instance()->warning( $message );
|
src/admin/settings/CnbApiKeyActivatedView.php
CHANGED
@@ -19,7 +19,7 @@ class CnbApiKeyActivatedView {
|
|
19 |
private $activation;
|
20 |
|
21 |
function header() {
|
22 |
-
echo '
|
23 |
}
|
24 |
|
25 |
/**
|
@@ -97,7 +97,7 @@ class CnbApiKeyActivatedView {
|
|
97 |
echo '<div style="width:200px;margin: 0 auto;">';
|
98 |
( new CnbDomainViewUpgradeFinished() )->echoBigYaySvg();
|
99 |
echo '</div>';
|
100 |
-
echo '<h1>You have successfully
|
101 |
echo '</div>';
|
102 |
}
|
103 |
|
@@ -157,7 +157,7 @@ class CnbApiKeyActivatedView {
|
|
157 |
}
|
158 |
echo '<div class="cnb-plan-features cnb-center top-50">';
|
159 |
echo '<h1><strong>Upgrade to PRO!</strong></h1>';
|
160 |
-
echo '<h3>🤩 All features from
|
161 |
( new CnbDomainViewUpgradeOverview() )->renderUpgradeForm( $domain );
|
162 |
echo '</div>';
|
163 |
}
|
@@ -169,12 +169,12 @@ class CnbApiKeyActivatedView {
|
|
169 |
*/
|
170 |
private function renderActivationFailure( $user ) {
|
171 |
if ( ! is_wp_error( $user ) ) {
|
172 |
-
echo '<div style="text-align: center"><h2>
|
173 |
|
174 |
return;
|
175 |
}
|
176 |
|
177 |
-
echo '<h1>You tried to activate
|
178 |
}
|
179 |
|
180 |
private function renderBenefits() {
|
@@ -190,7 +190,7 @@ class CnbApiKeyActivatedView {
|
|
190 |
$this->renderActivationSuccess();
|
191 |
}
|
192 |
if ( ! $this->activation->success && ! is_wp_error( $user ) ) {
|
193 |
-
echo '<div style="text-align: center"><h1>
|
194 |
}
|
195 |
if ( $this->activation->success || ! is_wp_error( $user ) ) {
|
196 |
$this->renderBenefits();
|
19 |
private $activation;
|
20 |
|
21 |
function header() {
|
22 |
+
echo 'Cloud activation';
|
23 |
}
|
24 |
|
25 |
/**
|
97 |
echo '<div style="width:200px;margin: 0 auto;">';
|
98 |
( new CnbDomainViewUpgradeFinished() )->echoBigYaySvg();
|
99 |
echo '</div>';
|
100 |
+
echo '<h1>You have successfully activated Call Now Button CLOUD</h1>';
|
101 |
echo '</div>';
|
102 |
}
|
103 |
|
157 |
}
|
158 |
echo '<div class="cnb-plan-features cnb-center top-50">';
|
159 |
echo '<h1><strong>Upgrade to PRO!</strong></h1>';
|
160 |
+
echo '<h3>🤩 All features from Cloud plus more! 🤩</h3>';
|
161 |
( new CnbDomainViewUpgradeOverview() )->renderUpgradeForm( $domain );
|
162 |
echo '</div>';
|
163 |
}
|
169 |
*/
|
170 |
private function renderActivationFailure( $user ) {
|
171 |
if ( ! is_wp_error( $user ) ) {
|
172 |
+
echo '<div style="text-align: center"><h2>Cloud is already active</h2></div>';
|
173 |
|
174 |
return;
|
175 |
}
|
176 |
|
177 |
+
echo '<h1>You tried to activate CLOUD, but something went wrong.</h1>';
|
178 |
}
|
179 |
|
180 |
private function renderBenefits() {
|
190 |
$this->renderActivationSuccess();
|
191 |
}
|
192 |
if ( ! $this->activation->success && ! is_wp_error( $user ) ) {
|
193 |
+
echo '<div style="text-align: center"><h1>Cloud is already active</h1></div>';
|
194 |
}
|
195 |
if ( $this->activation->success || ! is_wp_error( $user ) ) {
|
196 |
$this->renderBenefits();
|
src/admin/settings/CnbSettingsController.php
CHANGED
@@ -47,7 +47,7 @@ class CnbSettingsController {
|
|
47 |
'show_all_buttons_for_domain' => 0,
|
48 |
'footer_show_traces' => 0,
|
49 |
'api_caching' => 0,
|
50 |
-
|
51 |
);
|
52 |
|
53 |
return $this->post_option_cnb( $defaults );
|
@@ -175,7 +175,13 @@ class CnbSettingsController {
|
|
175 |
}
|
176 |
}
|
177 |
|
178 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
|
180 |
// Check for legacy button
|
181 |
$check = $this->disallow_active_without_phone_number( $updated_options );
|
@@ -191,10 +197,10 @@ class CnbSettingsController {
|
|
191 |
// But just in case, this is here for other unseen errors..
|
192 |
$messages[] = CnbAdminCloud::cnb_admin_get_error_message( 'save', 'settings', $check );
|
193 |
}
|
194 |
-
} else if ( $version_upgrade ) {
|
195 |
-
// NOOP - Do nothing for a version upgrade
|
196 |
} else {
|
197 |
-
|
|
|
|
|
198 |
}
|
199 |
|
200 |
$this->update_user_email_opt_in($original_settings, $input);
|
@@ -211,6 +217,17 @@ class CnbSettingsController {
|
|
211 |
return $updated_options;
|
212 |
}
|
213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
private function update_user_email_opt_in($current, $new) {
|
215 |
if (!key_exists('user_marketing_email_opt_in', $new)) {
|
216 |
return;
|
@@ -318,7 +335,7 @@ class CnbSettingsController {
|
|
318 |
// set "migration done"
|
319 |
// We should really only do this once, so we need to save something in the settings to stop continuous migration.
|
320 |
add_option( 'cnb_cloud_migration_done', true );
|
321 |
-
CnbAdminNotices::get_instance()->success( '<p>Successfully connected to your Call Now Button account.</p>' );
|
322 |
}
|
323 |
|
324 |
// If an API key was passed (no matter the status of activation)
|
47 |
'show_all_buttons_for_domain' => 0,
|
48 |
'footer_show_traces' => 0,
|
49 |
'api_caching' => 0,
|
50 |
+
'reporting_enabled' => 0,
|
51 |
);
|
52 |
|
53 |
return $this->post_option_cnb( $defaults );
|
175 |
}
|
176 |
}
|
177 |
|
178 |
+
$show_updated_notice = true;
|
179 |
+
if($this->is_version_upgrade($original_settings, $updated_options)) {
|
180 |
+
$show_updated_notice = false;
|
181 |
+
}
|
182 |
+
if (array_key_exists('activation_time', $input)) {
|
183 |
+
$show_updated_notice = false;
|
184 |
+
}
|
185 |
|
186 |
// Check for legacy button
|
187 |
$check = $this->disallow_active_without_phone_number( $updated_options );
|
197 |
// But just in case, this is here for other unseen errors..
|
198 |
$messages[] = CnbAdminCloud::cnb_admin_get_error_message( 'save', 'settings', $check );
|
199 |
}
|
|
|
|
|
200 |
} else {
|
201 |
+
if ($show_updated_notice) {
|
202 |
+
$messages[] = new CnbNotice( 'success', '<p>Your settings have been updated!</p>' );
|
203 |
+
}
|
204 |
}
|
205 |
|
206 |
$this->update_user_email_opt_in($original_settings, $input);
|
217 |
return $updated_options;
|
218 |
}
|
219 |
|
220 |
+
private function is_version_upgrade(&$original_settings, &$updated_options) {
|
221 |
+
if (!key_exists('changelog_version', $original_settings)) {
|
222 |
+
$original_settings['changelog_version'] = CNB_VERSION;
|
223 |
+
}
|
224 |
+
if (!key_exists('changelog_version', $updated_options)) {
|
225 |
+
$updated_options['changelog_version'] = CNB_VERSION;
|
226 |
+
}
|
227 |
+
return $original_settings['version'] != $updated_options['version'] || $original_settings['changelog_version'] != $updated_options['changelog_version'];
|
228 |
+
|
229 |
+
}
|
230 |
+
|
231 |
private function update_user_email_opt_in($current, $new) {
|
232 |
if (!key_exists('user_marketing_email_opt_in', $new)) {
|
233 |
return;
|
335 |
// set "migration done"
|
336 |
// We should really only do this once, so we need to save something in the settings to stop continuous migration.
|
337 |
add_option( 'cnb_cloud_migration_done', true );
|
338 |
+
CnbAdminNotices::get_instance()->success( '<p>Successfully connected to your Call Now Button cloud account.</p>' );
|
339 |
}
|
340 |
|
341 |
// If an API key was passed (no matter the status of activation)
|
src/admin/settings/CnbSettingsViewEdit.php
CHANGED
@@ -55,7 +55,7 @@ class CnbSettingsViewEdit {
|
|
55 |
}
|
56 |
|
57 |
private function render_error_reporting_options() {
|
58 |
-
$
|
59 |
?>
|
60 |
<tr>
|
61 |
<th colspan="2"><h2>Miscellaneous</h2></th>
|
@@ -66,7 +66,7 @@ class CnbSettingsViewEdit {
|
|
66 |
<input type="hidden" name="cnb[error_reporting]" value="0"/>
|
67 |
<input id="cnb-error-reporting" class="cnb_toggle_checkbox" type="checkbox"
|
68 |
name="cnb[error_reporting]"
|
69 |
-
value="1" <?php checked(
|
70 |
<label for="cnb-error-reporting" class="cnb_toggle_label">Toggle</label>
|
71 |
<span data-cnb_toggle_state_label="cnb-error-reporting"
|
72 |
class="cnb_toggle_state cnb_toggle_false">(Not sharing)</span>
|
@@ -158,7 +158,7 @@ class CnbSettingsViewEdit {
|
|
158 |
but it seems to be invalid or outdated.</p>
|
159 |
<p class="description">Clicking "Disconnect account" will drop the API key
|
160 |
and disconnect the plugin from your account. You will lose access to
|
161 |
-
your buttons and
|
162 |
callnowbutton.com account.
|
163 |
<br>
|
164 |
<input type="button" name="cnb_api_key_delete" id="cnb_api_key_delete"
|
@@ -177,7 +177,7 @@ class CnbSettingsViewEdit {
|
|
177 |
class="button button-secondary"
|
178 |
value="<?php esc_attr_e( 'Disconnect account' ) ?>"
|
179 |
onclick="return cnb_delete_apikey();"> </p>
|
180 |
-
<p class="description">Clicking "Disconnect account" will drop the API key and disconnect the plugin from your account. You will lose access to your buttons and
|
181 |
|
182 |
|
183 |
<input type="hidden" name="cnb[api_key]" id="cnb_api_key" value="delete_me" disabled="disabled"/>
|
@@ -357,14 +357,14 @@ class CnbSettingsViewEdit {
|
|
357 |
'<p>You can even replace it with an email button during your off-hours so people can still contact you.</p>',
|
358 |
'clock',
|
359 |
'<strong>Use the scheduler!</strong>',
|
360 |
-
'
|
361 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
362 |
);
|
363 |
( new CnbAdminFunctions() )->cnb_promobox(
|
364 |
'green',
|
365 |
'More buttons!',
|
366 |
-
'
|
367 |
-
'<p>If you need more phone numbers on a single page, then the Multibutton™ and the Buttonbar™ give you
|
368 |
'cloud',
|
369 |
'<strong>Try it out!</strong>',
|
370 |
'Learn more',
|
@@ -372,9 +372,9 @@ class CnbSettingsViewEdit {
|
|
372 |
);
|
373 |
( new CnbAdminFunctions() )->cnb_promobox(
|
374 |
'brown',
|
375 |
-
'
|
376 |
-
'
|
377 |
-
'<p>The
|
378 |
'<p>Try it out and enjoy scheduling, multiple buttons, more button types, animations and much more!</p>',
|
379 |
'money-alt',
|
380 |
'',
|
@@ -411,7 +411,7 @@ class CnbSettingsViewEdit {
|
|
411 |
</tr>
|
412 |
<tr>
|
413 |
<th scope="row">
|
414 |
-
<label for="cnb_cloud_enabled">
|
415 |
<?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
|
416 |
<a href="<?php echo esc_url( ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page() ) ?>"
|
417 |
class="cnb-nounderscore">
|
@@ -425,13 +425,13 @@ class CnbSettingsViewEdit {
|
|
425 |
<input id="cnb_cloud_enabled" class="cnb_toggle_checkbox" name="cnb[cloud_enabled]"
|
426 |
type="checkbox"
|
427 |
value="1" <?php checked( '1', $cnb_options['cloud_enabled'] ); ?> />
|
428 |
-
<label for="cnb_cloud_enabled" class="cnb_toggle_label">Enable
|
429 |
<span data-cnb_toggle_state_label="cnb_cloud_enabled"
|
430 |
class="cnb_toggle_state cnb_toggle_false">(Inactive)</span>
|
431 |
<span data-cnb_toggle_state_label="cnb_cloud_enabled"
|
432 |
class="cnb_toggle_state cnb_toggle_true">Active</span>
|
433 |
<?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
|
434 |
-
<p class="description">
|
435 |
<a href="<?php echo esc_url( ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page() ) ?>">Learn
|
436 |
more</a>
|
437 |
</p>
|
@@ -454,6 +454,7 @@ class CnbSettingsViewEdit {
|
|
454 |
$adminFunctions = new CnbAdminFunctions();
|
455 |
|
456 |
wp_enqueue_script( CNB_SLUG . '-settings' );
|
|
|
457 |
wp_enqueue_script( CNB_SLUG . '-timezone-picker-fix' );
|
458 |
wp_enqueue_script( CNB_SLUG . '-tally' );
|
459 |
|
@@ -476,17 +477,7 @@ class CnbSettingsViewEdit {
|
|
476 |
|
477 |
do_action( 'cnb_header' );
|
478 |
|
479 |
-
$cloud_successful = $status === 'cloud' && isset( $cnb_cloud_domain ) && ! ( $cnb_cloud_domain instanceof WP_Error );
|
480 |
-
if ( ! $cloud_successful ) { ?>
|
481 |
-
<script>
|
482 |
-
jQuery(() => {
|
483 |
-
const counter = jQuery("#cnb-nav-counter")
|
484 |
-
if (counter.length && counter.text() === '!') {
|
485 |
-
counter.hide();
|
486 |
-
}
|
487 |
-
});
|
488 |
-
</script>
|
489 |
-
<?php } ?>
|
490 |
|
491 |
<div class="cnb-two-column-section">
|
492 |
<div class="cnb-body-column">
|
55 |
}
|
56 |
|
57 |
private function render_error_reporting_options() {
|
58 |
+
$cnb_utils = new CnbUtils();
|
59 |
?>
|
60 |
<tr>
|
61 |
<th colspan="2"><h2>Miscellaneous</h2></th>
|
66 |
<input type="hidden" name="cnb[error_reporting]" value="0"/>
|
67 |
<input id="cnb-error-reporting" class="cnb_toggle_checkbox" type="checkbox"
|
68 |
name="cnb[error_reporting]"
|
69 |
+
value="1" <?php checked( $cnb_utils->is_reporting_enabled() ); ?> />
|
70 |
<label for="cnb-error-reporting" class="cnb_toggle_label">Toggle</label>
|
71 |
<span data-cnb_toggle_state_label="cnb-error-reporting"
|
72 |
class="cnb_toggle_state cnb_toggle_false">(Not sharing)</span>
|
158 |
but it seems to be invalid or outdated.</p>
|
159 |
<p class="description">Clicking "Disconnect account" will drop the API key
|
160 |
and disconnect the plugin from your account. You will lose access to
|
161 |
+
your buttons and cloud functionality until you reconnect with a
|
162 |
callnowbutton.com account.
|
163 |
<br>
|
164 |
<input type="button" name="cnb_api_key_delete" id="cnb_api_key_delete"
|
177 |
class="button button-secondary"
|
178 |
value="<?php esc_attr_e( 'Disconnect account' ) ?>"
|
179 |
onclick="return cnb_delete_apikey();"> </p>
|
180 |
+
<p class="description">Clicking "Disconnect account" will drop the API key and disconnect the plugin from your account. You will lose access to your buttons and all cloud functionality until you reconnect with a callnowbutton.com account.</p>
|
181 |
|
182 |
|
183 |
<input type="hidden" name="cnb[api_key]" id="cnb_api_key" value="delete_me" disabled="disabled"/>
|
357 |
'<p>You can even replace it with an email button during your off-hours so people can still contact you.</p>',
|
358 |
'clock',
|
359 |
'<strong>Use the scheduler!</strong>',
|
360 |
+
'Enable cloud',
|
361 |
( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
|
362 |
);
|
363 |
( new CnbAdminFunctions() )->cnb_promobox(
|
364 |
'green',
|
365 |
'More buttons!',
|
366 |
+
'Enable cloud to get lots of extra buttons. Coupled with advanced page selection options you can get really creative.</p>' .
|
367 |
+
'<p>If you need more phone numbers on a single page, then the Multibutton™ and the Buttonbar™ give you excellent options.</p>',
|
368 |
'cloud',
|
369 |
'<strong>Try it out!</strong>',
|
370 |
'Learn more',
|
372 |
);
|
373 |
( new CnbAdminFunctions() )->cnb_promobox(
|
374 |
'brown',
|
375 |
+
'Add more features!',
|
376 |
+
'Cloud adds a ton of extra power to the Call Now Button.</p>' .
|
377 |
+
'<p>The Free plan shows a little branding with your buttons but gives you access to 99% of all cloud features.</p>' .
|
378 |
'<p>Try it out and enjoy scheduling, multiple buttons, more button types, animations and much more!</p>',
|
379 |
'money-alt',
|
380 |
'',
|
411 |
</tr>
|
412 |
<tr>
|
413 |
<th scope="row">
|
414 |
+
<label for="cnb_cloud_enabled">Cloud
|
415 |
<?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
|
416 |
<a href="<?php echo esc_url( ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page() ) ?>"
|
417 |
class="cnb-nounderscore">
|
425 |
<input id="cnb_cloud_enabled" class="cnb_toggle_checkbox" name="cnb[cloud_enabled]"
|
426 |
type="checkbox"
|
427 |
value="1" <?php checked( '1', $cnb_options['cloud_enabled'] ); ?> />
|
428 |
+
<label for="cnb_cloud_enabled" class="cnb_toggle_label">Enable Cloud</label>
|
429 |
<span data-cnb_toggle_state_label="cnb_cloud_enabled"
|
430 |
class="cnb_toggle_state cnb_toggle_false">(Inactive)</span>
|
431 |
<span data-cnb_toggle_state_label="cnb_cloud_enabled"
|
432 |
class="cnb_toggle_state cnb_toggle_true">Active</span>
|
433 |
<?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
|
434 |
+
<p class="description"><a href="<?php echo esc_url( ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page() ) ?>">Sign up</a> (free) to enable cloud and enjoy extra functionality.
|
435 |
<a href="<?php echo esc_url( ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page() ) ?>">Learn
|
436 |
more</a>
|
437 |
</p>
|
454 |
$adminFunctions = new CnbAdminFunctions();
|
455 |
|
456 |
wp_enqueue_script( CNB_SLUG . '-settings' );
|
457 |
+
wp_enqueue_script( CNB_SLUG . '-premium-activation' );
|
458 |
wp_enqueue_script( CNB_SLUG . '-timezone-picker-fix' );
|
459 |
wp_enqueue_script( CNB_SLUG . '-tally' );
|
460 |
|
477 |
|
478 |
do_action( 'cnb_header' );
|
479 |
|
480 |
+
$cloud_successful = $status === 'cloud' && isset( $cnb_cloud_domain ) && ! ( $cnb_cloud_domain instanceof WP_Error ); ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
481 |
|
482 |
<div class="cnb-two-column-section">
|
483 |
<div class="cnb-body-column">
|
src/autoload.php
CHANGED
@@ -57,6 +57,9 @@ spl_autoload_register(
|
|
57 |
'cnb\\admin\\domain\\cnbdomainviewupgradefinished' => '/admin/domain/partials/CnbDomainViewUpgradeFinished.php',
|
58 |
'cnb\\admin\\domain\\cnbdomainviewupgradeinprogress' => '/admin/domain/partials/CnbDomainViewUpgradeInProgress.php',
|
59 |
'cnb\\admin\\domain\\cnbdomainviewupgradeoverview' => '/admin/domain/partials/CnbDomainViewUpgradeOverview.php',
|
|
|
|
|
|
|
60 |
'cnb\\admin\\legacy\\cnblegacycontroller' => '/admin/legacy/CnbLegacyController.php',
|
61 |
'cnb\\admin\\legacy\\cnblegacyedit' => '/admin/legacy/CnbLegacyEdit.php',
|
62 |
'cnb\\admin\\legacy\\cnblegacyupgrade' => '/admin/legacy/CnbLegacyUpgrade.php',
|
57 |
'cnb\\admin\\domain\\cnbdomainviewupgradefinished' => '/admin/domain/partials/CnbDomainViewUpgradeFinished.php',
|
58 |
'cnb\\admin\\domain\\cnbdomainviewupgradeinprogress' => '/admin/domain/partials/CnbDomainViewUpgradeInProgress.php',
|
59 |
'cnb\\admin\\domain\\cnbdomainviewupgradeoverview' => '/admin/domain/partials/CnbDomainViewUpgradeOverview.php',
|
60 |
+
'cnb\\admin\\gettingstarted\\gettingstartedcontroller' => '/admin/getting-started/class-getting-started-controller.php',
|
61 |
+
'cnb\\admin\\gettingstarted\\gettingstartedrouter' => '/admin/getting-started/class-getting-started-router.php',
|
62 |
+
'cnb\\admin\\gettingstarted\\gettingstartedview' => '/admin/getting-started/class-getting-started-view.php',
|
63 |
'cnb\\admin\\legacy\\cnblegacycontroller' => '/admin/legacy/CnbLegacyController.php',
|
64 |
'cnb\\admin\\legacy\\cnblegacyedit' => '/admin/legacy/CnbLegacyEdit.php',
|
65 |
'cnb\\admin\\legacy\\cnblegacyupgrade' => '/admin/legacy/CnbLegacyUpgrade.php',
|
src/composer.json
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"require": {
|
3 |
-
"php": "^7.2|^8.0",
|
4 |
-
"sentry/sdk": "3.2.0"
|
5 |
-
}
|
6 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
src/composer.lock
DELETED
@@ -1,1884 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"_readme": [
|
3 |
-
"This file locks the dependencies of your project to a known state",
|
4 |
-
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
5 |
-
"This file is @generated automatically"
|
6 |
-
],
|
7 |
-
"content-hash": "7bf6e13ecfe6677f5e64a1632bf3f99c",
|
8 |
-
"packages": [
|
9 |
-
{
|
10 |
-
"name": "clue/stream-filter",
|
11 |
-
"version": "v1.6.0",
|
12 |
-
"source": {
|
13 |
-
"type": "git",
|
14 |
-
"url": "https://github.com/clue/stream-filter.git",
|
15 |
-
"reference": "d6169430c7731d8509da7aecd0af756a5747b78e"
|
16 |
-
},
|
17 |
-
"dist": {
|
18 |
-
"type": "zip",
|
19 |
-
"url": "https://api.github.com/repos/clue/stream-filter/zipball/d6169430c7731d8509da7aecd0af756a5747b78e",
|
20 |
-
"reference": "d6169430c7731d8509da7aecd0af756a5747b78e",
|
21 |
-
"shasum": ""
|
22 |
-
},
|
23 |
-
"require": {
|
24 |
-
"php": ">=5.3"
|
25 |
-
},
|
26 |
-
"require-dev": {
|
27 |
-
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36"
|
28 |
-
},
|
29 |
-
"type": "library",
|
30 |
-
"autoload": {
|
31 |
-
"files": [
|
32 |
-
"src/functions_include.php"
|
33 |
-
],
|
34 |
-
"psr-4": {
|
35 |
-
"Clue\\StreamFilter\\": "src/"
|
36 |
-
}
|
37 |
-
},
|
38 |
-
"notification-url": "https://packagist.org/downloads/",
|
39 |
-
"license": [
|
40 |
-
"MIT"
|
41 |
-
],
|
42 |
-
"authors": [
|
43 |
-
{
|
44 |
-
"name": "Christian Lück",
|
45 |
-
"email": "christian@clue.engineering"
|
46 |
-
}
|
47 |
-
],
|
48 |
-
"description": "A simple and modern approach to stream filtering in PHP",
|
49 |
-
"homepage": "https://github.com/clue/php-stream-filter",
|
50 |
-
"keywords": [
|
51 |
-
"bucket brigade",
|
52 |
-
"callback",
|
53 |
-
"filter",
|
54 |
-
"php_user_filter",
|
55 |
-
"stream",
|
56 |
-
"stream_filter_append",
|
57 |
-
"stream_filter_register"
|
58 |
-
],
|
59 |
-
"support": {
|
60 |
-
"issues": "https://github.com/clue/stream-filter/issues",
|
61 |
-
"source": "https://github.com/clue/stream-filter/tree/v1.6.0"
|
62 |
-
},
|
63 |
-
"funding": [
|
64 |
-
{
|
65 |
-
"url": "https://clue.engineering/support",
|
66 |
-
"type": "custom"
|
67 |
-
},
|
68 |
-
{
|
69 |
-
"url": "https://github.com/clue",
|
70 |
-
"type": "github"
|
71 |
-
}
|
72 |
-
],
|
73 |
-
"time": "2022-02-21T13:15:14+00:00"
|
74 |
-
},
|
75 |
-
{
|
76 |
-
"name": "guzzlehttp/promises",
|
77 |
-
"version": "1.5.1",
|
78 |
-
"source": {
|
79 |
-
"type": "git",
|
80 |
-
"url": "https://github.com/guzzle/promises.git",
|
81 |
-
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da"
|
82 |
-
},
|
83 |
-
"dist": {
|
84 |
-
"type": "zip",
|
85 |
-
"url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
86 |
-
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
87 |
-
"shasum": ""
|
88 |
-
},
|
89 |
-
"require": {
|
90 |
-
"php": ">=5.5"
|
91 |
-
},
|
92 |
-
"require-dev": {
|
93 |
-
"symfony/phpunit-bridge": "^4.4 || ^5.1"
|
94 |
-
},
|
95 |
-
"type": "library",
|
96 |
-
"extra": {
|
97 |
-
"branch-alias": {
|
98 |
-
"dev-master": "1.5-dev"
|
99 |
-
}
|
100 |
-
},
|
101 |
-
"autoload": {
|
102 |
-
"files": [
|
103 |
-
"src/functions_include.php"
|
104 |
-
],
|
105 |
-
"psr-4": {
|
106 |
-
"GuzzleHttp\\Promise\\": "src/"
|
107 |
-
}
|
108 |
-
},
|
109 |
-
"notification-url": "https://packagist.org/downloads/",
|
110 |
-
"license": [
|
111 |
-
"MIT"
|
112 |
-
],
|
113 |
-
"authors": [
|
114 |
-
{
|
115 |
-
"name": "Graham Campbell",
|
116 |
-
"email": "hello@gjcampbell.co.uk",
|
117 |
-
"homepage": "https://github.com/GrahamCampbell"
|
118 |
-
},
|
119 |
-
{
|
120 |
-
"name": "Michael Dowling",
|
121 |
-
"email": "mtdowling@gmail.com",
|
122 |
-
"homepage": "https://github.com/mtdowling"
|
123 |
-
},
|
124 |
-
{
|
125 |
-
"name": "Tobias Nyholm",
|
126 |
-
"email": "tobias.nyholm@gmail.com",
|
127 |
-
"homepage": "https://github.com/Nyholm"
|
128 |
-
},
|
129 |
-
{
|
130 |
-
"name": "Tobias Schultze",
|
131 |
-
"email": "webmaster@tubo-world.de",
|
132 |
-
"homepage": "https://github.com/Tobion"
|
133 |
-
}
|
134 |
-
],
|
135 |
-
"description": "Guzzle promises library",
|
136 |
-
"keywords": [
|
137 |
-
"promise"
|
138 |
-
],
|
139 |
-
"support": {
|
140 |
-
"issues": "https://github.com/guzzle/promises/issues",
|
141 |
-
"source": "https://github.com/guzzle/promises/tree/1.5.1"
|
142 |
-
},
|
143 |
-
"funding": [
|
144 |
-
{
|
145 |
-
"url": "https://github.com/GrahamCampbell",
|
146 |
-
"type": "github"
|
147 |
-
},
|
148 |
-
{
|
149 |
-
"url": "https://github.com/Nyholm",
|
150 |
-
"type": "github"
|
151 |
-
},
|
152 |
-
{
|
153 |
-
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
|
154 |
-
"type": "tidelift"
|
155 |
-
}
|
156 |
-
],
|
157 |
-
"time": "2021-10-22T20:56:57+00:00"
|
158 |
-
},
|
159 |
-
{
|
160 |
-
"name": "guzzlehttp/psr7",
|
161 |
-
"version": "2.3.0",
|
162 |
-
"source": {
|
163 |
-
"type": "git",
|
164 |
-
"url": "https://github.com/guzzle/psr7.git",
|
165 |
-
"reference": "83260bb50b8fc753c72d14dc1621a2dac31877ee"
|
166 |
-
},
|
167 |
-
"dist": {
|
168 |
-
"type": "zip",
|
169 |
-
"url": "https://api.github.com/repos/guzzle/psr7/zipball/83260bb50b8fc753c72d14dc1621a2dac31877ee",
|
170 |
-
"reference": "83260bb50b8fc753c72d14dc1621a2dac31877ee",
|
171 |
-
"shasum": ""
|
172 |
-
},
|
173 |
-
"require": {
|
174 |
-
"php": "^7.2.5 || ^8.0",
|
175 |
-
"psr/http-factory": "^1.0",
|
176 |
-
"psr/http-message": "^1.0",
|
177 |
-
"ralouphie/getallheaders": "^3.0"
|
178 |
-
},
|
179 |
-
"provide": {
|
180 |
-
"psr/http-factory-implementation": "1.0",
|
181 |
-
"psr/http-message-implementation": "1.0"
|
182 |
-
},
|
183 |
-
"require-dev": {
|
184 |
-
"bamarni/composer-bin-plugin": "^1.4.1",
|
185 |
-
"http-interop/http-factory-tests": "^0.9",
|
186 |
-
"phpunit/phpunit": "^8.5.8 || ^9.3.10"
|
187 |
-
},
|
188 |
-
"suggest": {
|
189 |
-
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
190 |
-
},
|
191 |
-
"type": "library",
|
192 |
-
"extra": {
|
193 |
-
"branch-alias": {
|
194 |
-
"dev-master": "2.3-dev"
|
195 |
-
}
|
196 |
-
},
|
197 |
-
"autoload": {
|
198 |
-
"psr-4": {
|
199 |
-
"GuzzleHttp\\Psr7\\": "src/"
|
200 |
-
}
|
201 |
-
},
|
202 |
-
"notification-url": "https://packagist.org/downloads/",
|
203 |
-
"license": [
|
204 |
-
"MIT"
|
205 |
-
],
|
206 |
-
"authors": [
|
207 |
-
{
|
208 |
-
"name": "Graham Campbell",
|
209 |
-
"email": "hello@gjcampbell.co.uk",
|
210 |
-
"homepage": "https://github.com/GrahamCampbell"
|
211 |
-
},
|
212 |
-
{
|
213 |
-
"name": "Michael Dowling",
|
214 |
-
"email": "mtdowling@gmail.com",
|
215 |
-
"homepage": "https://github.com/mtdowling"
|
216 |
-
},
|
217 |
-
{
|
218 |
-
"name": "George Mponos",
|
219 |
-
"email": "gmponos@gmail.com",
|
220 |
-
"homepage": "https://github.com/gmponos"
|
221 |
-
},
|
222 |
-
{
|
223 |
-
"name": "Tobias Nyholm",
|
224 |
-
"email": "tobias.nyholm@gmail.com",
|
225 |
-
"homepage": "https://github.com/Nyholm"
|
226 |
-
},
|
227 |
-
{
|
228 |
-
"name": "Márk Sági-Kazár",
|
229 |
-
"email": "mark.sagikazar@gmail.com",
|
230 |
-
"homepage": "https://github.com/sagikazarmark"
|
231 |
-
},
|
232 |
-
{
|
233 |
-
"name": "Tobias Schultze",
|
234 |
-
"email": "webmaster@tubo-world.de",
|
235 |
-
"homepage": "https://github.com/Tobion"
|
236 |
-
},
|
237 |
-
{
|
238 |
-
"name": "Márk Sági-Kazár",
|
239 |
-
"email": "mark.sagikazar@gmail.com",
|
240 |
-
"homepage": "https://sagikazarmark.hu"
|
241 |
-
}
|
242 |
-
],
|
243 |
-
"description": "PSR-7 message implementation that also provides common utility methods",
|
244 |
-
"keywords": [
|
245 |
-
"http",
|
246 |
-
"message",
|
247 |
-
"psr-7",
|
248 |
-
"request",
|
249 |
-
"response",
|
250 |
-
"stream",
|
251 |
-
"uri",
|
252 |
-
"url"
|
253 |
-
],
|
254 |
-
"support": {
|
255 |
-
"issues": "https://github.com/guzzle/psr7/issues",
|
256 |
-
"source": "https://github.com/guzzle/psr7/tree/2.3.0"
|
257 |
-
},
|
258 |
-
"funding": [
|
259 |
-
{
|
260 |
-
"url": "https://github.com/GrahamCampbell",
|
261 |
-
"type": "github"
|
262 |
-
},
|
263 |
-
{
|
264 |
-
"url": "https://github.com/Nyholm",
|
265 |
-
"type": "github"
|
266 |
-
},
|
267 |
-
{
|
268 |
-
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
|
269 |
-
"type": "tidelift"
|
270 |
-
}
|
271 |
-
],
|
272 |
-
"time": "2022-06-09T08:26:02+00:00"
|
273 |
-
},
|
274 |
-
{
|
275 |
-
"name": "http-interop/http-factory-guzzle",
|
276 |
-
"version": "1.2.0",
|
277 |
-
"source": {
|
278 |
-
"type": "git",
|
279 |
-
"url": "https://github.com/http-interop/http-factory-guzzle.git",
|
280 |
-
"reference": "8f06e92b95405216b237521cc64c804dd44c4a81"
|
281 |
-
},
|
282 |
-
"dist": {
|
283 |
-
"type": "zip",
|
284 |
-
"url": "https://api.github.com/repos/http-interop/http-factory-guzzle/zipball/8f06e92b95405216b237521cc64c804dd44c4a81",
|
285 |
-
"reference": "8f06e92b95405216b237521cc64c804dd44c4a81",
|
286 |
-
"shasum": ""
|
287 |
-
},
|
288 |
-
"require": {
|
289 |
-
"guzzlehttp/psr7": "^1.7||^2.0",
|
290 |
-
"php": ">=7.3",
|
291 |
-
"psr/http-factory": "^1.0"
|
292 |
-
},
|
293 |
-
"provide": {
|
294 |
-
"psr/http-factory-implementation": "^1.0"
|
295 |
-
},
|
296 |
-
"require-dev": {
|
297 |
-
"http-interop/http-factory-tests": "^0.9",
|
298 |
-
"phpunit/phpunit": "^9.5"
|
299 |
-
},
|
300 |
-
"suggest": {
|
301 |
-
"guzzlehttp/psr7": "Includes an HTTP factory starting in version 2.0"
|
302 |
-
},
|
303 |
-
"type": "library",
|
304 |
-
"autoload": {
|
305 |
-
"psr-4": {
|
306 |
-
"Http\\Factory\\Guzzle\\": "src/"
|
307 |
-
}
|
308 |
-
},
|
309 |
-
"notification-url": "https://packagist.org/downloads/",
|
310 |
-
"license": [
|
311 |
-
"MIT"
|
312 |
-
],
|
313 |
-
"authors": [
|
314 |
-
{
|
315 |
-
"name": "PHP-FIG",
|
316 |
-
"homepage": "http://www.php-fig.org/"
|
317 |
-
}
|
318 |
-
],
|
319 |
-
"description": "An HTTP Factory using Guzzle PSR7",
|
320 |
-
"keywords": [
|
321 |
-
"factory",
|
322 |
-
"http",
|
323 |
-
"psr-17",
|
324 |
-
"psr-7"
|
325 |
-
],
|
326 |
-
"support": {
|
327 |
-
"issues": "https://github.com/http-interop/http-factory-guzzle/issues",
|
328 |
-
"source": "https://github.com/http-interop/http-factory-guzzle/tree/1.2.0"
|
329 |
-
},
|
330 |
-
"time": "2021-07-21T13:50:14+00:00"
|
331 |
-
},
|
332 |
-
{
|
333 |
-
"name": "jean85/pretty-package-versions",
|
334 |
-
"version": "2.0.5",
|
335 |
-
"source": {
|
336 |
-
"type": "git",
|
337 |
-
"url": "https://github.com/Jean85/pretty-package-versions.git",
|
338 |
-
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af"
|
339 |
-
},
|
340 |
-
"dist": {
|
341 |
-
"type": "zip",
|
342 |
-
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af",
|
343 |
-
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af",
|
344 |
-
"shasum": ""
|
345 |
-
},
|
346 |
-
"require": {
|
347 |
-
"composer-runtime-api": "^2.0.0",
|
348 |
-
"php": "^7.1|^8.0"
|
349 |
-
},
|
350 |
-
"require-dev": {
|
351 |
-
"friendsofphp/php-cs-fixer": "^2.17",
|
352 |
-
"jean85/composer-provided-replaced-stub-package": "^1.0",
|
353 |
-
"phpstan/phpstan": "^0.12.66",
|
354 |
-
"phpunit/phpunit": "^7.5|^8.5|^9.4",
|
355 |
-
"vimeo/psalm": "^4.3"
|
356 |
-
},
|
357 |
-
"type": "library",
|
358 |
-
"extra": {
|
359 |
-
"branch-alias": {
|
360 |
-
"dev-master": "1.x-dev"
|
361 |
-
}
|
362 |
-
},
|
363 |
-
"autoload": {
|
364 |
-
"psr-4": {
|
365 |
-
"Jean85\\": "src/"
|
366 |
-
}
|
367 |
-
},
|
368 |
-
"notification-url": "https://packagist.org/downloads/",
|
369 |
-
"license": [
|
370 |
-
"MIT"
|
371 |
-
],
|
372 |
-
"authors": [
|
373 |
-
{
|
374 |
-
"name": "Alessandro Lai",
|
375 |
-
"email": "alessandro.lai85@gmail.com"
|
376 |
-
}
|
377 |
-
],
|
378 |
-
"description": "A library to get pretty versions strings of installed dependencies",
|
379 |
-
"keywords": [
|
380 |
-
"composer",
|
381 |
-
"package",
|
382 |
-
"release",
|
383 |
-
"versions"
|
384 |
-
],
|
385 |
-
"support": {
|
386 |
-
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
|
387 |
-
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5"
|
388 |
-
},
|
389 |
-
"time": "2021-10-08T21:21:46+00:00"
|
390 |
-
},
|
391 |
-
{
|
392 |
-
"name": "php-http/client-common",
|
393 |
-
"version": "2.5.0",
|
394 |
-
"source": {
|
395 |
-
"type": "git",
|
396 |
-
"url": "https://github.com/php-http/client-common.git",
|
397 |
-
"reference": "d135751167d57e27c74de674d6a30cef2dc8e054"
|
398 |
-
},
|
399 |
-
"dist": {
|
400 |
-
"type": "zip",
|
401 |
-
"url": "https://api.github.com/repos/php-http/client-common/zipball/d135751167d57e27c74de674d6a30cef2dc8e054",
|
402 |
-
"reference": "d135751167d57e27c74de674d6a30cef2dc8e054",
|
403 |
-
"shasum": ""
|
404 |
-
},
|
405 |
-
"require": {
|
406 |
-
"php": "^7.1 || ^8.0",
|
407 |
-
"php-http/httplug": "^2.0",
|
408 |
-
"php-http/message": "^1.6",
|
409 |
-
"php-http/message-factory": "^1.0",
|
410 |
-
"psr/http-client": "^1.0",
|
411 |
-
"psr/http-factory": "^1.0",
|
412 |
-
"psr/http-message": "^1.0",
|
413 |
-
"symfony/options-resolver": "~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0 || ^6.0",
|
414 |
-
"symfony/polyfill-php80": "^1.17"
|
415 |
-
},
|
416 |
-
"require-dev": {
|
417 |
-
"doctrine/instantiator": "^1.1",
|
418 |
-
"guzzlehttp/psr7": "^1.4",
|
419 |
-
"nyholm/psr7": "^1.2",
|
420 |
-
"phpspec/phpspec": "^5.1 || ^6.3 || ^7.1",
|
421 |
-
"phpspec/prophecy": "^1.10.2",
|
422 |
-
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3"
|
423 |
-
},
|
424 |
-
"suggest": {
|
425 |
-
"ext-json": "To detect JSON responses with the ContentTypePlugin",
|
426 |
-
"ext-libxml": "To detect XML responses with the ContentTypePlugin",
|
427 |
-
"php-http/cache-plugin": "PSR-6 Cache plugin",
|
428 |
-
"php-http/logger-plugin": "PSR-3 Logger plugin",
|
429 |
-
"php-http/stopwatch-plugin": "Symfony Stopwatch plugin"
|
430 |
-
},
|
431 |
-
"type": "library",
|
432 |
-
"extra": {
|
433 |
-
"branch-alias": {
|
434 |
-
"dev-master": "2.3.x-dev"
|
435 |
-
}
|
436 |
-
},
|
437 |
-
"autoload": {
|
438 |
-
"psr-4": {
|
439 |
-
"Http\\Client\\Common\\": "src/"
|
440 |
-
}
|
441 |
-
},
|
442 |
-
"notification-url": "https://packagist.org/downloads/",
|
443 |
-
"license": [
|
444 |
-
"MIT"
|
445 |
-
],
|
446 |
-
"authors": [
|
447 |
-
{
|
448 |
-
"name": "Márk Sági-Kazár",
|
449 |
-
"email": "mark.sagikazar@gmail.com"
|
450 |
-
}
|
451 |
-
],
|
452 |
-
"description": "Common HTTP Client implementations and tools for HTTPlug",
|
453 |
-
"homepage": "http://httplug.io",
|
454 |
-
"keywords": [
|
455 |
-
"client",
|
456 |
-
"common",
|
457 |
-
"http",
|
458 |
-
"httplug"
|
459 |
-
],
|
460 |
-
"support": {
|
461 |
-
"issues": "https://github.com/php-http/client-common/issues",
|
462 |
-
"source": "https://github.com/php-http/client-common/tree/2.5.0"
|
463 |
-
},
|
464 |
-
"time": "2021-11-26T15:01:24+00:00"
|
465 |
-
},
|
466 |
-
{
|
467 |
-
"name": "php-http/discovery",
|
468 |
-
"version": "1.14.2",
|
469 |
-
"source": {
|
470 |
-
"type": "git",
|
471 |
-
"url": "https://github.com/php-http/discovery.git",
|
472 |
-
"reference": "c8d48852fbc052454af42f6de27635ddd916b959"
|
473 |
-
},
|
474 |
-
"dist": {
|
475 |
-
"type": "zip",
|
476 |
-
"url": "https://api.github.com/repos/php-http/discovery/zipball/c8d48852fbc052454af42f6de27635ddd916b959",
|
477 |
-
"reference": "c8d48852fbc052454af42f6de27635ddd916b959",
|
478 |
-
"shasum": ""
|
479 |
-
},
|
480 |
-
"require": {
|
481 |
-
"php": "^7.1 || ^8.0"
|
482 |
-
},
|
483 |
-
"conflict": {
|
484 |
-
"nyholm/psr7": "<1.0"
|
485 |
-
},
|
486 |
-
"require-dev": {
|
487 |
-
"graham-campbell/phpspec-skip-example-extension": "^5.0",
|
488 |
-
"php-http/httplug": "^1.0 || ^2.0",
|
489 |
-
"php-http/message-factory": "^1.0",
|
490 |
-
"phpspec/phpspec": "^5.1 || ^6.1"
|
491 |
-
},
|
492 |
-
"suggest": {
|
493 |
-
"php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories"
|
494 |
-
},
|
495 |
-
"type": "library",
|
496 |
-
"extra": {
|
497 |
-
"branch-alias": {
|
498 |
-
"dev-master": "1.9-dev"
|
499 |
-
}
|
500 |
-
},
|
501 |
-
"autoload": {
|
502 |
-
"psr-4": {
|
503 |
-
"Http\\Discovery\\": "src/"
|
504 |
-
}
|
505 |
-
},
|
506 |
-
"notification-url": "https://packagist.org/downloads/",
|
507 |
-
"license": [
|
508 |
-
"MIT"
|
509 |
-
],
|
510 |
-
"authors": [
|
511 |
-
{
|
512 |
-
"name": "Márk Sági-Kazár",
|
513 |
-
"email": "mark.sagikazar@gmail.com"
|
514 |
-
}
|
515 |
-
],
|
516 |
-
"description": "Finds installed HTTPlug implementations and PSR-7 message factories",
|
517 |
-
"homepage": "http://php-http.org",
|
518 |
-
"keywords": [
|
519 |
-
"adapter",
|
520 |
-
"client",
|
521 |
-
"discovery",
|
522 |
-
"factory",
|
523 |
-
"http",
|
524 |
-
"message",
|
525 |
-
"psr7"
|
526 |
-
],
|
527 |
-
"support": {
|
528 |
-
"issues": "https://github.com/php-http/discovery/issues",
|
529 |
-
"source": "https://github.com/php-http/discovery/tree/1.14.2"
|
530 |
-
},
|
531 |
-
"time": "2022-05-25T07:26:05+00:00"
|
532 |
-
},
|
533 |
-
{
|
534 |
-
"name": "php-http/httplug",
|
535 |
-
"version": "2.3.0",
|
536 |
-
"source": {
|
537 |
-
"type": "git",
|
538 |
-
"url": "https://github.com/php-http/httplug.git",
|
539 |
-
"reference": "f640739f80dfa1152533976e3c112477f69274eb"
|
540 |
-
},
|
541 |
-
"dist": {
|
542 |
-
"type": "zip",
|
543 |
-
"url": "https://api.github.com/repos/php-http/httplug/zipball/f640739f80dfa1152533976e3c112477f69274eb",
|
544 |
-
"reference": "f640739f80dfa1152533976e3c112477f69274eb",
|
545 |
-
"shasum": ""
|
546 |
-
},
|
547 |
-
"require": {
|
548 |
-
"php": "^7.1 || ^8.0",
|
549 |
-
"php-http/promise": "^1.1",
|
550 |
-
"psr/http-client": "^1.0",
|
551 |
-
"psr/http-message": "^1.0"
|
552 |
-
},
|
553 |
-
"require-dev": {
|
554 |
-
"friends-of-phpspec/phpspec-code-coverage": "^4.1",
|
555 |
-
"phpspec/phpspec": "^5.1 || ^6.0"
|
556 |
-
},
|
557 |
-
"type": "library",
|
558 |
-
"extra": {
|
559 |
-
"branch-alias": {
|
560 |
-
"dev-master": "2.x-dev"
|
561 |
-
}
|
562 |
-
},
|
563 |
-
"autoload": {
|
564 |
-
"psr-4": {
|
565 |
-
"Http\\Client\\": "src/"
|
566 |
-
}
|
567 |
-
},
|
568 |
-
"notification-url": "https://packagist.org/downloads/",
|
569 |
-
"license": [
|
570 |
-
"MIT"
|
571 |
-
],
|
572 |
-
"authors": [
|
573 |
-
{
|
574 |
-
"name": "Eric GELOEN",
|
575 |
-
"email": "geloen.eric@gmail.com"
|
576 |
-
},
|
577 |
-
{
|
578 |
-
"name": "Márk Sági-Kazár",
|
579 |
-
"email": "mark.sagikazar@gmail.com",
|
580 |
-
"homepage": "https://sagikazarmark.hu"
|
581 |
-
}
|
582 |
-
],
|
583 |
-
"description": "HTTPlug, the HTTP client abstraction for PHP",
|
584 |
-
"homepage": "http://httplug.io",
|
585 |
-
"keywords": [
|
586 |
-
"client",
|
587 |
-
"http"
|
588 |
-
],
|
589 |
-
"support": {
|
590 |
-
"issues": "https://github.com/php-http/httplug/issues",
|
591 |
-
"source": "https://github.com/php-http/httplug/tree/2.3.0"
|
592 |
-
},
|
593 |
-
"time": "2022-02-21T09:52:22+00:00"
|
594 |
-
},
|
595 |
-
{
|
596 |
-
"name": "php-http/message",
|
597 |
-
"version": "1.13.0",
|
598 |
-
"source": {
|
599 |
-
"type": "git",
|
600 |
-
"url": "https://github.com/php-http/message.git",
|
601 |
-
"reference": "7886e647a30a966a1a8d1dad1845b71ca8678361"
|
602 |
-
},
|
603 |
-
"dist": {
|
604 |
-
"type": "zip",
|
605 |
-
"url": "https://api.github.com/repos/php-http/message/zipball/7886e647a30a966a1a8d1dad1845b71ca8678361",
|
606 |
-
"reference": "7886e647a30a966a1a8d1dad1845b71ca8678361",
|
607 |
-
"shasum": ""
|
608 |
-
},
|
609 |
-
"require": {
|
610 |
-
"clue/stream-filter": "^1.5",
|
611 |
-
"php": "^7.1 || ^8.0",
|
612 |
-
"php-http/message-factory": "^1.0.2",
|
613 |
-
"psr/http-message": "^1.0"
|
614 |
-
},
|
615 |
-
"provide": {
|
616 |
-
"php-http/message-factory-implementation": "1.0"
|
617 |
-
},
|
618 |
-
"require-dev": {
|
619 |
-
"ergebnis/composer-normalize": "^2.6",
|
620 |
-
"ext-zlib": "*",
|
621 |
-
"guzzlehttp/psr7": "^1.0",
|
622 |
-
"laminas/laminas-diactoros": "^2.0",
|
623 |
-
"phpspec/phpspec": "^5.1 || ^6.3 || ^7.1",
|
624 |
-
"slim/slim": "^3.0"
|
625 |
-
},
|
626 |
-
"suggest": {
|
627 |
-
"ext-zlib": "Used with compressor/decompressor streams",
|
628 |
-
"guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories",
|
629 |
-
"laminas/laminas-diactoros": "Used with Diactoros Factories",
|
630 |
-
"slim/slim": "Used with Slim Framework PSR-7 implementation"
|
631 |
-
},
|
632 |
-
"type": "library",
|
633 |
-
"extra": {
|
634 |
-
"branch-alias": {
|
635 |
-
"dev-master": "1.10-dev"
|
636 |
-
}
|
637 |
-
},
|
638 |
-
"autoload": {
|
639 |
-
"files": [
|
640 |
-
"src/filters.php"
|
641 |
-
],
|
642 |
-
"psr-4": {
|
643 |
-
"Http\\Message\\": "src/"
|
644 |
-
}
|
645 |
-
},
|
646 |
-
"notification-url": "https://packagist.org/downloads/",
|
647 |
-
"license": [
|
648 |
-
"MIT"
|
649 |
-
],
|
650 |
-
"authors": [
|
651 |
-
{
|
652 |
-
"name": "Márk Sági-Kazár",
|
653 |
-
"email": "mark.sagikazar@gmail.com"
|
654 |
-
}
|
655 |
-
],
|
656 |
-
"description": "HTTP Message related tools",
|
657 |
-
"homepage": "http://php-http.org",
|
658 |
-
"keywords": [
|
659 |
-
"http",
|
660 |
-
"message",
|
661 |
-
"psr-7"
|
662 |
-
],
|
663 |
-
"support": {
|
664 |
-
"issues": "https://github.com/php-http/message/issues",
|
665 |
-
"source": "https://github.com/php-http/message/tree/1.13.0"
|
666 |
-
},
|
667 |
-
"time": "2022-02-11T13:41:14+00:00"
|
668 |
-
},
|
669 |
-
{
|
670 |
-
"name": "php-http/message-factory",
|
671 |
-
"version": "v1.0.2",
|
672 |
-
"source": {
|
673 |
-
"type": "git",
|
674 |
-
"url": "https://github.com/php-http/message-factory.git",
|
675 |
-
"reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1"
|
676 |
-
},
|
677 |
-
"dist": {
|
678 |
-
"type": "zip",
|
679 |
-
"url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1",
|
680 |
-
"reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1",
|
681 |
-
"shasum": ""
|
682 |
-
},
|
683 |
-
"require": {
|
684 |
-
"php": ">=5.4",
|
685 |
-
"psr/http-message": "^1.0"
|
686 |
-
},
|
687 |
-
"type": "library",
|
688 |
-
"extra": {
|
689 |
-
"branch-alias": {
|
690 |
-
"dev-master": "1.0-dev"
|
691 |
-
}
|
692 |
-
},
|
693 |
-
"autoload": {
|
694 |
-
"psr-4": {
|
695 |
-
"Http\\Message\\": "src/"
|
696 |
-
}
|
697 |
-
},
|
698 |
-
"notification-url": "https://packagist.org/downloads/",
|
699 |
-
"license": [
|
700 |
-
"MIT"
|
701 |
-
],
|
702 |
-
"authors": [
|
703 |
-
{
|
704 |
-
"name": "Márk Sági-Kazár",
|
705 |
-
"email": "mark.sagikazar@gmail.com"
|
706 |
-
}
|
707 |
-
],
|
708 |
-
"description": "Factory interfaces for PSR-7 HTTP Message",
|
709 |
-
"homepage": "http://php-http.org",
|
710 |
-
"keywords": [
|
711 |
-
"factory",
|
712 |
-
"http",
|
713 |
-
"message",
|
714 |
-
"stream",
|
715 |
-
"uri"
|
716 |
-
],
|
717 |
-
"support": {
|
718 |
-
"issues": "https://github.com/php-http/message-factory/issues",
|
719 |
-
"source": "https://github.com/php-http/message-factory/tree/master"
|
720 |
-
},
|
721 |
-
"time": "2015-12-19T14:08:53+00:00"
|
722 |
-
},
|
723 |
-
{
|
724 |
-
"name": "php-http/promise",
|
725 |
-
"version": "1.1.0",
|
726 |
-
"source": {
|
727 |
-
"type": "git",
|
728 |
-
"url": "https://github.com/php-http/promise.git",
|
729 |
-
"reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88"
|
730 |
-
},
|
731 |
-
"dist": {
|
732 |
-
"type": "zip",
|
733 |
-
"url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88",
|
734 |
-
"reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88",
|
735 |
-
"shasum": ""
|
736 |
-
},
|
737 |
-
"require": {
|
738 |
-
"php": "^7.1 || ^8.0"
|
739 |
-
},
|
740 |
-
"require-dev": {
|
741 |
-
"friends-of-phpspec/phpspec-code-coverage": "^4.3.2",
|
742 |
-
"phpspec/phpspec": "^5.1.2 || ^6.2"
|
743 |
-
},
|
744 |
-
"type": "library",
|
745 |
-
"extra": {
|
746 |
-
"branch-alias": {
|
747 |
-
"dev-master": "1.1-dev"
|
748 |
-
}
|
749 |
-
},
|
750 |
-
"autoload": {
|
751 |
-
"psr-4": {
|
752 |
-
"Http\\Promise\\": "src/"
|
753 |
-
}
|
754 |
-
},
|
755 |
-
"notification-url": "https://packagist.org/downloads/",
|
756 |
-
"license": [
|
757 |
-
"MIT"
|
758 |
-
],
|
759 |
-
"authors": [
|
760 |
-
{
|
761 |
-
"name": "Joel Wurtz",
|
762 |
-
"email": "joel.wurtz@gmail.com"
|
763 |
-
},
|
764 |
-
{
|
765 |
-
"name": "Márk Sági-Kazár",
|
766 |
-
"email": "mark.sagikazar@gmail.com"
|
767 |
-
}
|
768 |
-
],
|
769 |
-
"description": "Promise used for asynchronous HTTP requests",
|
770 |
-
"homepage": "http://httplug.io",
|
771 |
-
"keywords": [
|
772 |
-
"promise"
|
773 |
-
],
|
774 |
-
"support": {
|
775 |
-
"issues": "https://github.com/php-http/promise/issues",
|
776 |
-
"source": "https://github.com/php-http/promise/tree/1.1.0"
|
777 |
-
},
|
778 |
-
"time": "2020-07-07T09:29:14+00:00"
|
779 |
-
},
|
780 |
-
{
|
781 |
-
"name": "psr/container",
|
782 |
-
"version": "1.1.2",
|
783 |
-
"source": {
|
784 |
-
"type": "git",
|
785 |
-
"url": "https://github.com/php-fig/container.git",
|
786 |
-
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
|
787 |
-
},
|
788 |
-
"dist": {
|
789 |
-
"type": "zip",
|
790 |
-
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
|
791 |
-
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
|
792 |
-
"shasum": ""
|
793 |
-
},
|
794 |
-
"require": {
|
795 |
-
"php": ">=7.4.0"
|
796 |
-
},
|
797 |
-
"type": "library",
|
798 |
-
"autoload": {
|
799 |
-
"psr-4": {
|
800 |
-
"Psr\\Container\\": "src/"
|
801 |
-
}
|
802 |
-
},
|
803 |
-
"notification-url": "https://packagist.org/downloads/",
|
804 |
-
"license": [
|
805 |
-
"MIT"
|
806 |
-
],
|
807 |
-
"authors": [
|
808 |
-
{
|
809 |
-
"name": "PHP-FIG",
|
810 |
-
"homepage": "https://www.php-fig.org/"
|
811 |
-
}
|
812 |
-
],
|
813 |
-
"description": "Common Container Interface (PHP FIG PSR-11)",
|
814 |
-
"homepage": "https://github.com/php-fig/container",
|
815 |
-
"keywords": [
|
816 |
-
"PSR-11",
|
817 |
-
"container",
|
818 |
-
"container-interface",
|
819 |
-
"container-interop",
|
820 |
-
"psr"
|
821 |
-
],
|
822 |
-
"support": {
|
823 |
-
"issues": "https://github.com/php-fig/container/issues",
|
824 |
-
"source": "https://github.com/php-fig/container/tree/1.1.2"
|
825 |
-
},
|
826 |
-
"time": "2021-11-05T16:50:12+00:00"
|
827 |
-
},
|
828 |
-
{
|
829 |
-
"name": "psr/http-client",
|
830 |
-
"version": "1.0.1",
|
831 |
-
"source": {
|
832 |
-
"type": "git",
|
833 |
-
"url": "https://github.com/php-fig/http-client.git",
|
834 |
-
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
|
835 |
-
},
|
836 |
-
"dist": {
|
837 |
-
"type": "zip",
|
838 |
-
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
|
839 |
-
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
|
840 |
-
"shasum": ""
|
841 |
-
},
|
842 |
-
"require": {
|
843 |
-
"php": "^7.0 || ^8.0",
|
844 |
-
"psr/http-message": "^1.0"
|
845 |
-
},
|
846 |
-
"type": "library",
|
847 |
-
"extra": {
|
848 |
-
"branch-alias": {
|
849 |
-
"dev-master": "1.0.x-dev"
|
850 |
-
}
|
851 |
-
},
|
852 |
-
"autoload": {
|
853 |
-
"psr-4": {
|
854 |
-
"Psr\\Http\\Client\\": "src/"
|
855 |
-
}
|
856 |
-
},
|
857 |
-
"notification-url": "https://packagist.org/downloads/",
|
858 |
-
"license": [
|
859 |
-
"MIT"
|
860 |
-
],
|
861 |
-
"authors": [
|
862 |
-
{
|
863 |
-
"name": "PHP-FIG",
|
864 |
-
"homepage": "http://www.php-fig.org/"
|
865 |
-
}
|
866 |
-
],
|
867 |
-
"description": "Common interface for HTTP clients",
|
868 |
-
"homepage": "https://github.com/php-fig/http-client",
|
869 |
-
"keywords": [
|
870 |
-
"http",
|
871 |
-
"http-client",
|
872 |
-
"psr",
|
873 |
-
"psr-18"
|
874 |
-
],
|
875 |
-
"support": {
|
876 |
-
"source": "https://github.com/php-fig/http-client/tree/master"
|
877 |
-
},
|
878 |
-
"time": "2020-06-29T06:28:15+00:00"
|
879 |
-
},
|
880 |
-
{
|
881 |
-
"name": "psr/http-factory",
|
882 |
-
"version": "1.0.1",
|
883 |
-
"source": {
|
884 |
-
"type": "git",
|
885 |
-
"url": "https://github.com/php-fig/http-factory.git",
|
886 |
-
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
|
887 |
-
},
|
888 |
-
"dist": {
|
889 |
-
"type": "zip",
|
890 |
-
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
891 |
-
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
892 |
-
"shasum": ""
|
893 |
-
},
|
894 |
-
"require": {
|
895 |
-
"php": ">=7.0.0",
|
896 |
-
"psr/http-message": "^1.0"
|
897 |
-
},
|
898 |
-
"type": "library",
|
899 |
-
"extra": {
|
900 |
-
"branch-alias": {
|
901 |
-
"dev-master": "1.0.x-dev"
|
902 |
-
}
|
903 |
-
},
|
904 |
-
"autoload": {
|
905 |
-
"psr-4": {
|
906 |
-
"Psr\\Http\\Message\\": "src/"
|
907 |
-
}
|
908 |
-
},
|
909 |
-
"notification-url": "https://packagist.org/downloads/",
|
910 |
-
"license": [
|
911 |
-
"MIT"
|
912 |
-
],
|
913 |
-
"authors": [
|
914 |
-
{
|
915 |
-
"name": "PHP-FIG",
|
916 |
-
"homepage": "http://www.php-fig.org/"
|
917 |
-
}
|
918 |
-
],
|
919 |
-
"description": "Common interfaces for PSR-7 HTTP message factories",
|
920 |
-
"keywords": [
|
921 |
-
"factory",
|
922 |
-
"http",
|
923 |
-
"message",
|
924 |
-
"psr",
|
925 |
-
"psr-17",
|
926 |
-
"psr-7",
|
927 |
-
"request",
|
928 |
-
"response"
|
929 |
-
],
|
930 |
-
"support": {
|
931 |
-
"source": "https://github.com/php-fig/http-factory/tree/master"
|
932 |
-
},
|
933 |
-
"time": "2019-04-30T12:38:16+00:00"
|
934 |
-
},
|
935 |
-
{
|
936 |
-
"name": "psr/http-message",
|
937 |
-
"version": "1.0.1",
|
938 |
-
"source": {
|
939 |
-
"type": "git",
|
940 |
-
"url": "https://github.com/php-fig/http-message.git",
|
941 |
-
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
942 |
-
},
|
943 |
-
"dist": {
|
944 |
-
"type": "zip",
|
945 |
-
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
946 |
-
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
947 |
-
"shasum": ""
|
948 |
-
},
|
949 |
-
"require": {
|
950 |
-
"php": ">=5.3.0"
|
951 |
-
},
|
952 |
-
"type": "library",
|
953 |
-
"extra": {
|
954 |
-
"branch-alias": {
|
955 |
-
"dev-master": "1.0.x-dev"
|
956 |
-
}
|
957 |
-
},
|
958 |
-
"autoload": {
|
959 |
-
"psr-4": {
|
960 |
-
"Psr\\Http\\Message\\": "src/"
|
961 |
-
}
|
962 |
-
},
|
963 |
-
"notification-url": "https://packagist.org/downloads/",
|
964 |
-
"license": [
|
965 |
-
"MIT"
|
966 |
-
],
|
967 |
-
"authors": [
|
968 |
-
{
|
969 |
-
"name": "PHP-FIG",
|
970 |
-
"homepage": "http://www.php-fig.org/"
|
971 |
-
}
|
972 |
-
],
|
973 |
-
"description": "Common interface for HTTP messages",
|
974 |
-
"homepage": "https://github.com/php-fig/http-message",
|
975 |
-
"keywords": [
|
976 |
-
"http",
|
977 |
-
"http-message",
|
978 |
-
"psr",
|
979 |
-
"psr-7",
|
980 |
-
"request",
|
981 |
-
"response"
|
982 |
-
],
|
983 |
-
"support": {
|
984 |
-
"source": "https://github.com/php-fig/http-message/tree/master"
|
985 |
-
},
|
986 |
-
"time": "2016-08-06T14:39:51+00:00"
|
987 |
-
},
|
988 |
-
{
|
989 |
-
"name": "psr/log",
|
990 |
-
"version": "1.1.4",
|
991 |
-
"source": {
|
992 |
-
"type": "git",
|
993 |
-
"url": "https://github.com/php-fig/log.git",
|
994 |
-
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
|
995 |
-
},
|
996 |
-
"dist": {
|
997 |
-
"type": "zip",
|
998 |
-
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
|
999 |
-
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
|
1000 |
-
"shasum": ""
|
1001 |
-
},
|
1002 |
-
"require": {
|
1003 |
-
"php": ">=5.3.0"
|
1004 |
-
},
|
1005 |
-
"type": "library",
|
1006 |
-
"extra": {
|
1007 |
-
"branch-alias": {
|
1008 |
-
"dev-master": "1.1.x-dev"
|
1009 |
-
}
|
1010 |
-
},
|
1011 |
-
"autoload": {
|
1012 |
-
"psr-4": {
|
1013 |
-
"Psr\\Log\\": "Psr/Log/"
|
1014 |
-
}
|
1015 |
-
},
|
1016 |
-
"notification-url": "https://packagist.org/downloads/",
|
1017 |
-
"license": [
|
1018 |
-
"MIT"
|
1019 |
-
],
|
1020 |
-
"authors": [
|
1021 |
-
{
|
1022 |
-
"name": "PHP-FIG",
|
1023 |
-
"homepage": "https://www.php-fig.org/"
|
1024 |
-
}
|
1025 |
-
],
|
1026 |
-
"description": "Common interface for logging libraries",
|
1027 |
-
"homepage": "https://github.com/php-fig/log",
|
1028 |
-
"keywords": [
|
1029 |
-
"log",
|
1030 |
-
"psr",
|
1031 |
-
"psr-3"
|
1032 |
-
],
|
1033 |
-
"support": {
|
1034 |
-
"source": "https://github.com/php-fig/log/tree/1.1.4"
|
1035 |
-
},
|
1036 |
-
"time": "2021-05-03T11:20:27+00:00"
|
1037 |
-
},
|
1038 |
-
{
|
1039 |
-
"name": "ralouphie/getallheaders",
|
1040 |
-
"version": "3.0.3",
|
1041 |
-
"source": {
|
1042 |
-
"type": "git",
|
1043 |
-
"url": "https://github.com/ralouphie/getallheaders.git",
|
1044 |
-
"reference": "120b605dfeb996808c31b6477290a714d356e822"
|
1045 |
-
},
|
1046 |
-
"dist": {
|
1047 |
-
"type": "zip",
|
1048 |
-
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
|
1049 |
-
"reference": "120b605dfeb996808c31b6477290a714d356e822",
|
1050 |
-
"shasum": ""
|
1051 |
-
},
|
1052 |
-
"require": {
|
1053 |
-
"php": ">=5.6"
|
1054 |
-
},
|
1055 |
-
"require-dev": {
|
1056 |
-
"php-coveralls/php-coveralls": "^2.1",
|
1057 |
-
"phpunit/phpunit": "^5 || ^6.5"
|
1058 |
-
},
|
1059 |
-
"type": "library",
|
1060 |
-
"autoload": {
|
1061 |
-
"files": [
|
1062 |
-
"src/getallheaders.php"
|
1063 |
-
]
|
1064 |
-
},
|
1065 |
-
"notification-url": "https://packagist.org/downloads/",
|
1066 |
-
"license": [
|
1067 |
-
"MIT"
|
1068 |
-
],
|
1069 |
-
"authors": [
|
1070 |
-
{
|
1071 |
-
"name": "Ralph Khattar",
|
1072 |
-
"email": "ralph.khattar@gmail.com"
|
1073 |
-
}
|
1074 |
-
],
|
1075 |
-
"description": "A polyfill for getallheaders.",
|
1076 |
-
"support": {
|
1077 |
-
"issues": "https://github.com/ralouphie/getallheaders/issues",
|
1078 |
-
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
|
1079 |
-
},
|
1080 |
-
"time": "2019-03-08T08:55:37+00:00"
|
1081 |
-
},
|
1082 |
-
{
|
1083 |
-
"name": "sentry/sdk",
|
1084 |
-
"version": "3.2.0",
|
1085 |
-
"source": {
|
1086 |
-
"type": "git",
|
1087 |
-
"url": "https://github.com/getsentry/sentry-php-sdk.git",
|
1088 |
-
"reference": "6d78bd83b43efbb52f81d6824f4af344fa9ba292"
|
1089 |
-
},
|
1090 |
-
"dist": {
|
1091 |
-
"type": "zip",
|
1092 |
-
"url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/6d78bd83b43efbb52f81d6824f4af344fa9ba292",
|
1093 |
-
"reference": "6d78bd83b43efbb52f81d6824f4af344fa9ba292",
|
1094 |
-
"shasum": ""
|
1095 |
-
},
|
1096 |
-
"require": {
|
1097 |
-
"http-interop/http-factory-guzzle": "^1.0",
|
1098 |
-
"sentry/sentry": "^3.5",
|
1099 |
-
"symfony/http-client": "^4.3|^5.0|^6.0"
|
1100 |
-
},
|
1101 |
-
"type": "metapackage",
|
1102 |
-
"notification-url": "https://packagist.org/downloads/",
|
1103 |
-
"license": [
|
1104 |
-
"MIT"
|
1105 |
-
],
|
1106 |
-
"authors": [
|
1107 |
-
{
|
1108 |
-
"name": "Sentry",
|
1109 |
-
"email": "accounts@sentry.io"
|
1110 |
-
}
|
1111 |
-
],
|
1112 |
-
"description": "This is a metapackage shipping sentry/sentry with a recommended HTTP client.",
|
1113 |
-
"homepage": "http://sentry.io",
|
1114 |
-
"keywords": [
|
1115 |
-
"crash-reporting",
|
1116 |
-
"crash-reports",
|
1117 |
-
"error-handler",
|
1118 |
-
"error-monitoring",
|
1119 |
-
"log",
|
1120 |
-
"logging",
|
1121 |
-
"sentry"
|
1122 |
-
],
|
1123 |
-
"support": {
|
1124 |
-
"issues": "https://github.com/getsentry/sentry-php-sdk/issues",
|
1125 |
-
"source": "https://github.com/getsentry/sentry-php-sdk/tree/3.2.0"
|
1126 |
-
},
|
1127 |
-
"funding": [
|
1128 |
-
{
|
1129 |
-
"url": "https://sentry.io/",
|
1130 |
-
"type": "custom"
|
1131 |
-
},
|
1132 |
-
{
|
1133 |
-
"url": "https://sentry.io/pricing/",
|
1134 |
-
"type": "custom"
|
1135 |
-
}
|
1136 |
-
],
|
1137 |
-
"time": "2022-05-21T11:10:11+00:00"
|
1138 |
-
},
|
1139 |
-
{
|
1140 |
-
"name": "sentry/sentry",
|
1141 |
-
"version": "3.6.0",
|
1142 |
-
"source": {
|
1143 |
-
"type": "git",
|
1144 |
-
"url": "https://github.com/getsentry/sentry-php.git",
|
1145 |
-
"reference": "6d1a6ee29c558be373bfe08d454a3c116c02dd0d"
|
1146 |
-
},
|
1147 |
-
"dist": {
|
1148 |
-
"type": "zip",
|
1149 |
-
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/6d1a6ee29c558be373bfe08d454a3c116c02dd0d",
|
1150 |
-
"reference": "6d1a6ee29c558be373bfe08d454a3c116c02dd0d",
|
1151 |
-
"shasum": ""
|
1152 |
-
},
|
1153 |
-
"require": {
|
1154 |
-
"ext-json": "*",
|
1155 |
-
"ext-mbstring": "*",
|
1156 |
-
"guzzlehttp/promises": "^1.4",
|
1157 |
-
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
|
1158 |
-
"jean85/pretty-package-versions": "^1.5|^2.0.4",
|
1159 |
-
"php": "^7.2|^8.0",
|
1160 |
-
"php-http/async-client-implementation": "^1.0",
|
1161 |
-
"php-http/client-common": "^1.5|^2.0",
|
1162 |
-
"php-http/discovery": "^1.11",
|
1163 |
-
"php-http/httplug": "^1.1|^2.0",
|
1164 |
-
"php-http/message": "^1.5",
|
1165 |
-
"psr/http-factory": "^1.0",
|
1166 |
-
"psr/http-message-implementation": "^1.0",
|
1167 |
-
"psr/log": "^1.0|^2.0|^3.0",
|
1168 |
-
"symfony/options-resolver": "^3.4.43|^4.4.30|^5.0.11|^6.0",
|
1169 |
-
"symfony/polyfill-php80": "^1.17",
|
1170 |
-
"symfony/polyfill-uuid": "^1.13.1"
|
1171 |
-
},
|
1172 |
-
"conflict": {
|
1173 |
-
"php-http/client-common": "1.8.0",
|
1174 |
-
"raven/raven": "*"
|
1175 |
-
},
|
1176 |
-
"require-dev": {
|
1177 |
-
"friendsofphp/php-cs-fixer": "^2.19|3.4.*",
|
1178 |
-
"http-interop/http-factory-guzzle": "^1.0",
|
1179 |
-
"monolog/monolog": "^1.6|^2.0|^3.0",
|
1180 |
-
"nikic/php-parser": "^4.10.3",
|
1181 |
-
"php-http/mock-client": "^1.3",
|
1182 |
-
"phpbench/phpbench": "^1.0",
|
1183 |
-
"phpstan/extension-installer": "^1.0",
|
1184 |
-
"phpstan/phpstan": "^1.3",
|
1185 |
-
"phpstan/phpstan-phpunit": "^1.0",
|
1186 |
-
"phpunit/phpunit": "^8.5.14|^9.4",
|
1187 |
-
"symfony/phpunit-bridge": "^5.2|^6.0",
|
1188 |
-
"vimeo/psalm": "^4.17"
|
1189 |
-
},
|
1190 |
-
"suggest": {
|
1191 |
-
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
|
1192 |
-
},
|
1193 |
-
"type": "library",
|
1194 |
-
"extra": {
|
1195 |
-
"branch-alias": {
|
1196 |
-
"dev-master": "3.6.x-dev"
|
1197 |
-
}
|
1198 |
-
},
|
1199 |
-
"autoload": {
|
1200 |
-
"files": [
|
1201 |
-
"src/functions.php"
|
1202 |
-
],
|
1203 |
-
"psr-4": {
|
1204 |
-
"Sentry\\": "src/"
|
1205 |
-
}
|
1206 |
-
},
|
1207 |
-
"notification-url": "https://packagist.org/downloads/",
|
1208 |
-
"license": [
|
1209 |
-
"BSD-3-Clause"
|
1210 |
-
],
|
1211 |
-
"authors": [
|
1212 |
-
{
|
1213 |
-
"name": "Sentry",
|
1214 |
-
"email": "accounts@sentry.io"
|
1215 |
-
}
|
1216 |
-
],
|
1217 |
-
"description": "A PHP SDK for Sentry (http://sentry.io)",
|
1218 |
-
"homepage": "http://sentry.io",
|
1219 |
-
"keywords": [
|
1220 |
-
"crash-reporting",
|
1221 |
-
"crash-reports",
|
1222 |
-
"error-handler",
|
1223 |
-
"error-monitoring",
|
1224 |
-
"log",
|
1225 |
-
"logging",
|
1226 |
-
"sentry"
|
1227 |
-
],
|
1228 |
-
"support": {
|
1229 |
-
"issues": "https://github.com/getsentry/sentry-php/issues",
|
1230 |
-
"source": "https://github.com/getsentry/sentry-php/tree/3.6.0"
|
1231 |
-
},
|
1232 |
-
"funding": [
|
1233 |
-
{
|
1234 |
-
"url": "https://sentry.io/",
|
1235 |
-
"type": "custom"
|
1236 |
-
},
|
1237 |
-
{
|
1238 |
-
"url": "https://sentry.io/pricing/",
|
1239 |
-
"type": "custom"
|
1240 |
-
}
|
1241 |
-
],
|
1242 |
-
"time": "2022-06-09T20:33:39+00:00"
|
1243 |
-
},
|
1244 |
-
{
|
1245 |
-
"name": "symfony/deprecation-contracts",
|
1246 |
-
"version": "v2.5.1",
|
1247 |
-
"source": {
|
1248 |
-
"type": "git",
|
1249 |
-
"url": "https://github.com/symfony/deprecation-contracts.git",
|
1250 |
-
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
|
1251 |
-
},
|
1252 |
-
"dist": {
|
1253 |
-
"type": "zip",
|
1254 |
-
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
|
1255 |
-
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
|
1256 |
-
"shasum": ""
|
1257 |
-
},
|
1258 |
-
"require": {
|
1259 |
-
"php": ">=7.1"
|
1260 |
-
},
|
1261 |
-
"type": "library",
|
1262 |
-
"extra": {
|
1263 |
-
"branch-alias": {
|
1264 |
-
"dev-main": "2.5-dev"
|
1265 |
-
},
|
1266 |
-
"thanks": {
|
1267 |
-
"name": "symfony/contracts",
|
1268 |
-
"url": "https://github.com/symfony/contracts"
|
1269 |
-
}
|
1270 |
-
},
|
1271 |
-
"autoload": {
|
1272 |
-
"files": [
|
1273 |
-
"function.php"
|
1274 |
-
]
|
1275 |
-
},
|
1276 |
-
"notification-url": "https://packagist.org/downloads/",
|
1277 |
-
"license": [
|
1278 |
-
"MIT"
|
1279 |
-
],
|
1280 |
-
"authors": [
|
1281 |
-
{
|
1282 |
-
"name": "Nicolas Grekas",
|
1283 |
-
"email": "p@tchwork.com"
|
1284 |
-
},
|
1285 |
-
{
|
1286 |
-
"name": "Symfony Community",
|
1287 |
-
"homepage": "https://symfony.com/contributors"
|
1288 |
-
}
|
1289 |
-
],
|
1290 |
-
"description": "A generic function and convention to trigger deprecation notices",
|
1291 |
-
"homepage": "https://symfony.com",
|
1292 |
-
"support": {
|
1293 |
-
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1"
|
1294 |
-
},
|
1295 |
-
"funding": [
|
1296 |
-
{
|
1297 |
-
"url": "https://symfony.com/sponsor",
|
1298 |
-
"type": "custom"
|
1299 |
-
},
|
1300 |
-
{
|
1301 |
-
"url": "https://github.com/fabpot",
|
1302 |
-
"type": "github"
|
1303 |
-
},
|
1304 |
-
{
|
1305 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1306 |
-
"type": "tidelift"
|
1307 |
-
}
|
1308 |
-
],
|
1309 |
-
"time": "2022-01-02T09:53:40+00:00"
|
1310 |
-
},
|
1311 |
-
{
|
1312 |
-
"name": "symfony/http-client",
|
1313 |
-
"version": "v5.4.9",
|
1314 |
-
"source": {
|
1315 |
-
"type": "git",
|
1316 |
-
"url": "https://github.com/symfony/http-client.git",
|
1317 |
-
"reference": "dc0b15e42b762c040761c1eb9ce86a55d47cf672"
|
1318 |
-
},
|
1319 |
-
"dist": {
|
1320 |
-
"type": "zip",
|
1321 |
-
"url": "https://api.github.com/repos/symfony/http-client/zipball/dc0b15e42b762c040761c1eb9ce86a55d47cf672",
|
1322 |
-
"reference": "dc0b15e42b762c040761c1eb9ce86a55d47cf672",
|
1323 |
-
"shasum": ""
|
1324 |
-
},
|
1325 |
-
"require": {
|
1326 |
-
"php": ">=7.2.5",
|
1327 |
-
"psr/log": "^1|^2|^3",
|
1328 |
-
"symfony/deprecation-contracts": "^2.1|^3",
|
1329 |
-
"symfony/http-client-contracts": "^2.4",
|
1330 |
-
"symfony/polyfill-php73": "^1.11",
|
1331 |
-
"symfony/polyfill-php80": "^1.16",
|
1332 |
-
"symfony/service-contracts": "^1.0|^2|^3"
|
1333 |
-
},
|
1334 |
-
"provide": {
|
1335 |
-
"php-http/async-client-implementation": "*",
|
1336 |
-
"php-http/client-implementation": "*",
|
1337 |
-
"psr/http-client-implementation": "1.0",
|
1338 |
-
"symfony/http-client-implementation": "2.4"
|
1339 |
-
},
|
1340 |
-
"require-dev": {
|
1341 |
-
"amphp/amp": "^2.5",
|
1342 |
-
"amphp/http-client": "^4.2.1",
|
1343 |
-
"amphp/http-tunnel": "^1.0",
|
1344 |
-
"amphp/socket": "^1.1",
|
1345 |
-
"guzzlehttp/promises": "^1.4",
|
1346 |
-
"nyholm/psr7": "^1.0",
|
1347 |
-
"php-http/httplug": "^1.0|^2.0",
|
1348 |
-
"psr/http-client": "^1.0",
|
1349 |
-
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
|
1350 |
-
"symfony/http-kernel": "^4.4.13|^5.1.5|^6.0",
|
1351 |
-
"symfony/process": "^4.4|^5.0|^6.0",
|
1352 |
-
"symfony/stopwatch": "^4.4|^5.0|^6.0"
|
1353 |
-
},
|
1354 |
-
"type": "library",
|
1355 |
-
"autoload": {
|
1356 |
-
"psr-4": {
|
1357 |
-
"Symfony\\Component\\HttpClient\\": ""
|
1358 |
-
},
|
1359 |
-
"exclude-from-classmap": [
|
1360 |
-
"/Tests/"
|
1361 |
-
]
|
1362 |
-
},
|
1363 |
-
"notification-url": "https://packagist.org/downloads/",
|
1364 |
-
"license": [
|
1365 |
-
"MIT"
|
1366 |
-
],
|
1367 |
-
"authors": [
|
1368 |
-
{
|
1369 |
-
"name": "Nicolas Grekas",
|
1370 |
-
"email": "p@tchwork.com"
|
1371 |
-
},
|
1372 |
-
{
|
1373 |
-
"name": "Symfony Community",
|
1374 |
-
"homepage": "https://symfony.com/contributors"
|
1375 |
-
}
|
1376 |
-
],
|
1377 |
-
"description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
|
1378 |
-
"homepage": "https://symfony.com",
|
1379 |
-
"support": {
|
1380 |
-
"source": "https://github.com/symfony/http-client/tree/v5.4.9"
|
1381 |
-
},
|
1382 |
-
"funding": [
|
1383 |
-
{
|
1384 |
-
"url": "https://symfony.com/sponsor",
|
1385 |
-
"type": "custom"
|
1386 |
-
},
|
1387 |
-
{
|
1388 |
-
"url": "https://github.com/fabpot",
|
1389 |
-
"type": "github"
|
1390 |
-
},
|
1391 |
-
{
|
1392 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1393 |
-
"type": "tidelift"
|
1394 |
-
}
|
1395 |
-
],
|
1396 |
-
"time": "2022-05-21T08:57:05+00:00"
|
1397 |
-
},
|
1398 |
-
{
|
1399 |
-
"name": "symfony/http-client-contracts",
|
1400 |
-
"version": "v2.5.1",
|
1401 |
-
"source": {
|
1402 |
-
"type": "git",
|
1403 |
-
"url": "https://github.com/symfony/http-client-contracts.git",
|
1404 |
-
"reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5"
|
1405 |
-
},
|
1406 |
-
"dist": {
|
1407 |
-
"type": "zip",
|
1408 |
-
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1a4f708e4e87f335d1b1be6148060739152f0bd5",
|
1409 |
-
"reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5",
|
1410 |
-
"shasum": ""
|
1411 |
-
},
|
1412 |
-
"require": {
|
1413 |
-
"php": ">=7.2.5"
|
1414 |
-
},
|
1415 |
-
"suggest": {
|
1416 |
-
"symfony/http-client-implementation": ""
|
1417 |
-
},
|
1418 |
-
"type": "library",
|
1419 |
-
"extra": {
|
1420 |
-
"branch-alias": {
|
1421 |
-
"dev-main": "2.5-dev"
|
1422 |
-
},
|
1423 |
-
"thanks": {
|
1424 |
-
"name": "symfony/contracts",
|
1425 |
-
"url": "https://github.com/symfony/contracts"
|
1426 |
-
}
|
1427 |
-
},
|
1428 |
-
"autoload": {
|
1429 |
-
"psr-4": {
|
1430 |
-
"Symfony\\Contracts\\HttpClient\\": ""
|
1431 |
-
}
|
1432 |
-
},
|
1433 |
-
"notification-url": "https://packagist.org/downloads/",
|
1434 |
-
"license": [
|
1435 |
-
"MIT"
|
1436 |
-
],
|
1437 |
-
"authors": [
|
1438 |
-
{
|
1439 |
-
"name": "Nicolas Grekas",
|
1440 |
-
"email": "p@tchwork.com"
|
1441 |
-
},
|
1442 |
-
{
|
1443 |
-
"name": "Symfony Community",
|
1444 |
-
"homepage": "https://symfony.com/contributors"
|
1445 |
-
}
|
1446 |
-
],
|
1447 |
-
"description": "Generic abstractions related to HTTP clients",
|
1448 |
-
"homepage": "https://symfony.com",
|
1449 |
-
"keywords": [
|
1450 |
-
"abstractions",
|
1451 |
-
"contracts",
|
1452 |
-
"decoupling",
|
1453 |
-
"interfaces",
|
1454 |
-
"interoperability",
|
1455 |
-
"standards"
|
1456 |
-
],
|
1457 |
-
"support": {
|
1458 |
-
"source": "https://github.com/symfony/http-client-contracts/tree/v2.5.1"
|
1459 |
-
},
|
1460 |
-
"funding": [
|
1461 |
-
{
|
1462 |
-
"url": "https://symfony.com/sponsor",
|
1463 |
-
"type": "custom"
|
1464 |
-
},
|
1465 |
-
{
|
1466 |
-
"url": "https://github.com/fabpot",
|
1467 |
-
"type": "github"
|
1468 |
-
},
|
1469 |
-
{
|
1470 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1471 |
-
"type": "tidelift"
|
1472 |
-
}
|
1473 |
-
],
|
1474 |
-
"time": "2022-03-13T20:07:29+00:00"
|
1475 |
-
},
|
1476 |
-
{
|
1477 |
-
"name": "symfony/options-resolver",
|
1478 |
-
"version": "v5.4.3",
|
1479 |
-
"source": {
|
1480 |
-
"type": "git",
|
1481 |
-
"url": "https://github.com/symfony/options-resolver.git",
|
1482 |
-
"reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8"
|
1483 |
-
},
|
1484 |
-
"dist": {
|
1485 |
-
"type": "zip",
|
1486 |
-
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/cc1147cb11af1b43f503ac18f31aa3bec213aba8",
|
1487 |
-
"reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8",
|
1488 |
-
"shasum": ""
|
1489 |
-
},
|
1490 |
-
"require": {
|
1491 |
-
"php": ">=7.2.5",
|
1492 |
-
"symfony/deprecation-contracts": "^2.1|^3",
|
1493 |
-
"symfony/polyfill-php73": "~1.0",
|
1494 |
-
"symfony/polyfill-php80": "^1.16"
|
1495 |
-
},
|
1496 |
-
"type": "library",
|
1497 |
-
"autoload": {
|
1498 |
-
"psr-4": {
|
1499 |
-
"Symfony\\Component\\OptionsResolver\\": ""
|
1500 |
-
},
|
1501 |
-
"exclude-from-classmap": [
|
1502 |
-
"/Tests/"
|
1503 |
-
]
|
1504 |
-
},
|
1505 |
-
"notification-url": "https://packagist.org/downloads/",
|
1506 |
-
"license": [
|
1507 |
-
"MIT"
|
1508 |
-
],
|
1509 |
-
"authors": [
|
1510 |
-
{
|
1511 |
-
"name": "Fabien Potencier",
|
1512 |
-
"email": "fabien@symfony.com"
|
1513 |
-
},
|
1514 |
-
{
|
1515 |
-
"name": "Symfony Community",
|
1516 |
-
"homepage": "https://symfony.com/contributors"
|
1517 |
-
}
|
1518 |
-
],
|
1519 |
-
"description": "Provides an improved replacement for the array_replace PHP function",
|
1520 |
-
"homepage": "https://symfony.com",
|
1521 |
-
"keywords": [
|
1522 |
-
"config",
|
1523 |
-
"configuration",
|
1524 |
-
"options"
|
1525 |
-
],
|
1526 |
-
"support": {
|
1527 |
-
"source": "https://github.com/symfony/options-resolver/tree/v5.4.3"
|
1528 |
-
},
|
1529 |
-
"funding": [
|
1530 |
-
{
|
1531 |
-
"url": "https://symfony.com/sponsor",
|
1532 |
-
"type": "custom"
|
1533 |
-
},
|
1534 |
-
{
|
1535 |
-
"url": "https://github.com/fabpot",
|
1536 |
-
"type": "github"
|
1537 |
-
},
|
1538 |
-
{
|
1539 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1540 |
-
"type": "tidelift"
|
1541 |
-
}
|
1542 |
-
],
|
1543 |
-
"time": "2022-01-02T09:53:40+00:00"
|
1544 |
-
},
|
1545 |
-
{
|
1546 |
-
"name": "symfony/polyfill-php73",
|
1547 |
-
"version": "v1.26.0",
|
1548 |
-
"source": {
|
1549 |
-
"type": "git",
|
1550 |
-
"url": "https://github.com/symfony/polyfill-php73.git",
|
1551 |
-
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
|
1552 |
-
},
|
1553 |
-
"dist": {
|
1554 |
-
"type": "zip",
|
1555 |
-
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
|
1556 |
-
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
|
1557 |
-
"shasum": ""
|
1558 |
-
},
|
1559 |
-
"require": {
|
1560 |
-
"php": ">=7.1"
|
1561 |
-
},
|
1562 |
-
"type": "library",
|
1563 |
-
"extra": {
|
1564 |
-
"branch-alias": {
|
1565 |
-
"dev-main": "1.26-dev"
|
1566 |
-
},
|
1567 |
-
"thanks": {
|
1568 |
-
"name": "symfony/polyfill",
|
1569 |
-
"url": "https://github.com/symfony/polyfill"
|
1570 |
-
}
|
1571 |
-
},
|
1572 |
-
"autoload": {
|
1573 |
-
"files": [
|
1574 |
-
"bootstrap.php"
|
1575 |
-
],
|
1576 |
-
"psr-4": {
|
1577 |
-
"Symfony\\Polyfill\\Php73\\": ""
|
1578 |
-
},
|
1579 |
-
"classmap": [
|
1580 |
-
"Resources/stubs"
|
1581 |
-
]
|
1582 |
-
},
|
1583 |
-
"notification-url": "https://packagist.org/downloads/",
|
1584 |
-
"license": [
|
1585 |
-
"MIT"
|
1586 |
-
],
|
1587 |
-
"authors": [
|
1588 |
-
{
|
1589 |
-
"name": "Nicolas Grekas",
|
1590 |
-
"email": "p@tchwork.com"
|
1591 |
-
},
|
1592 |
-
{
|
1593 |
-
"name": "Symfony Community",
|
1594 |
-
"homepage": "https://symfony.com/contributors"
|
1595 |
-
}
|
1596 |
-
],
|
1597 |
-
"description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
|
1598 |
-
"homepage": "https://symfony.com",
|
1599 |
-
"keywords": [
|
1600 |
-
"compatibility",
|
1601 |
-
"polyfill",
|
1602 |
-
"portable",
|
1603 |
-
"shim"
|
1604 |
-
],
|
1605 |
-
"support": {
|
1606 |
-
"source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
|
1607 |
-
},
|
1608 |
-
"funding": [
|
1609 |
-
{
|
1610 |
-
"url": "https://symfony.com/sponsor",
|
1611 |
-
"type": "custom"
|
1612 |
-
},
|
1613 |
-
{
|
1614 |
-
"url": "https://github.com/fabpot",
|
1615 |
-
"type": "github"
|
1616 |
-
},
|
1617 |
-
{
|
1618 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1619 |
-
"type": "tidelift"
|
1620 |
-
}
|
1621 |
-
],
|
1622 |
-
"time": "2022-05-24T11:49:31+00:00"
|
1623 |
-
},
|
1624 |
-
{
|
1625 |
-
"name": "symfony/polyfill-php80",
|
1626 |
-
"version": "v1.26.0",
|
1627 |
-
"source": {
|
1628 |
-
"type": "git",
|
1629 |
-
"url": "https://github.com/symfony/polyfill-php80.git",
|
1630 |
-
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
1631 |
-
},
|
1632 |
-
"dist": {
|
1633 |
-
"type": "zip",
|
1634 |
-
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
1635 |
-
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
1636 |
-
"shasum": ""
|
1637 |
-
},
|
1638 |
-
"require": {
|
1639 |
-
"php": ">=7.1"
|
1640 |
-
},
|
1641 |
-
"type": "library",
|
1642 |
-
"extra": {
|
1643 |
-
"branch-alias": {
|
1644 |
-
"dev-main": "1.26-dev"
|
1645 |
-
},
|
1646 |
-
"thanks": {
|
1647 |
-
"name": "symfony/polyfill",
|
1648 |
-
"url": "https://github.com/symfony/polyfill"
|
1649 |
-
}
|
1650 |
-
},
|
1651 |
-
"autoload": {
|
1652 |
-
"files": [
|
1653 |
-
"bootstrap.php"
|
1654 |
-
],
|
1655 |
-
"psr-4": {
|
1656 |
-
"Symfony\\Polyfill\\Php80\\": ""
|
1657 |
-
},
|
1658 |
-
"classmap": [
|
1659 |
-
"Resources/stubs"
|
1660 |
-
]
|
1661 |
-
},
|
1662 |
-
"notification-url": "https://packagist.org/downloads/",
|
1663 |
-
"license": [
|
1664 |
-
"MIT"
|
1665 |
-
],
|
1666 |
-
"authors": [
|
1667 |
-
{
|
1668 |
-
"name": "Ion Bazan",
|
1669 |
-
"email": "ion.bazan@gmail.com"
|
1670 |
-
},
|
1671 |
-
{
|
1672 |
-
"name": "Nicolas Grekas",
|
1673 |
-
"email": "p@tchwork.com"
|
1674 |
-
},
|
1675 |
-
{
|
1676 |
-
"name": "Symfony Community",
|
1677 |
-
"homepage": "https://symfony.com/contributors"
|
1678 |
-
}
|
1679 |
-
],
|
1680 |
-
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
1681 |
-
"homepage": "https://symfony.com",
|
1682 |
-
"keywords": [
|
1683 |
-
"compatibility",
|
1684 |
-
"polyfill",
|
1685 |
-
"portable",
|
1686 |
-
"shim"
|
1687 |
-
],
|
1688 |
-
"support": {
|
1689 |
-
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
1690 |
-
},
|
1691 |
-
"funding": [
|
1692 |
-
{
|
1693 |
-
"url": "https://symfony.com/sponsor",
|
1694 |
-
"type": "custom"
|
1695 |
-
},
|
1696 |
-
{
|
1697 |
-
"url": "https://github.com/fabpot",
|
1698 |
-
"type": "github"
|
1699 |
-
},
|
1700 |
-
{
|
1701 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1702 |
-
"type": "tidelift"
|
1703 |
-
}
|
1704 |
-
],
|
1705 |
-
"time": "2022-05-10T07:21:04+00:00"
|
1706 |
-
},
|
1707 |
-
{
|
1708 |
-
"name": "symfony/polyfill-uuid",
|
1709 |
-
"version": "v1.26.0",
|
1710 |
-
"source": {
|
1711 |
-
"type": "git",
|
1712 |
-
"url": "https://github.com/symfony/polyfill-uuid.git",
|
1713 |
-
"reference": "a41886c1c81dc075a09c71fe6db5b9d68c79de23"
|
1714 |
-
},
|
1715 |
-
"dist": {
|
1716 |
-
"type": "zip",
|
1717 |
-
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/a41886c1c81dc075a09c71fe6db5b9d68c79de23",
|
1718 |
-
"reference": "a41886c1c81dc075a09c71fe6db5b9d68c79de23",
|
1719 |
-
"shasum": ""
|
1720 |
-
},
|
1721 |
-
"require": {
|
1722 |
-
"php": ">=7.1"
|
1723 |
-
},
|
1724 |
-
"provide": {
|
1725 |
-
"ext-uuid": "*"
|
1726 |
-
},
|
1727 |
-
"suggest": {
|
1728 |
-
"ext-uuid": "For best performance"
|
1729 |
-
},
|
1730 |
-
"type": "library",
|
1731 |
-
"extra": {
|
1732 |
-
"branch-alias": {
|
1733 |
-
"dev-main": "1.26-dev"
|
1734 |
-
},
|
1735 |
-
"thanks": {
|
1736 |
-
"name": "symfony/polyfill",
|
1737 |
-
"url": "https://github.com/symfony/polyfill"
|
1738 |
-
}
|
1739 |
-
},
|
1740 |
-
"autoload": {
|
1741 |
-
"files": [
|
1742 |
-
"bootstrap.php"
|
1743 |
-
],
|
1744 |
-
"psr-4": {
|
1745 |
-
"Symfony\\Polyfill\\Uuid\\": ""
|
1746 |
-
}
|
1747 |
-
},
|
1748 |
-
"notification-url": "https://packagist.org/downloads/",
|
1749 |
-
"license": [
|
1750 |
-
"MIT"
|
1751 |
-
],
|
1752 |
-
"authors": [
|
1753 |
-
{
|
1754 |
-
"name": "Grégoire Pineau",
|
1755 |
-
"email": "lyrixx@lyrixx.info"
|
1756 |
-
},
|
1757 |
-
{
|
1758 |
-
"name": "Symfony Community",
|
1759 |
-
"homepage": "https://symfony.com/contributors"
|
1760 |
-
}
|
1761 |
-
],
|
1762 |
-
"description": "Symfony polyfill for uuid functions",
|
1763 |
-
"homepage": "https://symfony.com",
|
1764 |
-
"keywords": [
|
1765 |
-
"compatibility",
|
1766 |
-
"polyfill",
|
1767 |
-
"portable",
|
1768 |
-
"uuid"
|
1769 |
-
],
|
1770 |
-
"support": {
|
1771 |
-
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.26.0"
|
1772 |
-
},
|
1773 |
-
"funding": [
|
1774 |
-
{
|
1775 |
-
"url": "https://symfony.com/sponsor",
|
1776 |
-
"type": "custom"
|
1777 |
-
},
|
1778 |
-
{
|
1779 |
-
"url": "https://github.com/fabpot",
|
1780 |
-
"type": "github"
|
1781 |
-
},
|
1782 |
-
{
|
1783 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1784 |
-
"type": "tidelift"
|
1785 |
-
}
|
1786 |
-
],
|
1787 |
-
"time": "2022-05-24T11:49:31+00:00"
|
1788 |
-
},
|
1789 |
-
{
|
1790 |
-
"name": "symfony/service-contracts",
|
1791 |
-
"version": "v2.5.1",
|
1792 |
-
"source": {
|
1793 |
-
"type": "git",
|
1794 |
-
"url": "https://github.com/symfony/service-contracts.git",
|
1795 |
-
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
|
1796 |
-
},
|
1797 |
-
"dist": {
|
1798 |
-
"type": "zip",
|
1799 |
-
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
|
1800 |
-
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
|
1801 |
-
"shasum": ""
|
1802 |
-
},
|
1803 |
-
"require": {
|
1804 |
-
"php": ">=7.2.5",
|
1805 |
-
"psr/container": "^1.1",
|
1806 |
-
"symfony/deprecation-contracts": "^2.1|^3"
|
1807 |
-
},
|
1808 |
-
"conflict": {
|
1809 |
-
"ext-psr": "<1.1|>=2"
|
1810 |
-
},
|
1811 |
-
"suggest": {
|
1812 |
-
"symfony/service-implementation": ""
|
1813 |
-
},
|
1814 |
-
"type": "library",
|
1815 |
-
"extra": {
|
1816 |
-
"branch-alias": {
|
1817 |
-
"dev-main": "2.5-dev"
|
1818 |
-
},
|
1819 |
-
"thanks": {
|
1820 |
-
"name": "symfony/contracts",
|
1821 |
-
"url": "https://github.com/symfony/contracts"
|
1822 |
-
}
|
1823 |
-
},
|
1824 |
-
"autoload": {
|
1825 |
-
"psr-4": {
|
1826 |
-
"Symfony\\Contracts\\Service\\": ""
|
1827 |
-
}
|
1828 |
-
},
|
1829 |
-
"notification-url": "https://packagist.org/downloads/",
|
1830 |
-
"license": [
|
1831 |
-
"MIT"
|
1832 |
-
],
|
1833 |
-
"authors": [
|
1834 |
-
{
|
1835 |
-
"name": "Nicolas Grekas",
|
1836 |
-
"email": "p@tchwork.com"
|
1837 |
-
},
|
1838 |
-
{
|
1839 |
-
"name": "Symfony Community",
|
1840 |
-
"homepage": "https://symfony.com/contributors"
|
1841 |
-
}
|
1842 |
-
],
|
1843 |
-
"description": "Generic abstractions related to writing services",
|
1844 |
-
"homepage": "https://symfony.com",
|
1845 |
-
"keywords": [
|
1846 |
-
"abstractions",
|
1847 |
-
"contracts",
|
1848 |
-
"decoupling",
|
1849 |
-
"interfaces",
|
1850 |
-
"interoperability",
|
1851 |
-
"standards"
|
1852 |
-
],
|
1853 |
-
"support": {
|
1854 |
-
"source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
|
1855 |
-
},
|
1856 |
-
"funding": [
|
1857 |
-
{
|
1858 |
-
"url": "https://symfony.com/sponsor",
|
1859 |
-
"type": "custom"
|
1860 |
-
},
|
1861 |
-
{
|
1862 |
-
"url": "https://github.com/fabpot",
|
1863 |
-
"type": "github"
|
1864 |
-
},
|
1865 |
-
{
|
1866 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1867 |
-
"type": "tidelift"
|
1868 |
-
}
|
1869 |
-
],
|
1870 |
-
"time": "2022-03-13T20:07:29+00:00"
|
1871 |
-
}
|
1872 |
-
],
|
1873 |
-
"packages-dev": [],
|
1874 |
-
"aliases": [],
|
1875 |
-
"minimum-stability": "stable",
|
1876 |
-
"stability-flags": [],
|
1877 |
-
"prefer-stable": false,
|
1878 |
-
"prefer-lowest": false,
|
1879 |
-
"platform": {
|
1880 |
-
"php": "^7.2|^8.0"
|
1881 |
-
},
|
1882 |
-
"platform-dev": [],
|
1883 |
-
"plugin-api-version": "2.3.0"
|
1884 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/utils/CnbUtils.php
CHANGED
@@ -257,6 +257,11 @@ class CnbUtils {
|
|
257 |
return $default;
|
258 |
}
|
259 |
|
|
|
|
|
|
|
|
|
|
|
260 |
function is_reporting_enabled() {
|
261 |
$cnb_options = get_option( 'cnb' );
|
262 |
return ( key_exists( 'error_reporting', $cnb_options ) && $cnb_options['error_reporting'] );
|
257 |
return $default;
|
258 |
}
|
259 |
|
260 |
+
/**
|
261 |
+
* Check if the error_reporting settings is set and enabled.
|
262 |
+
*
|
263 |
+
* @return bool
|
264 |
+
*/
|
265 |
function is_reporting_enabled() {
|
266 |
$cnb_options = get_option( 'cnb' );
|
267 |
return ( key_exists( 'error_reporting', $cnb_options ) && $cnb_options['error_reporting'] );
|
src/utils/class-cnb-sentry.php
CHANGED
@@ -44,8 +44,9 @@ class Cnb_Sentry {
|
|
44 |
}
|
45 |
|
46 |
$cnb_options = get_option( 'cnb' );
|
47 |
-
// Only do with permission AND PHP > 7 (since that's what Sentry requires)
|
48 |
-
|
|
|
49 |
&& ! class_exists( 'Sentry\SentrySdk' )
|
50 |
&& key_exists( 'error_reporting', $cnb_options )
|
51 |
&& $cnb_options['error_reporting'] ) {
|
@@ -70,7 +71,6 @@ class Cnb_Sentry {
|
|
70 |
'environment' => WP_DEBUG ? 'development' : 'production',
|
71 |
] );
|
72 |
|
73 |
-
|
74 |
self::setup_global_transaction($op_name);
|
75 |
$cnb_sentry_init = true;
|
76 |
}
|
@@ -86,17 +86,6 @@ class Cnb_Sentry {
|
|
86 |
} );
|
87 |
}
|
88 |
|
89 |
-
private function get_ip() {
|
90 |
-
if (isset($_SERVER['REMOTE_ADDR'])) {
|
91 |
-
return preg_replace(
|
92 |
-
'/[^\d., ]/', '',
|
93 |
-
// phpcs:ignore WordPress.Security
|
94 |
-
wp_unslash( $_SERVER['REMOTE_ADDR'] )
|
95 |
-
);
|
96 |
-
}
|
97 |
-
return 'ip unknown';
|
98 |
-
}
|
99 |
-
|
100 |
/**
|
101 |
* Finish the transaction, this submits the transaction and its span to Sentry
|
102 |
*
|
44 |
}
|
45 |
|
46 |
$cnb_options = get_option( 'cnb' );
|
47 |
+
// Only do with permission AND PHP > 7 (since that's what Sentry (/composer) requires)
|
48 |
+
// Verify this number is the same as used in src/vendor/composer/platform_check.php
|
49 |
+
if ( version_compare( PHP_VERSION, '7.2.5', '>=' )
|
50 |
&& ! class_exists( 'Sentry\SentrySdk' )
|
51 |
&& key_exists( 'error_reporting', $cnb_options )
|
52 |
&& $cnb_options['error_reporting'] ) {
|
71 |
'environment' => WP_DEBUG ? 'development' : 'production',
|
72 |
] );
|
73 |
|
|
|
74 |
self::setup_global_transaction($op_name);
|
75 |
$cnb_sentry_init = true;
|
76 |
}
|
86 |
} );
|
87 |
}
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
/**
|
90 |
* Finish the transaction, this submits the transaction and its span to Sentry
|
91 |
*
|
src/vendor/composer/InstalledVersions.php
CHANGED
@@ -28,7 +28,7 @@ class InstalledVersions
|
|
28 |
{
|
29 |
/**
|
30 |
* @var mixed[]|null
|
31 |
-
* @psalm-var array{root: array{name: string,
|
32 |
*/
|
33 |
private static $installed;
|
34 |
|
@@ -39,7 +39,7 @@ class InstalledVersions
|
|
39 |
|
40 |
/**
|
41 |
* @var array[]
|
42 |
-
* @psalm-var array<string, array{root: array{name: string,
|
43 |
*/
|
44 |
private static $installedByVendor = array();
|
45 |
|
@@ -243,7 +243,7 @@ class InstalledVersions
|
|
243 |
|
244 |
/**
|
245 |
* @return array
|
246 |
-
* @psalm-return array{name: string,
|
247 |
*/
|
248 |
public static function getRootPackage()
|
249 |
{
|
@@ -257,7 +257,7 @@ class InstalledVersions
|
|
257 |
*
|
258 |
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
259 |
* @return array[]
|
260 |
-
* @psalm-return array{root: array{name: string,
|
261 |
*/
|
262 |
public static function getRawData()
|
263 |
{
|
@@ -280,7 +280,7 @@ class InstalledVersions
|
|
280 |
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
281 |
*
|
282 |
* @return array[]
|
283 |
-
* @psalm-return list<array{root: array{name: string,
|
284 |
*/
|
285 |
public static function getAllRawData()
|
286 |
{
|
@@ -303,7 +303,7 @@ class InstalledVersions
|
|
303 |
* @param array[] $data A vendor/composer/installed.php data set
|
304 |
* @return void
|
305 |
*
|
306 |
-
* @psalm-param array{root: array{name: string,
|
307 |
*/
|
308 |
public static function reload($data)
|
309 |
{
|
@@ -313,7 +313,7 @@ class InstalledVersions
|
|
313 |
|
314 |
/**
|
315 |
* @return array[]
|
316 |
-
* @psalm-return list<array{root: array{name: string,
|
317 |
*/
|
318 |
private static function getInstalled()
|
319 |
{
|
28 |
{
|
29 |
/**
|
30 |
* @var mixed[]|null
|
31 |
+
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
32 |
*/
|
33 |
private static $installed;
|
34 |
|
39 |
|
40 |
/**
|
41 |
* @var array[]
|
42 |
+
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
43 |
*/
|
44 |
private static $installedByVendor = array();
|
45 |
|
243 |
|
244 |
/**
|
245 |
* @return array
|
246 |
+
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
247 |
*/
|
248 |
public static function getRootPackage()
|
249 |
{
|
257 |
*
|
258 |
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
259 |
* @return array[]
|
260 |
+
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
261 |
*/
|
262 |
public static function getRawData()
|
263 |
{
|
280 |
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
281 |
*
|
282 |
* @return array[]
|
283 |
+
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
284 |
*/
|
285 |
public static function getAllRawData()
|
286 |
{
|
303 |
* @param array[] $data A vendor/composer/installed.php data set
|
304 |
* @return void
|
305 |
*
|
306 |
+
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
307 |
*/
|
308 |
public static function reload($data)
|
309 |
{
|
313 |
|
314 |
/**
|
315 |
* @return array[]
|
316 |
+
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
317 |
*/
|
318 |
private static function getInstalled()
|
319 |
{
|
src/vendor/composer/autoload_files.php
CHANGED
@@ -7,9 +7,9 @@ $baseDir = dirname($vendorDir);
|
|
7 |
|
8 |
return array(
|
9 |
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
|
|
10 |
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
11 |
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
|
12 |
-
'9c67151ae59aff4788964ce8eb2a0f43' => $vendorDir . '/clue/stream-filter/src/functions_include.php',
|
13 |
'8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php',
|
14 |
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
15 |
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
7 |
|
8 |
return array(
|
9 |
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
10 |
+
'9c67151ae59aff4788964ce8eb2a0f43' => $vendorDir . '/clue/stream-filter/src/functions_include.php',
|
11 |
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
12 |
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
|
|
|
13 |
'8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php',
|
14 |
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
15 |
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
src/vendor/composer/autoload_psr4.php
CHANGED
@@ -9,20 +9,16 @@ return array(
|
|
9 |
'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'),
|
10 |
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
11 |
'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'),
|
12 |
-
'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
|
13 |
-
'Symfony\\Contracts\\HttpClient\\' => array($vendorDir . '/symfony/http-client-contracts'),
|
14 |
'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'),
|
15 |
-
'Symfony\\Component\\HttpClient\\' => array($vendorDir . '/symfony/http-client'),
|
16 |
'Sentry\\' => array($vendorDir . '/sentry/sentry/src'),
|
17 |
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
18 |
-
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-
|
19 |
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
20 |
-
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
21 |
'Jean85\\' => array($vendorDir . '/jean85/pretty-package-versions/src'),
|
22 |
'Http\\Promise\\' => array($vendorDir . '/php-http/promise/src'),
|
23 |
-
'Http\\Message\\' => array($vendorDir . '/php-http/message
|
24 |
-
'Http\\Factory\\Guzzle\\' => array($vendorDir . '/http-interop/http-factory-guzzle/src'),
|
25 |
'Http\\Discovery\\' => array($vendorDir . '/php-http/discovery/src'),
|
|
|
26 |
'Http\\Client\\Common\\' => array($vendorDir . '/php-http/client-common/src'),
|
27 |
'Http\\Client\\' => array($vendorDir . '/php-http/httplug/src'),
|
28 |
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
9 |
'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'),
|
10 |
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
11 |
'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'),
|
|
|
|
|
12 |
'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'),
|
|
|
13 |
'Sentry\\' => array($vendorDir . '/sentry/sentry/src'),
|
14 |
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
15 |
+
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
16 |
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
|
|
17 |
'Jean85\\' => array($vendorDir . '/jean85/pretty-package-versions/src'),
|
18 |
'Http\\Promise\\' => array($vendorDir . '/php-http/promise/src'),
|
19 |
+
'Http\\Message\\' => array($vendorDir . '/php-http/message/src', $vendorDir . '/php-http/message-factory/src'),
|
|
|
20 |
'Http\\Discovery\\' => array($vendorDir . '/php-http/discovery/src'),
|
21 |
+
'Http\\Client\\Curl\\' => array($vendorDir . '/php-http/curl-client/src'),
|
22 |
'Http\\Client\\Common\\' => array($vendorDir . '/php-http/client-common/src'),
|
23 |
'Http\\Client\\' => array($vendorDir . '/php-http/httplug/src'),
|
24 |
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
src/vendor/composer/autoload_static.php
CHANGED
@@ -8,9 +8,9 @@ class ComposerStaticInit447dd0acaa396d40f40a0cb37adffd44
|
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
|
|
11 |
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
12 |
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
|
13 |
-
'9c67151ae59aff4788964ce8eb2a0f43' => __DIR__ . '/..' . '/clue/stream-filter/src/functions_include.php',
|
14 |
'8cff32064859f4559445b89279f3199c' => __DIR__ . '/..' . '/php-http/message/src/filters.php',
|
15 |
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
16 |
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
@@ -24,10 +24,7 @@ class ComposerStaticInit447dd0acaa396d40f40a0cb37adffd44
|
|
24 |
'Symfony\\Polyfill\\Uuid\\' => 22,
|
25 |
'Symfony\\Polyfill\\Php80\\' => 23,
|
26 |
'Symfony\\Polyfill\\Php73\\' => 23,
|
27 |
-
'Symfony\\Contracts\\Service\\' => 26,
|
28 |
-
'Symfony\\Contracts\\HttpClient\\' => 29,
|
29 |
'Symfony\\Component\\OptionsResolver\\' => 34,
|
30 |
-
'Symfony\\Component\\HttpClient\\' => 29,
|
31 |
'Sentry\\' => 7,
|
32 |
),
|
33 |
'P' =>
|
@@ -35,7 +32,6 @@ class ComposerStaticInit447dd0acaa396d40f40a0cb37adffd44
|
|
35 |
'Psr\\Log\\' => 8,
|
36 |
'Psr\\Http\\Message\\' => 17,
|
37 |
'Psr\\Http\\Client\\' => 16,
|
38 |
-
'Psr\\Container\\' => 14,
|
39 |
),
|
40 |
'J' =>
|
41 |
array (
|
@@ -45,8 +41,8 @@ class ComposerStaticInit447dd0acaa396d40f40a0cb37adffd44
|
|
45 |
array (
|
46 |
'Http\\Promise\\' => 13,
|
47 |
'Http\\Message\\' => 13,
|
48 |
-
'Http\\Factory\\Guzzle\\' => 20,
|
49 |
'Http\\Discovery\\' => 15,
|
|
|
50 |
'Http\\Client\\Common\\' => 19,
|
51 |
'Http\\Client\\' => 12,
|
52 |
),
|
@@ -74,22 +70,10 @@ class ComposerStaticInit447dd0acaa396d40f40a0cb37adffd44
|
|
74 |
array (
|
75 |
0 => __DIR__ . '/..' . '/symfony/polyfill-php73',
|
76 |
),
|
77 |
-
'Symfony\\Contracts\\Service\\' =>
|
78 |
-
array (
|
79 |
-
0 => __DIR__ . '/..' . '/symfony/service-contracts',
|
80 |
-
),
|
81 |
-
'Symfony\\Contracts\\HttpClient\\' =>
|
82 |
-
array (
|
83 |
-
0 => __DIR__ . '/..' . '/symfony/http-client-contracts',
|
84 |
-
),
|
85 |
'Symfony\\Component\\OptionsResolver\\' =>
|
86 |
array (
|
87 |
0 => __DIR__ . '/..' . '/symfony/options-resolver',
|
88 |
),
|
89 |
-
'Symfony\\Component\\HttpClient\\' =>
|
90 |
-
array (
|
91 |
-
0 => __DIR__ . '/..' . '/symfony/http-client',
|
92 |
-
),
|
93 |
'Sentry\\' =>
|
94 |
array (
|
95 |
0 => __DIR__ . '/..' . '/sentry/sentry/src',
|
@@ -100,17 +84,13 @@ class ComposerStaticInit447dd0acaa396d40f40a0cb37adffd44
|
|
100 |
),
|
101 |
'Psr\\Http\\Message\\' =>
|
102 |
array (
|
103 |
-
0 => __DIR__ . '/..' . '/psr/http-
|
104 |
-
1 => __DIR__ . '/..' . '/psr/http-
|
105 |
),
|
106 |
'Psr\\Http\\Client\\' =>
|
107 |
array (
|
108 |
0 => __DIR__ . '/..' . '/psr/http-client/src',
|
109 |
),
|
110 |
-
'Psr\\Container\\' =>
|
111 |
-
array (
|
112 |
-
0 => __DIR__ . '/..' . '/psr/container/src',
|
113 |
-
),
|
114 |
'Jean85\\' =>
|
115 |
array (
|
116 |
0 => __DIR__ . '/..' . '/jean85/pretty-package-versions/src',
|
@@ -121,17 +101,17 @@ class ComposerStaticInit447dd0acaa396d40f40a0cb37adffd44
|
|
121 |
),
|
122 |
'Http\\Message\\' =>
|
123 |
array (
|
124 |
-
0 => __DIR__ . '/..' . '/php-http/message
|
125 |
-
1 => __DIR__ . '/..' . '/php-http/message/src',
|
126 |
-
),
|
127 |
-
'Http\\Factory\\Guzzle\\' =>
|
128 |
-
array (
|
129 |
-
0 => __DIR__ . '/..' . '/http-interop/http-factory-guzzle/src',
|
130 |
),
|
131 |
'Http\\Discovery\\' =>
|
132 |
array (
|
133 |
0 => __DIR__ . '/..' . '/php-http/discovery/src',
|
134 |
),
|
|
|
|
|
|
|
|
|
135 |
'Http\\Client\\Common\\' =>
|
136 |
array (
|
137 |
0 => __DIR__ . '/..' . '/php-http/client-common/src',
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
11 |
+
'9c67151ae59aff4788964ce8eb2a0f43' => __DIR__ . '/..' . '/clue/stream-filter/src/functions_include.php',
|
12 |
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
13 |
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
|
|
|
14 |
'8cff32064859f4559445b89279f3199c' => __DIR__ . '/..' . '/php-http/message/src/filters.php',
|
15 |
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
16 |
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
24 |
'Symfony\\Polyfill\\Uuid\\' => 22,
|
25 |
'Symfony\\Polyfill\\Php80\\' => 23,
|
26 |
'Symfony\\Polyfill\\Php73\\' => 23,
|
|
|
|
|
27 |
'Symfony\\Component\\OptionsResolver\\' => 34,
|
|
|
28 |
'Sentry\\' => 7,
|
29 |
),
|
30 |
'P' =>
|
32 |
'Psr\\Log\\' => 8,
|
33 |
'Psr\\Http\\Message\\' => 17,
|
34 |
'Psr\\Http\\Client\\' => 16,
|
|
|
35 |
),
|
36 |
'J' =>
|
37 |
array (
|
41 |
array (
|
42 |
'Http\\Promise\\' => 13,
|
43 |
'Http\\Message\\' => 13,
|
|
|
44 |
'Http\\Discovery\\' => 15,
|
45 |
+
'Http\\Client\\Curl\\' => 17,
|
46 |
'Http\\Client\\Common\\' => 19,
|
47 |
'Http\\Client\\' => 12,
|
48 |
),
|
70 |
array (
|
71 |
0 => __DIR__ . '/..' . '/symfony/polyfill-php73',
|
72 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
'Symfony\\Component\\OptionsResolver\\' =>
|
74 |
array (
|
75 |
0 => __DIR__ . '/..' . '/symfony/options-resolver',
|
76 |
),
|
|
|
|
|
|
|
|
|
77 |
'Sentry\\' =>
|
78 |
array (
|
79 |
0 => __DIR__ . '/..' . '/sentry/sentry/src',
|
84 |
),
|
85 |
'Psr\\Http\\Message\\' =>
|
86 |
array (
|
87 |
+
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
88 |
+
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
89 |
),
|
90 |
'Psr\\Http\\Client\\' =>
|
91 |
array (
|
92 |
0 => __DIR__ . '/..' . '/psr/http-client/src',
|
93 |
),
|
|
|
|
|
|
|
|
|
94 |
'Jean85\\' =>
|
95 |
array (
|
96 |
0 => __DIR__ . '/..' . '/jean85/pretty-package-versions/src',
|
101 |
),
|
102 |
'Http\\Message\\' =>
|
103 |
array (
|
104 |
+
0 => __DIR__ . '/..' . '/php-http/message/src',
|
105 |
+
1 => __DIR__ . '/..' . '/php-http/message-factory/src',
|
|
|
|
|
|
|
|
|
106 |
),
|
107 |
'Http\\Discovery\\' =>
|
108 |
array (
|
109 |
0 => __DIR__ . '/..' . '/php-http/discovery/src',
|
110 |
),
|
111 |
+
'Http\\Client\\Curl\\' =>
|
112 |
+
array (
|
113 |
+
0 => __DIR__ . '/..' . '/php-http/curl-client/src',
|
114 |
+
),
|
115 |
'Http\\Client\\Common\\' =>
|
116 |
array (
|
117 |
0 => __DIR__ . '/..' . '/php-http/client-common/src',
|
src/vendor/composer/installed.json
CHANGED
@@ -158,17 +158,17 @@
|
|
158 |
},
|
159 |
{
|
160 |
"name": "guzzlehttp/psr7",
|
161 |
-
"version": "2.
|
162 |
-
"version_normalized": "2.
|
163 |
"source": {
|
164 |
"type": "git",
|
165 |
"url": "https://github.com/guzzle/psr7.git",
|
166 |
-
"reference": "
|
167 |
},
|
168 |
"dist": {
|
169 |
"type": "zip",
|
170 |
-
"url": "https://api.github.com/repos/guzzle/psr7/zipball/
|
171 |
-
"reference": "
|
172 |
"shasum": ""
|
173 |
},
|
174 |
"require": {
|
@@ -189,11 +189,11 @@
|
|
189 |
"suggest": {
|
190 |
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
191 |
},
|
192 |
-
"time": "2022-06-
|
193 |
"type": "library",
|
194 |
"extra": {
|
195 |
"branch-alias": {
|
196 |
-
"dev-master": "2.
|
197 |
}
|
198 |
},
|
199 |
"installation-source": "dist",
|
@@ -256,7 +256,7 @@
|
|
256 |
],
|
257 |
"support": {
|
258 |
"issues": "https://github.com/guzzle/psr7/issues",
|
259 |
-
"source": "https://github.com/guzzle/psr7/tree/2.
|
260 |
},
|
261 |
"funding": [
|
262 |
{
|
@@ -274,67 +274,6 @@
|
|
274 |
],
|
275 |
"install-path": "../guzzlehttp/psr7"
|
276 |
},
|
277 |
-
{
|
278 |
-
"name": "http-interop/http-factory-guzzle",
|
279 |
-
"version": "1.2.0",
|
280 |
-
"version_normalized": "1.2.0.0",
|
281 |
-
"source": {
|
282 |
-
"type": "git",
|
283 |
-
"url": "https://github.com/http-interop/http-factory-guzzle.git",
|
284 |
-
"reference": "8f06e92b95405216b237521cc64c804dd44c4a81"
|
285 |
-
},
|
286 |
-
"dist": {
|
287 |
-
"type": "zip",
|
288 |
-
"url": "https://api.github.com/repos/http-interop/http-factory-guzzle/zipball/8f06e92b95405216b237521cc64c804dd44c4a81",
|
289 |
-
"reference": "8f06e92b95405216b237521cc64c804dd44c4a81",
|
290 |
-
"shasum": ""
|
291 |
-
},
|
292 |
-
"require": {
|
293 |
-
"guzzlehttp/psr7": "^1.7||^2.0",
|
294 |
-
"php": ">=7.3",
|
295 |
-
"psr/http-factory": "^1.0"
|
296 |
-
},
|
297 |
-
"provide": {
|
298 |
-
"psr/http-factory-implementation": "^1.0"
|
299 |
-
},
|
300 |
-
"require-dev": {
|
301 |
-
"http-interop/http-factory-tests": "^0.9",
|
302 |
-
"phpunit/phpunit": "^9.5"
|
303 |
-
},
|
304 |
-
"suggest": {
|
305 |
-
"guzzlehttp/psr7": "Includes an HTTP factory starting in version 2.0"
|
306 |
-
},
|
307 |
-
"time": "2021-07-21T13:50:14+00:00",
|
308 |
-
"type": "library",
|
309 |
-
"installation-source": "dist",
|
310 |
-
"autoload": {
|
311 |
-
"psr-4": {
|
312 |
-
"Http\\Factory\\Guzzle\\": "src/"
|
313 |
-
}
|
314 |
-
},
|
315 |
-
"notification-url": "https://packagist.org/downloads/",
|
316 |
-
"license": [
|
317 |
-
"MIT"
|
318 |
-
],
|
319 |
-
"authors": [
|
320 |
-
{
|
321 |
-
"name": "PHP-FIG",
|
322 |
-
"homepage": "http://www.php-fig.org/"
|
323 |
-
}
|
324 |
-
],
|
325 |
-
"description": "An HTTP Factory using Guzzle PSR7",
|
326 |
-
"keywords": [
|
327 |
-
"factory",
|
328 |
-
"http",
|
329 |
-
"psr-17",
|
330 |
-
"psr-7"
|
331 |
-
],
|
332 |
-
"support": {
|
333 |
-
"issues": "https://github.com/http-interop/http-factory-guzzle/issues",
|
334 |
-
"source": "https://github.com/http-interop/http-factory-guzzle/tree/1.2.0"
|
335 |
-
},
|
336 |
-
"install-path": "../http-interop/http-factory-guzzle"
|
337 |
-
},
|
338 |
{
|
339 |
"name": "jean85/pretty-package-versions",
|
340 |
"version": "2.0.5",
|
@@ -475,19 +414,91 @@
|
|
475 |
},
|
476 |
"install-path": "../php-http/client-common"
|
477 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
478 |
{
|
479 |
"name": "php-http/discovery",
|
480 |
-
"version": "1.14.
|
481 |
-
"version_normalized": "1.14.
|
482 |
"source": {
|
483 |
"type": "git",
|
484 |
"url": "https://github.com/php-http/discovery.git",
|
485 |
-
"reference": "
|
486 |
},
|
487 |
"dist": {
|
488 |
"type": "zip",
|
489 |
-
"url": "https://api.github.com/repos/php-http/discovery/zipball/
|
490 |
-
"reference": "
|
491 |
"shasum": ""
|
492 |
},
|
493 |
"require": {
|
@@ -505,7 +516,7 @@
|
|
505 |
"suggest": {
|
506 |
"php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories"
|
507 |
},
|
508 |
-
"time": "2022-
|
509 |
"type": "library",
|
510 |
"extra": {
|
511 |
"branch-alias": {
|
@@ -541,7 +552,7 @@
|
|
541 |
],
|
542 |
"support": {
|
543 |
"issues": "https://github.com/php-http/discovery/issues",
|
544 |
-
"source": "https://github.com/php-http/discovery/tree/1.14.
|
545 |
},
|
546 |
"install-path": "../php-http/discovery"
|
547 |
},
|
@@ -804,57 +815,6 @@
|
|
804 |
},
|
805 |
"install-path": "../php-http/promise"
|
806 |
},
|
807 |
-
{
|
808 |
-
"name": "psr/container",
|
809 |
-
"version": "1.1.2",
|
810 |
-
"version_normalized": "1.1.2.0",
|
811 |
-
"source": {
|
812 |
-
"type": "git",
|
813 |
-
"url": "https://github.com/php-fig/container.git",
|
814 |
-
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
|
815 |
-
},
|
816 |
-
"dist": {
|
817 |
-
"type": "zip",
|
818 |
-
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
|
819 |
-
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
|
820 |
-
"shasum": ""
|
821 |
-
},
|
822 |
-
"require": {
|
823 |
-
"php": ">=7.4.0"
|
824 |
-
},
|
825 |
-
"time": "2021-11-05T16:50:12+00:00",
|
826 |
-
"type": "library",
|
827 |
-
"installation-source": "dist",
|
828 |
-
"autoload": {
|
829 |
-
"psr-4": {
|
830 |
-
"Psr\\Container\\": "src/"
|
831 |
-
}
|
832 |
-
},
|
833 |
-
"notification-url": "https://packagist.org/downloads/",
|
834 |
-
"license": [
|
835 |
-
"MIT"
|
836 |
-
],
|
837 |
-
"authors": [
|
838 |
-
{
|
839 |
-
"name": "PHP-FIG",
|
840 |
-
"homepage": "https://www.php-fig.org/"
|
841 |
-
}
|
842 |
-
],
|
843 |
-
"description": "Common Container Interface (PHP FIG PSR-11)",
|
844 |
-
"homepage": "https://github.com/php-fig/container",
|
845 |
-
"keywords": [
|
846 |
-
"PSR-11",
|
847 |
-
"container",
|
848 |
-
"container-interface",
|
849 |
-
"container-interop",
|
850 |
-
"psr"
|
851 |
-
],
|
852 |
-
"support": {
|
853 |
-
"issues": "https://github.com/php-fig/container/issues",
|
854 |
-
"source": "https://github.com/php-fig/container/tree/1.1.2"
|
855 |
-
},
|
856 |
-
"install-path": "../psr/container"
|
857 |
-
},
|
858 |
{
|
859 |
"name": "psr/http-client",
|
860 |
"version": "1.0.1",
|
@@ -1124,78 +1084,19 @@
|
|
1124 |
},
|
1125 |
"install-path": "../ralouphie/getallheaders"
|
1126 |
},
|
1127 |
-
{
|
1128 |
-
"name": "sentry/sdk",
|
1129 |
-
"version": "3.2.0",
|
1130 |
-
"version_normalized": "3.2.0.0",
|
1131 |
-
"source": {
|
1132 |
-
"type": "git",
|
1133 |
-
"url": "https://github.com/getsentry/sentry-php-sdk.git",
|
1134 |
-
"reference": "6d78bd83b43efbb52f81d6824f4af344fa9ba292"
|
1135 |
-
},
|
1136 |
-
"dist": {
|
1137 |
-
"type": "zip",
|
1138 |
-
"url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/6d78bd83b43efbb52f81d6824f4af344fa9ba292",
|
1139 |
-
"reference": "6d78bd83b43efbb52f81d6824f4af344fa9ba292",
|
1140 |
-
"shasum": ""
|
1141 |
-
},
|
1142 |
-
"require": {
|
1143 |
-
"http-interop/http-factory-guzzle": "^1.0",
|
1144 |
-
"sentry/sentry": "^3.5",
|
1145 |
-
"symfony/http-client": "^4.3|^5.0|^6.0"
|
1146 |
-
},
|
1147 |
-
"time": "2022-05-21T11:10:11+00:00",
|
1148 |
-
"type": "metapackage",
|
1149 |
-
"notification-url": "https://packagist.org/downloads/",
|
1150 |
-
"license": [
|
1151 |
-
"MIT"
|
1152 |
-
],
|
1153 |
-
"authors": [
|
1154 |
-
{
|
1155 |
-
"name": "Sentry",
|
1156 |
-
"email": "accounts@sentry.io"
|
1157 |
-
}
|
1158 |
-
],
|
1159 |
-
"description": "This is a metapackage shipping sentry/sentry with a recommended HTTP client.",
|
1160 |
-
"homepage": "http://sentry.io",
|
1161 |
-
"keywords": [
|
1162 |
-
"crash-reporting",
|
1163 |
-
"crash-reports",
|
1164 |
-
"error-handler",
|
1165 |
-
"error-monitoring",
|
1166 |
-
"log",
|
1167 |
-
"logging",
|
1168 |
-
"sentry"
|
1169 |
-
],
|
1170 |
-
"support": {
|
1171 |
-
"issues": "https://github.com/getsentry/sentry-php-sdk/issues",
|
1172 |
-
"source": "https://github.com/getsentry/sentry-php-sdk/tree/3.2.0"
|
1173 |
-
},
|
1174 |
-
"funding": [
|
1175 |
-
{
|
1176 |
-
"url": "https://sentry.io/",
|
1177 |
-
"type": "custom"
|
1178 |
-
},
|
1179 |
-
{
|
1180 |
-
"url": "https://sentry.io/pricing/",
|
1181 |
-
"type": "custom"
|
1182 |
-
}
|
1183 |
-
],
|
1184 |
-
"install-path": null
|
1185 |
-
},
|
1186 |
{
|
1187 |
"name": "sentry/sentry",
|
1188 |
-
"version": "3.
|
1189 |
-
"version_normalized": "3.
|
1190 |
"source": {
|
1191 |
"type": "git",
|
1192 |
"url": "https://github.com/getsentry/sentry-php.git",
|
1193 |
-
"reference": "
|
1194 |
},
|
1195 |
"dist": {
|
1196 |
"type": "zip",
|
1197 |
-
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/
|
1198 |
-
"reference": "
|
1199 |
"shasum": ""
|
1200 |
},
|
1201 |
"require": {
|
@@ -1238,11 +1139,11 @@
|
|
1238 |
"suggest": {
|
1239 |
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
|
1240 |
},
|
1241 |
-
"time": "2022-
|
1242 |
"type": "library",
|
1243 |
"extra": {
|
1244 |
"branch-alias": {
|
1245 |
-
"dev-master": "3.
|
1246 |
}
|
1247 |
},
|
1248 |
"installation-source": "dist",
|
@@ -1277,7 +1178,7 @@
|
|
1277 |
],
|
1278 |
"support": {
|
1279 |
"issues": "https://github.com/getsentry/sentry-php/issues",
|
1280 |
-
"source": "https://github.com/getsentry/sentry-php/tree/3.
|
1281 |
},
|
1282 |
"funding": [
|
1283 |
{
|
@@ -1293,8 +1194,8 @@
|
|
1293 |
},
|
1294 |
{
|
1295 |
"name": "symfony/deprecation-contracts",
|
1296 |
-
"version": "v2.5.
|
1297 |
-
"version_normalized": "2.5.
|
1298 |
"source": {
|
1299 |
"type": "git",
|
1300 |
"url": "https://github.com/symfony/deprecation-contracts.git",
|
@@ -1343,7 +1244,7 @@
|
|
1343 |
"description": "A generic function and convention to trigger deprecation notices",
|
1344 |
"homepage": "https://symfony.com",
|
1345 |
"support": {
|
1346 |
-
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.
|
1347 |
},
|
1348 |
"funding": [
|
1349 |
{
|
@@ -1361,177 +1262,6 @@
|
|
1361 |
],
|
1362 |
"install-path": "../symfony/deprecation-contracts"
|
1363 |
},
|
1364 |
-
{
|
1365 |
-
"name": "symfony/http-client",
|
1366 |
-
"version": "v5.4.9",
|
1367 |
-
"version_normalized": "5.4.9.0",
|
1368 |
-
"source": {
|
1369 |
-
"type": "git",
|
1370 |
-
"url": "https://github.com/symfony/http-client.git",
|
1371 |
-
"reference": "dc0b15e42b762c040761c1eb9ce86a55d47cf672"
|
1372 |
-
},
|
1373 |
-
"dist": {
|
1374 |
-
"type": "zip",
|
1375 |
-
"url": "https://api.github.com/repos/symfony/http-client/zipball/dc0b15e42b762c040761c1eb9ce86a55d47cf672",
|
1376 |
-
"reference": "dc0b15e42b762c040761c1eb9ce86a55d47cf672",
|
1377 |
-
"shasum": ""
|
1378 |
-
},
|
1379 |
-
"require": {
|
1380 |
-
"php": ">=7.2.5",
|
1381 |
-
"psr/log": "^1|^2|^3",
|
1382 |
-
"symfony/deprecation-contracts": "^2.1|^3",
|
1383 |
-
"symfony/http-client-contracts": "^2.4",
|
1384 |
-
"symfony/polyfill-php73": "^1.11",
|
1385 |
-
"symfony/polyfill-php80": "^1.16",
|
1386 |
-
"symfony/service-contracts": "^1.0|^2|^3"
|
1387 |
-
},
|
1388 |
-
"provide": {
|
1389 |
-
"php-http/async-client-implementation": "*",
|
1390 |
-
"php-http/client-implementation": "*",
|
1391 |
-
"psr/http-client-implementation": "1.0",
|
1392 |
-
"symfony/http-client-implementation": "2.4"
|
1393 |
-
},
|
1394 |
-
"require-dev": {
|
1395 |
-
"amphp/amp": "^2.5",
|
1396 |
-
"amphp/http-client": "^4.2.1",
|
1397 |
-
"amphp/http-tunnel": "^1.0",
|
1398 |
-
"amphp/socket": "^1.1",
|
1399 |
-
"guzzlehttp/promises": "^1.4",
|
1400 |
-
"nyholm/psr7": "^1.0",
|
1401 |
-
"php-http/httplug": "^1.0|^2.0",
|
1402 |
-
"psr/http-client": "^1.0",
|
1403 |
-
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
|
1404 |
-
"symfony/http-kernel": "^4.4.13|^5.1.5|^6.0",
|
1405 |
-
"symfony/process": "^4.4|^5.0|^6.0",
|
1406 |
-
"symfony/stopwatch": "^4.4|^5.0|^6.0"
|
1407 |
-
},
|
1408 |
-
"time": "2022-05-21T08:57:05+00:00",
|
1409 |
-
"type": "library",
|
1410 |
-
"installation-source": "dist",
|
1411 |
-
"autoload": {
|
1412 |
-
"psr-4": {
|
1413 |
-
"Symfony\\Component\\HttpClient\\": ""
|
1414 |
-
},
|
1415 |
-
"exclude-from-classmap": [
|
1416 |
-
"/Tests/"
|
1417 |
-
]
|
1418 |
-
},
|
1419 |
-
"notification-url": "https://packagist.org/downloads/",
|
1420 |
-
"license": [
|
1421 |
-
"MIT"
|
1422 |
-
],
|
1423 |
-
"authors": [
|
1424 |
-
{
|
1425 |
-
"name": "Nicolas Grekas",
|
1426 |
-
"email": "p@tchwork.com"
|
1427 |
-
},
|
1428 |
-
{
|
1429 |
-
"name": "Symfony Community",
|
1430 |
-
"homepage": "https://symfony.com/contributors"
|
1431 |
-
}
|
1432 |
-
],
|
1433 |
-
"description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
|
1434 |
-
"homepage": "https://symfony.com",
|
1435 |
-
"support": {
|
1436 |
-
"source": "https://github.com/symfony/http-client/tree/v5.4.9"
|
1437 |
-
},
|
1438 |
-
"funding": [
|
1439 |
-
{
|
1440 |
-
"url": "https://symfony.com/sponsor",
|
1441 |
-
"type": "custom"
|
1442 |
-
},
|
1443 |
-
{
|
1444 |
-
"url": "https://github.com/fabpot",
|
1445 |
-
"type": "github"
|
1446 |
-
},
|
1447 |
-
{
|
1448 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1449 |
-
"type": "tidelift"
|
1450 |
-
}
|
1451 |
-
],
|
1452 |
-
"install-path": "../symfony/http-client"
|
1453 |
-
},
|
1454 |
-
{
|
1455 |
-
"name": "symfony/http-client-contracts",
|
1456 |
-
"version": "v2.5.1",
|
1457 |
-
"version_normalized": "2.5.1.0",
|
1458 |
-
"source": {
|
1459 |
-
"type": "git",
|
1460 |
-
"url": "https://github.com/symfony/http-client-contracts.git",
|
1461 |
-
"reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5"
|
1462 |
-
},
|
1463 |
-
"dist": {
|
1464 |
-
"type": "zip",
|
1465 |
-
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1a4f708e4e87f335d1b1be6148060739152f0bd5",
|
1466 |
-
"reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5",
|
1467 |
-
"shasum": ""
|
1468 |
-
},
|
1469 |
-
"require": {
|
1470 |
-
"php": ">=7.2.5"
|
1471 |
-
},
|
1472 |
-
"suggest": {
|
1473 |
-
"symfony/http-client-implementation": ""
|
1474 |
-
},
|
1475 |
-
"time": "2022-03-13T20:07:29+00:00",
|
1476 |
-
"type": "library",
|
1477 |
-
"extra": {
|
1478 |
-
"branch-alias": {
|
1479 |
-
"dev-main": "2.5-dev"
|
1480 |
-
},
|
1481 |
-
"thanks": {
|
1482 |
-
"name": "symfony/contracts",
|
1483 |
-
"url": "https://github.com/symfony/contracts"
|
1484 |
-
}
|
1485 |
-
},
|
1486 |
-
"installation-source": "dist",
|
1487 |
-
"autoload": {
|
1488 |
-
"psr-4": {
|
1489 |
-
"Symfony\\Contracts\\HttpClient\\": ""
|
1490 |
-
}
|
1491 |
-
},
|
1492 |
-
"notification-url": "https://packagist.org/downloads/",
|
1493 |
-
"license": [
|
1494 |
-
"MIT"
|
1495 |
-
],
|
1496 |
-
"authors": [
|
1497 |
-
{
|
1498 |
-
"name": "Nicolas Grekas",
|
1499 |
-
"email": "p@tchwork.com"
|
1500 |
-
},
|
1501 |
-
{
|
1502 |
-
"name": "Symfony Community",
|
1503 |
-
"homepage": "https://symfony.com/contributors"
|
1504 |
-
}
|
1505 |
-
],
|
1506 |
-
"description": "Generic abstractions related to HTTP clients",
|
1507 |
-
"homepage": "https://symfony.com",
|
1508 |
-
"keywords": [
|
1509 |
-
"abstractions",
|
1510 |
-
"contracts",
|
1511 |
-
"decoupling",
|
1512 |
-
"interfaces",
|
1513 |
-
"interoperability",
|
1514 |
-
"standards"
|
1515 |
-
],
|
1516 |
-
"support": {
|
1517 |
-
"source": "https://github.com/symfony/http-client-contracts/tree/v2.5.1"
|
1518 |
-
},
|
1519 |
-
"funding": [
|
1520 |
-
{
|
1521 |
-
"url": "https://symfony.com/sponsor",
|
1522 |
-
"type": "custom"
|
1523 |
-
},
|
1524 |
-
{
|
1525 |
-
"url": "https://github.com/fabpot",
|
1526 |
-
"type": "github"
|
1527 |
-
},
|
1528 |
-
{
|
1529 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1530 |
-
"type": "tidelift"
|
1531 |
-
}
|
1532 |
-
],
|
1533 |
-
"install-path": "../symfony/http-client-contracts"
|
1534 |
-
},
|
1535 |
{
|
1536 |
"name": "symfony/options-resolver",
|
1537 |
"version": "v5.4.3",
|
@@ -1856,92 +1586,6 @@
|
|
1856 |
}
|
1857 |
],
|
1858 |
"install-path": "../symfony/polyfill-uuid"
|
1859 |
-
},
|
1860 |
-
{
|
1861 |
-
"name": "symfony/service-contracts",
|
1862 |
-
"version": "v2.5.1",
|
1863 |
-
"version_normalized": "2.5.1.0",
|
1864 |
-
"source": {
|
1865 |
-
"type": "git",
|
1866 |
-
"url": "https://github.com/symfony/service-contracts.git",
|
1867 |
-
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
|
1868 |
-
},
|
1869 |
-
"dist": {
|
1870 |
-
"type": "zip",
|
1871 |
-
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
|
1872 |
-
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
|
1873 |
-
"shasum": ""
|
1874 |
-
},
|
1875 |
-
"require": {
|
1876 |
-
"php": ">=7.2.5",
|
1877 |
-
"psr/container": "^1.1",
|
1878 |
-
"symfony/deprecation-contracts": "^2.1|^3"
|
1879 |
-
},
|
1880 |
-
"conflict": {
|
1881 |
-
"ext-psr": "<1.1|>=2"
|
1882 |
-
},
|
1883 |
-
"suggest": {
|
1884 |
-
"symfony/service-implementation": ""
|
1885 |
-
},
|
1886 |
-
"time": "2022-03-13T20:07:29+00:00",
|
1887 |
-
"type": "library",
|
1888 |
-
"extra": {
|
1889 |
-
"branch-alias": {
|
1890 |
-
"dev-main": "2.5-dev"
|
1891 |
-
},
|
1892 |
-
"thanks": {
|
1893 |
-
"name": "symfony/contracts",
|
1894 |
-
"url": "https://github.com/symfony/contracts"
|
1895 |
-
}
|
1896 |
-
},
|
1897 |
-
"installation-source": "dist",
|
1898 |
-
"autoload": {
|
1899 |
-
"psr-4": {
|
1900 |
-
"Symfony\\Contracts\\Service\\": ""
|
1901 |
-
}
|
1902 |
-
},
|
1903 |
-
"notification-url": "https://packagist.org/downloads/",
|
1904 |
-
"license": [
|
1905 |
-
"MIT"
|
1906 |
-
],
|
1907 |
-
"authors": [
|
1908 |
-
{
|
1909 |
-
"name": "Nicolas Grekas",
|
1910 |
-
"email": "p@tchwork.com"
|
1911 |
-
},
|
1912 |
-
{
|
1913 |
-
"name": "Symfony Community",
|
1914 |
-
"homepage": "https://symfony.com/contributors"
|
1915 |
-
}
|
1916 |
-
],
|
1917 |
-
"description": "Generic abstractions related to writing services",
|
1918 |
-
"homepage": "https://symfony.com",
|
1919 |
-
"keywords": [
|
1920 |
-
"abstractions",
|
1921 |
-
"contracts",
|
1922 |
-
"decoupling",
|
1923 |
-
"interfaces",
|
1924 |
-
"interoperability",
|
1925 |
-
"standards"
|
1926 |
-
],
|
1927 |
-
"support": {
|
1928 |
-
"source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
|
1929 |
-
},
|
1930 |
-
"funding": [
|
1931 |
-
{
|
1932 |
-
"url": "https://symfony.com/sponsor",
|
1933 |
-
"type": "custom"
|
1934 |
-
},
|
1935 |
-
{
|
1936 |
-
"url": "https://github.com/fabpot",
|
1937 |
-
"type": "github"
|
1938 |
-
},
|
1939 |
-
{
|
1940 |
-
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
1941 |
-
"type": "tidelift"
|
1942 |
-
}
|
1943 |
-
],
|
1944 |
-
"install-path": "../symfony/service-contracts"
|
1945 |
}
|
1946 |
],
|
1947 |
"dev": true,
|
158 |
},
|
159 |
{
|
160 |
"name": "guzzlehttp/psr7",
|
161 |
+
"version": "2.4.0",
|
162 |
+
"version_normalized": "2.4.0.0",
|
163 |
"source": {
|
164 |
"type": "git",
|
165 |
"url": "https://github.com/guzzle/psr7.git",
|
166 |
+
"reference": "13388f00956b1503577598873fffb5ae994b5737"
|
167 |
},
|
168 |
"dist": {
|
169 |
"type": "zip",
|
170 |
+
"url": "https://api.github.com/repos/guzzle/psr7/zipball/13388f00956b1503577598873fffb5ae994b5737",
|
171 |
+
"reference": "13388f00956b1503577598873fffb5ae994b5737",
|
172 |
"shasum": ""
|
173 |
},
|
174 |
"require": {
|
189 |
"suggest": {
|
190 |
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
191 |
},
|
192 |
+
"time": "2022-06-20T21:43:11+00:00",
|
193 |
"type": "library",
|
194 |
"extra": {
|
195 |
"branch-alias": {
|
196 |
+
"dev-master": "2.4-dev"
|
197 |
}
|
198 |
},
|
199 |
"installation-source": "dist",
|
256 |
],
|
257 |
"support": {
|
258 |
"issues": "https://github.com/guzzle/psr7/issues",
|
259 |
+
"source": "https://github.com/guzzle/psr7/tree/2.4.0"
|
260 |
},
|
261 |
"funding": [
|
262 |
{
|
274 |
],
|
275 |
"install-path": "../guzzlehttp/psr7"
|
276 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
{
|
278 |
"name": "jean85/pretty-package-versions",
|
279 |
"version": "2.0.5",
|
414 |
},
|
415 |
"install-path": "../php-http/client-common"
|
416 |
},
|
417 |
+
{
|
418 |
+
"name": "php-http/curl-client",
|
419 |
+
"version": "2.2.1",
|
420 |
+
"version_normalized": "2.2.1.0",
|
421 |
+
"source": {
|
422 |
+
"type": "git",
|
423 |
+
"url": "https://github.com/php-http/curl-client.git",
|
424 |
+
"reference": "2ed4245a817d859dd0c1d51c7078cdb343cf5233"
|
425 |
+
},
|
426 |
+
"dist": {
|
427 |
+
"type": "zip",
|
428 |
+
"url": "https://api.github.com/repos/php-http/curl-client/zipball/2ed4245a817d859dd0c1d51c7078cdb343cf5233",
|
429 |
+
"reference": "2ed4245a817d859dd0c1d51c7078cdb343cf5233",
|
430 |
+
"shasum": ""
|
431 |
+
},
|
432 |
+
"require": {
|
433 |
+
"ext-curl": "*",
|
434 |
+
"php": "^7.1 || ^8.0",
|
435 |
+
"php-http/discovery": "^1.6",
|
436 |
+
"php-http/httplug": "^2.0",
|
437 |
+
"php-http/message": "^1.2",
|
438 |
+
"psr/http-client": "^1.0",
|
439 |
+
"psr/http-factory": "^1.0",
|
440 |
+
"symfony/options-resolver": "^3.4 || ^4.0 || ^5.0 || ^6.0"
|
441 |
+
},
|
442 |
+
"provide": {
|
443 |
+
"php-http/async-client-implementation": "1.0",
|
444 |
+
"php-http/client-implementation": "1.0",
|
445 |
+
"psr/http-client-implementation": "1.0"
|
446 |
+
},
|
447 |
+
"require-dev": {
|
448 |
+
"guzzlehttp/psr7": "^1.0",
|
449 |
+
"laminas/laminas-diactoros": "^2.0",
|
450 |
+
"php-http/client-integration-tests": "^3.0",
|
451 |
+
"phpunit/phpunit": "^7.5 || ^9.4"
|
452 |
+
},
|
453 |
+
"time": "2021-12-10T18:02:07+00:00",
|
454 |
+
"type": "library",
|
455 |
+
"extra": {
|
456 |
+
"branch-alias": {
|
457 |
+
"dev-master": "2.x-dev"
|
458 |
+
}
|
459 |
+
},
|
460 |
+
"installation-source": "dist",
|
461 |
+
"autoload": {
|
462 |
+
"psr-4": {
|
463 |
+
"Http\\Client\\Curl\\": "src/"
|
464 |
+
}
|
465 |
+
},
|
466 |
+
"notification-url": "https://packagist.org/downloads/",
|
467 |
+
"license": [
|
468 |
+
"MIT"
|
469 |
+
],
|
470 |
+
"authors": [
|
471 |
+
{
|
472 |
+
"name": "Михаил Красильников",
|
473 |
+
"email": "m.krasilnikov@yandex.ru"
|
474 |
+
}
|
475 |
+
],
|
476 |
+
"description": "PSR-18 and HTTPlug Async client with cURL",
|
477 |
+
"homepage": "http://php-http.org",
|
478 |
+
"keywords": [
|
479 |
+
"curl",
|
480 |
+
"http",
|
481 |
+
"psr-18"
|
482 |
+
],
|
483 |
+
"support": {
|
484 |
+
"issues": "https://github.com/php-http/curl-client/issues",
|
485 |
+
"source": "https://github.com/php-http/curl-client/tree/2.2.1"
|
486 |
+
},
|
487 |
+
"install-path": "../php-http/curl-client"
|
488 |
+
},
|
489 |
{
|
490 |
"name": "php-http/discovery",
|
491 |
+
"version": "1.14.3",
|
492 |
+
"version_normalized": "1.14.3.0",
|
493 |
"source": {
|
494 |
"type": "git",
|
495 |
"url": "https://github.com/php-http/discovery.git",
|
496 |
+
"reference": "31d8ee46d0215108df16a8527c7438e96a4d7735"
|
497 |
},
|
498 |
"dist": {
|
499 |
"type": "zip",
|
500 |
+
"url": "https://api.github.com/repos/php-http/discovery/zipball/31d8ee46d0215108df16a8527c7438e96a4d7735",
|
501 |
+
"reference": "31d8ee46d0215108df16a8527c7438e96a4d7735",
|
502 |
"shasum": ""
|
503 |
},
|
504 |
"require": {
|
516 |
"suggest": {
|
517 |
"php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories"
|
518 |
},
|
519 |
+
"time": "2022-07-11T14:04:40+00:00",
|
520 |
"type": "library",
|
521 |
"extra": {
|
522 |
"branch-alias": {
|
552 |
],
|
553 |
"support": {
|
554 |
"issues": "https://github.com/php-http/discovery/issues",
|
555 |
+
"source": "https://github.com/php-http/discovery/tree/1.14.3"
|
556 |
},
|
557 |
"install-path": "../php-http/discovery"
|
558 |
},
|
815 |
},
|
816 |
"install-path": "../php-http/promise"
|
817 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
818 |
{
|
819 |
"name": "psr/http-client",
|
820 |
"version": "1.0.1",
|
1084 |
},
|
1085 |
"install-path": "../ralouphie/getallheaders"
|
1086 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1087 |
{
|
1088 |
"name": "sentry/sentry",
|
1089 |
+
"version": "3.7.0",
|
1090 |
+
"version_normalized": "3.7.0.0",
|
1091 |
"source": {
|
1092 |
"type": "git",
|
1093 |
"url": "https://github.com/getsentry/sentry-php.git",
|
1094 |
+
"reference": "877bca3f0f0ac0fc8ec0a218c6070cccea266795"
|
1095 |
},
|
1096 |
"dist": {
|
1097 |
"type": "zip",
|
1098 |
+
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/877bca3f0f0ac0fc8ec0a218c6070cccea266795",
|
1099 |
+
"reference": "877bca3f0f0ac0fc8ec0a218c6070cccea266795",
|
1100 |
"shasum": ""
|
1101 |
},
|
1102 |
"require": {
|
1139 |
"suggest": {
|
1140 |
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
|
1141 |
},
|
1142 |
+
"time": "2022-07-18T07:55:36+00:00",
|
1143 |
"type": "library",
|
1144 |
"extra": {
|
1145 |
"branch-alias": {
|
1146 |
+
"dev-master": "3.7.x-dev"
|
1147 |
}
|
1148 |
},
|
1149 |
"installation-source": "dist",
|
1178 |
],
|
1179 |
"support": {
|
1180 |
"issues": "https://github.com/getsentry/sentry-php/issues",
|
1181 |
+
"source": "https://github.com/getsentry/sentry-php/tree/3.7.0"
|
1182 |
},
|
1183 |
"funding": [
|
1184 |
{
|
1194 |
},
|
1195 |
{
|
1196 |
"name": "symfony/deprecation-contracts",
|
1197 |
+
"version": "v2.5.2",
|
1198 |
+
"version_normalized": "2.5.2.0",
|
1199 |
"source": {
|
1200 |
"type": "git",
|
1201 |
"url": "https://github.com/symfony/deprecation-contracts.git",
|
1244 |
"description": "A generic function and convention to trigger deprecation notices",
|
1245 |
"homepage": "https://symfony.com",
|
1246 |
"support": {
|
1247 |
+
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2"
|
1248 |
},
|
1249 |
"funding": [
|
1250 |
{
|
1262 |
],
|
1263 |
"install-path": "../symfony/deprecation-contracts"
|
1264 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1265 |
{
|
1266 |
"name": "symfony/options-resolver",
|
1267 |
"version": "v5.4.3",
|
1586 |
}
|
1587 |
],
|
1588 |
"install-path": "../symfony/polyfill-uuid"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1589 |
}
|
1590 |
],
|
1591 |
"dev": true,
|
src/vendor/composer/installed.php
CHANGED
@@ -1,124 +1,124 @@
|
|
1 |
<?php return array(
|
2 |
'root' => array(
|
|
|
3 |
'pretty_version' => 'dev-master',
|
4 |
'version' => 'dev-master',
|
|
|
5 |
'type' => 'library',
|
6 |
'install_path' => __DIR__ . '/../../',
|
7 |
'aliases' => array(),
|
8 |
-
'reference' => 'fb3ccded0384ee9d86c8ecb0ac0cf84a969f93e6',
|
9 |
-
'name' => '__root__',
|
10 |
'dev' => true,
|
11 |
),
|
12 |
'versions' => array(
|
13 |
'__root__' => array(
|
14 |
'pretty_version' => 'dev-master',
|
15 |
'version' => 'dev-master',
|
|
|
16 |
'type' => 'library',
|
17 |
'install_path' => __DIR__ . '/../../',
|
18 |
'aliases' => array(),
|
19 |
-
'reference' => 'fb3ccded0384ee9d86c8ecb0ac0cf84a969f93e6',
|
20 |
'dev_requirement' => false,
|
21 |
),
|
22 |
'clue/stream-filter' => array(
|
23 |
'pretty_version' => 'v1.6.0',
|
24 |
'version' => '1.6.0.0',
|
|
|
25 |
'type' => 'library',
|
26 |
'install_path' => __DIR__ . '/../clue/stream-filter',
|
27 |
'aliases' => array(),
|
28 |
-
'reference' => 'd6169430c7731d8509da7aecd0af756a5747b78e',
|
29 |
'dev_requirement' => false,
|
30 |
),
|
31 |
'guzzlehttp/promises' => array(
|
32 |
'pretty_version' => '1.5.1',
|
33 |
'version' => '1.5.1.0',
|
|
|
34 |
'type' => 'library',
|
35 |
'install_path' => __DIR__ . '/../guzzlehttp/promises',
|
36 |
'aliases' => array(),
|
37 |
-
'reference' => 'fe752aedc9fd8fcca3fe7ad05d419d32998a06da',
|
38 |
'dev_requirement' => false,
|
39 |
),
|
40 |
'guzzlehttp/psr7' => array(
|
41 |
-
'pretty_version' => '2.
|
42 |
-
'version' => '2.
|
|
|
43 |
'type' => 'library',
|
44 |
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
|
45 |
'aliases' => array(),
|
46 |
-
'reference' => '83260bb50b8fc753c72d14dc1621a2dac31877ee',
|
47 |
-
'dev_requirement' => false,
|
48 |
-
),
|
49 |
-
'http-interop/http-factory-guzzle' => array(
|
50 |
-
'pretty_version' => '1.2.0',
|
51 |
-
'version' => '1.2.0.0',
|
52 |
-
'type' => 'library',
|
53 |
-
'install_path' => __DIR__ . '/../http-interop/http-factory-guzzle',
|
54 |
-
'aliases' => array(),
|
55 |
-
'reference' => '8f06e92b95405216b237521cc64c804dd44c4a81',
|
56 |
'dev_requirement' => false,
|
57 |
),
|
58 |
'jean85/pretty-package-versions' => array(
|
59 |
'pretty_version' => '2.0.5',
|
60 |
'version' => '2.0.5.0',
|
|
|
61 |
'type' => 'library',
|
62 |
'install_path' => __DIR__ . '/../jean85/pretty-package-versions',
|
63 |
'aliases' => array(),
|
64 |
-
'reference' => 'ae547e455a3d8babd07b96966b17d7fd21d9c6af',
|
65 |
'dev_requirement' => false,
|
66 |
),
|
67 |
'php-http/async-client-implementation' => array(
|
68 |
'dev_requirement' => false,
|
69 |
'provided' => array(
|
70 |
-
0 => '
|
71 |
),
|
72 |
),
|
73 |
'php-http/client-common' => array(
|
74 |
'pretty_version' => '2.5.0',
|
75 |
'version' => '2.5.0.0',
|
|
|
76 |
'type' => 'library',
|
77 |
'install_path' => __DIR__ . '/../php-http/client-common',
|
78 |
'aliases' => array(),
|
79 |
-
'reference' => 'd135751167d57e27c74de674d6a30cef2dc8e054',
|
80 |
'dev_requirement' => false,
|
81 |
),
|
82 |
'php-http/client-implementation' => array(
|
83 |
'dev_requirement' => false,
|
84 |
'provided' => array(
|
85 |
-
0 => '
|
86 |
),
|
87 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
'php-http/discovery' => array(
|
89 |
-
'pretty_version' => '1.14.
|
90 |
-
'version' => '1.14.
|
|
|
91 |
'type' => 'library',
|
92 |
'install_path' => __DIR__ . '/../php-http/discovery',
|
93 |
'aliases' => array(),
|
94 |
-
'reference' => 'c8d48852fbc052454af42f6de27635ddd916b959',
|
95 |
'dev_requirement' => false,
|
96 |
),
|
97 |
'php-http/httplug' => array(
|
98 |
'pretty_version' => '2.3.0',
|
99 |
'version' => '2.3.0.0',
|
|
|
100 |
'type' => 'library',
|
101 |
'install_path' => __DIR__ . '/../php-http/httplug',
|
102 |
'aliases' => array(),
|
103 |
-
'reference' => 'f640739f80dfa1152533976e3c112477f69274eb',
|
104 |
'dev_requirement' => false,
|
105 |
),
|
106 |
'php-http/message' => array(
|
107 |
'pretty_version' => '1.13.0',
|
108 |
'version' => '1.13.0.0',
|
|
|
109 |
'type' => 'library',
|
110 |
'install_path' => __DIR__ . '/../php-http/message',
|
111 |
'aliases' => array(),
|
112 |
-
'reference' => '7886e647a30a966a1a8d1dad1845b71ca8678361',
|
113 |
'dev_requirement' => false,
|
114 |
),
|
115 |
'php-http/message-factory' => array(
|
116 |
'pretty_version' => 'v1.0.2',
|
117 |
'version' => '1.0.2.0',
|
|
|
118 |
'type' => 'library',
|
119 |
'install_path' => __DIR__ . '/../php-http/message-factory',
|
120 |
'aliases' => array(),
|
121 |
-
'reference' => 'a478cb11f66a6ac48d8954216cfed9aa06a501a1',
|
122 |
'dev_requirement' => false,
|
123 |
),
|
124 |
'php-http/message-factory-implementation' => array(
|
@@ -130,28 +130,19 @@
|
|
130 |
'php-http/promise' => array(
|
131 |
'pretty_version' => '1.1.0',
|
132 |
'version' => '1.1.0.0',
|
133 |
-
'type' => 'library',
|
134 |
-
'install_path' => __DIR__ . '/../php-http/promise',
|
135 |
-
'aliases' => array(),
|
136 |
'reference' => '4c4c1f9b7289a2ec57cde7f1e9762a5789506f88',
|
137 |
-
'dev_requirement' => false,
|
138 |
-
),
|
139 |
-
'psr/container' => array(
|
140 |
-
'pretty_version' => '1.1.2',
|
141 |
-
'version' => '1.1.2.0',
|
142 |
'type' => 'library',
|
143 |
-
'install_path' => __DIR__ . '/../
|
144 |
'aliases' => array(),
|
145 |
-
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
|
146 |
'dev_requirement' => false,
|
147 |
),
|
148 |
'psr/http-client' => array(
|
149 |
'pretty_version' => '1.0.1',
|
150 |
'version' => '1.0.1.0',
|
|
|
151 |
'type' => 'library',
|
152 |
'install_path' => __DIR__ . '/../psr/http-client',
|
153 |
'aliases' => array(),
|
154 |
-
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
|
155 |
'dev_requirement' => false,
|
156 |
),
|
157 |
'psr/http-client-implementation' => array(
|
@@ -163,26 +154,25 @@
|
|
163 |
'psr/http-factory' => array(
|
164 |
'pretty_version' => '1.0.1',
|
165 |
'version' => '1.0.1.0',
|
|
|
166 |
'type' => 'library',
|
167 |
'install_path' => __DIR__ . '/../psr/http-factory',
|
168 |
'aliases' => array(),
|
169 |
-
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
|
170 |
'dev_requirement' => false,
|
171 |
),
|
172 |
'psr/http-factory-implementation' => array(
|
173 |
'dev_requirement' => false,
|
174 |
'provided' => array(
|
175 |
0 => '1.0',
|
176 |
-
1 => '^1.0',
|
177 |
),
|
178 |
),
|
179 |
'psr/http-message' => array(
|
180 |
'pretty_version' => '1.0.1',
|
181 |
'version' => '1.0.1.0',
|
|
|
182 |
'type' => 'library',
|
183 |
'install_path' => __DIR__ . '/../psr/http-message',
|
184 |
'aliases' => array(),
|
185 |
-
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
186 |
'dev_requirement' => false,
|
187 |
),
|
188 |
'psr/http-message-implementation' => array(
|
@@ -194,115 +184,73 @@
|
|
194 |
'psr/log' => array(
|
195 |
'pretty_version' => '1.1.4',
|
196 |
'version' => '1.1.4.0',
|
|
|
197 |
'type' => 'library',
|
198 |
'install_path' => __DIR__ . '/../psr/log',
|
199 |
'aliases' => array(),
|
200 |
-
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
201 |
'dev_requirement' => false,
|
202 |
),
|
203 |
'ralouphie/getallheaders' => array(
|
204 |
'pretty_version' => '3.0.3',
|
205 |
'version' => '3.0.3.0',
|
|
|
206 |
'type' => 'library',
|
207 |
'install_path' => __DIR__ . '/../ralouphie/getallheaders',
|
208 |
'aliases' => array(),
|
209 |
-
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
|
210 |
-
'dev_requirement' => false,
|
211 |
-
),
|
212 |
-
'sentry/sdk' => array(
|
213 |
-
'pretty_version' => '3.2.0',
|
214 |
-
'version' => '3.2.0.0',
|
215 |
-
'type' => 'metapackage',
|
216 |
-
'install_path' => NULL,
|
217 |
-
'aliases' => array(),
|
218 |
-
'reference' => '6d78bd83b43efbb52f81d6824f4af344fa9ba292',
|
219 |
'dev_requirement' => false,
|
220 |
),
|
221 |
'sentry/sentry' => array(
|
222 |
-
'pretty_version' => '3.
|
223 |
-
'version' => '3.
|
|
|
224 |
'type' => 'library',
|
225 |
'install_path' => __DIR__ . '/../sentry/sentry',
|
226 |
'aliases' => array(),
|
227 |
-
'reference' => '6d1a6ee29c558be373bfe08d454a3c116c02dd0d',
|
228 |
'dev_requirement' => false,
|
229 |
),
|
230 |
'symfony/deprecation-contracts' => array(
|
231 |
-
'pretty_version' => 'v2.5.
|
232 |
-
'version' => '2.5.
|
233 |
-
'type' => 'library',
|
234 |
-
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
235 |
-
'aliases' => array(),
|
236 |
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
|
237 |
-
'dev_requirement' => false,
|
238 |
-
),
|
239 |
-
'symfony/http-client' => array(
|
240 |
-
'pretty_version' => 'v5.4.9',
|
241 |
-
'version' => '5.4.9.0',
|
242 |
-
'type' => 'library',
|
243 |
-
'install_path' => __DIR__ . '/../symfony/http-client',
|
244 |
-
'aliases' => array(),
|
245 |
-
'reference' => 'dc0b15e42b762c040761c1eb9ce86a55d47cf672',
|
246 |
-
'dev_requirement' => false,
|
247 |
-
),
|
248 |
-
'symfony/http-client-contracts' => array(
|
249 |
-
'pretty_version' => 'v2.5.1',
|
250 |
-
'version' => '2.5.1.0',
|
251 |
'type' => 'library',
|
252 |
-
'install_path' => __DIR__ . '/../symfony/
|
253 |
'aliases' => array(),
|
254 |
-
'reference' => '1a4f708e4e87f335d1b1be6148060739152f0bd5',
|
255 |
'dev_requirement' => false,
|
256 |
),
|
257 |
-
'symfony/http-client-implementation' => array(
|
258 |
-
'dev_requirement' => false,
|
259 |
-
'provided' => array(
|
260 |
-
0 => '2.4',
|
261 |
-
),
|
262 |
-
),
|
263 |
'symfony/options-resolver' => array(
|
264 |
'pretty_version' => 'v5.4.3',
|
265 |
'version' => '5.4.3.0',
|
|
|
266 |
'type' => 'library',
|
267 |
'install_path' => __DIR__ . '/../symfony/options-resolver',
|
268 |
'aliases' => array(),
|
269 |
-
'reference' => 'cc1147cb11af1b43f503ac18f31aa3bec213aba8',
|
270 |
'dev_requirement' => false,
|
271 |
),
|
272 |
'symfony/polyfill-php73' => array(
|
273 |
'pretty_version' => 'v1.26.0',
|
274 |
'version' => '1.26.0.0',
|
|
|
275 |
'type' => 'library',
|
276 |
'install_path' => __DIR__ . '/../symfony/polyfill-php73',
|
277 |
'aliases' => array(),
|
278 |
-
'reference' => 'e440d35fa0286f77fb45b79a03fedbeda9307e85',
|
279 |
'dev_requirement' => false,
|
280 |
),
|
281 |
'symfony/polyfill-php80' => array(
|
282 |
'pretty_version' => 'v1.26.0',
|
283 |
'version' => '1.26.0.0',
|
|
|
284 |
'type' => 'library',
|
285 |
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
286 |
'aliases' => array(),
|
287 |
-
'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace',
|
288 |
'dev_requirement' => false,
|
289 |
),
|
290 |
'symfony/polyfill-uuid' => array(
|
291 |
'pretty_version' => 'v1.26.0',
|
292 |
'version' => '1.26.0.0',
|
293 |
-
'type' => 'library',
|
294 |
-
'install_path' => __DIR__ . '/../symfony/polyfill-uuid',
|
295 |
-
'aliases' => array(),
|
296 |
'reference' => 'a41886c1c81dc075a09c71fe6db5b9d68c79de23',
|
297 |
-
'dev_requirement' => false,
|
298 |
-
),
|
299 |
-
'symfony/service-contracts' => array(
|
300 |
-
'pretty_version' => 'v2.5.1',
|
301 |
-
'version' => '2.5.1.0',
|
302 |
'type' => 'library',
|
303 |
-
'install_path' => __DIR__ . '/../symfony/
|
304 |
'aliases' => array(),
|
305 |
-
'reference' => '24d9dc654b83e91aa59f9d167b131bc3b5bea24c',
|
306 |
'dev_requirement' => false,
|
307 |
),
|
308 |
),
|
1 |
<?php return array(
|
2 |
'root' => array(
|
3 |
+
'name' => '__root__',
|
4 |
'pretty_version' => 'dev-master',
|
5 |
'version' => 'dev-master',
|
6 |
+
'reference' => 'd2c6b667fba2a45bba8a3ce6ced006dfa882dfbd',
|
7 |
'type' => 'library',
|
8 |
'install_path' => __DIR__ . '/../../',
|
9 |
'aliases' => array(),
|
|
|
|
|
10 |
'dev' => true,
|
11 |
),
|
12 |
'versions' => array(
|
13 |
'__root__' => array(
|
14 |
'pretty_version' => 'dev-master',
|
15 |
'version' => 'dev-master',
|
16 |
+
'reference' => 'd2c6b667fba2a45bba8a3ce6ced006dfa882dfbd',
|
17 |
'type' => 'library',
|
18 |
'install_path' => __DIR__ . '/../../',
|
19 |
'aliases' => array(),
|
|
|
20 |
'dev_requirement' => false,
|
21 |
),
|
22 |
'clue/stream-filter' => array(
|
23 |
'pretty_version' => 'v1.6.0',
|
24 |
'version' => '1.6.0.0',
|
25 |
+
'reference' => 'd6169430c7731d8509da7aecd0af756a5747b78e',
|
26 |
'type' => 'library',
|
27 |
'install_path' => __DIR__ . '/../clue/stream-filter',
|
28 |
'aliases' => array(),
|
|
|
29 |
'dev_requirement' => false,
|
30 |
),
|
31 |
'guzzlehttp/promises' => array(
|
32 |
'pretty_version' => '1.5.1',
|
33 |
'version' => '1.5.1.0',
|
34 |
+
'reference' => 'fe752aedc9fd8fcca3fe7ad05d419d32998a06da',
|
35 |
'type' => 'library',
|
36 |
'install_path' => __DIR__ . '/../guzzlehttp/promises',
|
37 |
'aliases' => array(),
|
|
|
38 |
'dev_requirement' => false,
|
39 |
),
|
40 |
'guzzlehttp/psr7' => array(
|
41 |
+
'pretty_version' => '2.4.0',
|
42 |
+
'version' => '2.4.0.0',
|
43 |
+
'reference' => '13388f00956b1503577598873fffb5ae994b5737',
|
44 |
'type' => 'library',
|
45 |
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
|
46 |
'aliases' => array(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
'dev_requirement' => false,
|
48 |
),
|
49 |
'jean85/pretty-package-versions' => array(
|
50 |
'pretty_version' => '2.0.5',
|
51 |
'version' => '2.0.5.0',
|
52 |
+
'reference' => 'ae547e455a3d8babd07b96966b17d7fd21d9c6af',
|
53 |
'type' => 'library',
|
54 |
'install_path' => __DIR__ . '/../jean85/pretty-package-versions',
|
55 |
'aliases' => array(),
|
|
|
56 |
'dev_requirement' => false,
|
57 |
),
|
58 |
'php-http/async-client-implementation' => array(
|
59 |
'dev_requirement' => false,
|
60 |
'provided' => array(
|
61 |
+
0 => '1.0',
|
62 |
),
|
63 |
),
|
64 |
'php-http/client-common' => array(
|
65 |
'pretty_version' => '2.5.0',
|
66 |
'version' => '2.5.0.0',
|
67 |
+
'reference' => 'd135751167d57e27c74de674d6a30cef2dc8e054',
|
68 |
'type' => 'library',
|
69 |
'install_path' => __DIR__ . '/../php-http/client-common',
|
70 |
'aliases' => array(),
|
|
|
71 |
'dev_requirement' => false,
|
72 |
),
|
73 |
'php-http/client-implementation' => array(
|
74 |
'dev_requirement' => false,
|
75 |
'provided' => array(
|
76 |
+
0 => '1.0',
|
77 |
),
|
78 |
),
|
79 |
+
'php-http/curl-client' => array(
|
80 |
+
'pretty_version' => '2.2.1',
|
81 |
+
'version' => '2.2.1.0',
|
82 |
+
'reference' => '2ed4245a817d859dd0c1d51c7078cdb343cf5233',
|
83 |
+
'type' => 'library',
|
84 |
+
'install_path' => __DIR__ . '/../php-http/curl-client',
|
85 |
+
'aliases' => array(),
|
86 |
+
'dev_requirement' => false,
|
87 |
+
),
|
88 |
'php-http/discovery' => array(
|
89 |
+
'pretty_version' => '1.14.3',
|
90 |
+
'version' => '1.14.3.0',
|
91 |
+
'reference' => '31d8ee46d0215108df16a8527c7438e96a4d7735',
|
92 |
'type' => 'library',
|
93 |
'install_path' => __DIR__ . '/../php-http/discovery',
|
94 |
'aliases' => array(),
|
|
|
95 |
'dev_requirement' => false,
|
96 |
),
|
97 |
'php-http/httplug' => array(
|
98 |
'pretty_version' => '2.3.0',
|
99 |
'version' => '2.3.0.0',
|
100 |
+
'reference' => 'f640739f80dfa1152533976e3c112477f69274eb',
|
101 |
'type' => 'library',
|
102 |
'install_path' => __DIR__ . '/../php-http/httplug',
|
103 |
'aliases' => array(),
|
|
|
104 |
'dev_requirement' => false,
|
105 |
),
|
106 |
'php-http/message' => array(
|
107 |
'pretty_version' => '1.13.0',
|
108 |
'version' => '1.13.0.0',
|
109 |
+
'reference' => '7886e647a30a966a1a8d1dad1845b71ca8678361',
|
110 |
'type' => 'library',
|
111 |
'install_path' => __DIR__ . '/../php-http/message',
|
112 |
'aliases' => array(),
|
|
|
113 |
'dev_requirement' => false,
|
114 |
),
|
115 |
'php-http/message-factory' => array(
|
116 |
'pretty_version' => 'v1.0.2',
|
117 |
'version' => '1.0.2.0',
|
118 |
+
'reference' => 'a478cb11f66a6ac48d8954216cfed9aa06a501a1',
|
119 |
'type' => 'library',
|
120 |
'install_path' => __DIR__ . '/../php-http/message-factory',
|
121 |
'aliases' => array(),
|
|
|
122 |
'dev_requirement' => false,
|
123 |
),
|
124 |
'php-http/message-factory-implementation' => array(
|
130 |
'php-http/promise' => array(
|
131 |
'pretty_version' => '1.1.0',
|
132 |
'version' => '1.1.0.0',
|
|
|
|
|
|
|
133 |
'reference' => '4c4c1f9b7289a2ec57cde7f1e9762a5789506f88',
|
|
|
|
|
|
|
|
|
|
|
134 |
'type' => 'library',
|
135 |
+
'install_path' => __DIR__ . '/../php-http/promise',
|
136 |
'aliases' => array(),
|
|
|
137 |
'dev_requirement' => false,
|
138 |
),
|
139 |
'psr/http-client' => array(
|
140 |
'pretty_version' => '1.0.1',
|
141 |
'version' => '1.0.1.0',
|
142 |
+
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
|
143 |
'type' => 'library',
|
144 |
'install_path' => __DIR__ . '/../psr/http-client',
|
145 |
'aliases' => array(),
|
|
|
146 |
'dev_requirement' => false,
|
147 |
),
|
148 |
'psr/http-client-implementation' => array(
|
154 |
'psr/http-factory' => array(
|
155 |
'pretty_version' => '1.0.1',
|
156 |
'version' => '1.0.1.0',
|
157 |
+
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
|
158 |
'type' => 'library',
|
159 |
'install_path' => __DIR__ . '/../psr/http-factory',
|
160 |
'aliases' => array(),
|
|
|
161 |
'dev_requirement' => false,
|
162 |
),
|
163 |
'psr/http-factory-implementation' => array(
|
164 |
'dev_requirement' => false,
|
165 |
'provided' => array(
|
166 |
0 => '1.0',
|
|
|
167 |
),
|
168 |
),
|
169 |
'psr/http-message' => array(
|
170 |
'pretty_version' => '1.0.1',
|
171 |
'version' => '1.0.1.0',
|
172 |
+
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
173 |
'type' => 'library',
|
174 |
'install_path' => __DIR__ . '/../psr/http-message',
|
175 |
'aliases' => array(),
|
|
|
176 |
'dev_requirement' => false,
|
177 |
),
|
178 |
'psr/http-message-implementation' => array(
|
184 |
'psr/log' => array(
|
185 |
'pretty_version' => '1.1.4',
|
186 |
'version' => '1.1.4.0',
|
187 |
+
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
188 |
'type' => 'library',
|
189 |
'install_path' => __DIR__ . '/../psr/log',
|
190 |
'aliases' => array(),
|
|
|
191 |
'dev_requirement' => false,
|
192 |
),
|
193 |
'ralouphie/getallheaders' => array(
|
194 |
'pretty_version' => '3.0.3',
|
195 |
'version' => '3.0.3.0',
|
196 |
+
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
|
197 |
'type' => 'library',
|
198 |
'install_path' => __DIR__ . '/../ralouphie/getallheaders',
|
199 |
'aliases' => array(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
'dev_requirement' => false,
|
201 |
),
|
202 |
'sentry/sentry' => array(
|
203 |
+
'pretty_version' => '3.7.0',
|
204 |
+
'version' => '3.7.0.0',
|
205 |
+
'reference' => '877bca3f0f0ac0fc8ec0a218c6070cccea266795',
|
206 |
'type' => 'library',
|
207 |
'install_path' => __DIR__ . '/../sentry/sentry',
|
208 |
'aliases' => array(),
|
|
|
209 |
'dev_requirement' => false,
|
210 |
),
|
211 |
'symfony/deprecation-contracts' => array(
|
212 |
+
'pretty_version' => 'v2.5.2',
|
213 |
+
'version' => '2.5.2.0',
|
|
|
|
|
|
|
214 |
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
'type' => 'library',
|
216 |
+
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
217 |
'aliases' => array(),
|
|
|
218 |
'dev_requirement' => false,
|
219 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
'symfony/options-resolver' => array(
|
221 |
'pretty_version' => 'v5.4.3',
|
222 |
'version' => '5.4.3.0',
|
223 |
+
'reference' => 'cc1147cb11af1b43f503ac18f31aa3bec213aba8',
|
224 |
'type' => 'library',
|
225 |
'install_path' => __DIR__ . '/../symfony/options-resolver',
|
226 |
'aliases' => array(),
|
|
|
227 |
'dev_requirement' => false,
|
228 |
),
|
229 |
'symfony/polyfill-php73' => array(
|
230 |
'pretty_version' => 'v1.26.0',
|
231 |
'version' => '1.26.0.0',
|
232 |
+
'reference' => 'e440d35fa0286f77fb45b79a03fedbeda9307e85',
|
233 |
'type' => 'library',
|
234 |
'install_path' => __DIR__ . '/../symfony/polyfill-php73',
|
235 |
'aliases' => array(),
|
|
|
236 |
'dev_requirement' => false,
|
237 |
),
|
238 |
'symfony/polyfill-php80' => array(
|
239 |
'pretty_version' => 'v1.26.0',
|
240 |
'version' => '1.26.0.0',
|
241 |
+
'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace',
|
242 |
'type' => 'library',
|
243 |
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
244 |
'aliases' => array(),
|
|
|
245 |
'dev_requirement' => false,
|
246 |
),
|
247 |
'symfony/polyfill-uuid' => array(
|
248 |
'pretty_version' => 'v1.26.0',
|
249 |
'version' => '1.26.0.0',
|
|
|
|
|
|
|
250 |
'reference' => 'a41886c1c81dc075a09c71fe6db5b9d68c79de23',
|
|
|
|
|
|
|
|
|
|
|
251 |
'type' => 'library',
|
252 |
+
'install_path' => __DIR__ . '/../symfony/polyfill-uuid',
|
253 |
'aliases' => array(),
|
|
|
254 |
'dev_requirement' => false,
|
255 |
),
|
256 |
),
|
src/vendor/composer/platform_check.php
CHANGED
@@ -4,8 +4,8 @@
|
|
4 |
|
5 |
$issues = array();
|
6 |
|
7 |
-
if (!(PHP_VERSION_ID >=
|
8 |
-
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.
|
9 |
}
|
10 |
|
11 |
if ($issues) {
|
4 |
|
5 |
$issues = array();
|
6 |
|
7 |
+
if (!(PHP_VERSION_ID >= 70205)) {
|
8 |
+
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
|
9 |
}
|
10 |
|
11 |
if ($issues) {
|
src/vendor/guzzlehttp/psr7/CHANGELOG.md
CHANGED
@@ -7,20 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7 |
|
8 |
## Unreleased
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
## 2.3.0 - 2022-06-09
|
11 |
|
12 |
### Fixed
|
13 |
|
14 |
-
- Added `Header::splitList
|
15 |
-
- Added `Utils::tryGetContents`
|
16 |
-
- Improved `Stream::getContents
|
17 |
- Updated mimetype mappings
|
18 |
|
19 |
## 2.2.2 - 2022-06-08
|
20 |
|
21 |
### Fixed
|
22 |
|
23 |
-
- Fix `Message::parseRequestUri
|
24 |
- Re-wrap exceptions thrown in `fread` into runtime exceptions
|
25 |
- Throw an exception when multipart options is misformatted
|
26 |
|
7 |
|
8 |
## Unreleased
|
9 |
|
10 |
+
## 2.4.0 - 2022-06-20
|
11 |
+
|
12 |
+
### Added
|
13 |
+
|
14 |
+
- Added provisional PHP 8.2 support
|
15 |
+
- Added `UriComparator::isCrossOrigin` method
|
16 |
+
|
17 |
## 2.3.0 - 2022-06-09
|
18 |
|
19 |
### Fixed
|
20 |
|
21 |
+
- Added `Header::splitList` method
|
22 |
+
- Added `Utils::tryGetContents` method
|
23 |
+
- Improved `Stream::getContents` method
|
24 |
- Updated mimetype mappings
|
25 |
|
26 |
## 2.2.2 - 2022-06-08
|
27 |
|
28 |
### Fixed
|
29 |
|
30 |
+
- Fix `Message::parseRequestUri` for numeric headers
|
31 |
- Re-wrap exceptions thrown in `fread` into runtime exceptions
|
32 |
- Throw an exception when multipart options is misformatted
|
33 |
|
src/vendor/guzzlehttp/psr7/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
# PSR-7 Message Implementation
|
2 |
|
3 |
-
This repository contains a full [PSR-7](
|
4 |
message implementation, several stream decorators, and some helpful
|
5 |
functionality like query string parsing.
|
6 |
|
@@ -669,7 +669,7 @@ manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__to
|
|
669 |
|
670 |
`public static function fromParts(array $parts): UriInterface`
|
671 |
|
672 |
-
Creates a URI from a hash of [`parse_url`](
|
673 |
|
674 |
|
675 |
### `GuzzleHttp\Psr7\Uri::withQueryValue`
|
@@ -694,6 +694,16 @@ associative array of key => value.
|
|
694 |
Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
|
695 |
provided key are removed.
|
696 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
697 |
## Reference Resolution
|
698 |
|
699 |
`GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according
|
@@ -818,21 +828,25 @@ Whether two URIs can be considered equivalent. Both URIs are normalized automati
|
|
818 |
This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
|
819 |
equivalence or difference of relative references does not mean anything.
|
820 |
|
|
|
821 |
## Version Guidance
|
822 |
|
823 |
| Version | Status | PHP Version |
|
824 |
|---------|----------------|------------------|
|
825 |
-
| 1.x | Security fixes | >=
|
826 |
| 2.x | Latest | ^7.2.5 \|\| ^8.0 |
|
827 |
|
|
|
828 |
## Security
|
829 |
|
830 |
If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information.
|
831 |
|
|
|
832 |
## License
|
833 |
|
834 |
Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.
|
835 |
|
|
|
836 |
## For Enterprise
|
837 |
|
838 |
Available as part of the Tidelift Subscription
|
1 |
# PSR-7 Message Implementation
|
2 |
|
3 |
+
This repository contains a full [PSR-7](https://www.php-fig.org/psr/psr-7/)
|
4 |
message implementation, several stream decorators, and some helpful
|
5 |
functionality like query string parsing.
|
6 |
|
669 |
|
670 |
`public static function fromParts(array $parts): UriInterface`
|
671 |
|
672 |
+
Creates a URI from a hash of [`parse_url`](https://www.php.net/manual/en/function.parse-url.php) components.
|
673 |
|
674 |
|
675 |
### `GuzzleHttp\Psr7\Uri::withQueryValue`
|
694 |
Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
|
695 |
provided key are removed.
|
696 |
|
697 |
+
## Cross-Origin Detection
|
698 |
+
|
699 |
+
`GuzzleHttp\Psr7\UriComparator` provides methods to determine if a modified URL should be considered cross-origin.
|
700 |
+
|
701 |
+
### `GuzzleHttp\Psr7\UriComparator::isCrossOrigin`
|
702 |
+
|
703 |
+
`public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool`
|
704 |
+
|
705 |
+
Determines if a modified URL should be considered cross-origin with respect to an original URL.
|
706 |
+
|
707 |
## Reference Resolution
|
708 |
|
709 |
`GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according
|
828 |
This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
|
829 |
equivalence or difference of relative references does not mean anything.
|
830 |
|
831 |
+
|
832 |
## Version Guidance
|
833 |
|
834 |
| Version | Status | PHP Version |
|
835 |
|---------|----------------|------------------|
|
836 |
+
| 1.x | Security fixes | >=5.4,<8.1 |
|
837 |
| 2.x | Latest | ^7.2.5 \|\| ^8.0 |
|
838 |
|
839 |
+
|
840 |
## Security
|
841 |
|
842 |
If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information.
|
843 |
|
844 |
+
|
845 |
## License
|
846 |
|
847 |
Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.
|
848 |
|
849 |
+
|
850 |
## For Enterprise
|
851 |
|
852 |
Available as part of the Tidelift Subscription
|
src/vendor/guzzlehttp/psr7/composer.json
CHANGED
@@ -79,7 +79,7 @@
|
|
79 |
},
|
80 |
"extra": {
|
81 |
"branch-alias": {
|
82 |
-
"dev-master": "2.
|
83 |
}
|
84 |
},
|
85 |
"config": {
|
79 |
},
|
80 |
"extra": {
|
81 |
"branch-alias": {
|
82 |
+
"dev-master": "2.4-dev"
|
83 |
}
|
84 |
},
|
85 |
"config": {
|
src/vendor/guzzlehttp/psr7/src/CachingStream.php
CHANGED
@@ -20,6 +20,11 @@ final class CachingStream implements StreamInterface
|
|
20 |
/** @var int Number of bytes to skip reading due to a write on the buffer */
|
21 |
private $skipReadBytes = 0;
|
22 |
|
|
|
|
|
|
|
|
|
|
|
23 |
/**
|
24 |
* We will treat the buffer object as the body of the stream
|
25 |
*
|
20 |
/** @var int Number of bytes to skip reading due to a write on the buffer */
|
21 |
private $skipReadBytes = 0;
|
22 |
|
23 |
+
/**
|
24 |
+
* @var StreamInterface
|
25 |
+
*/
|
26 |
+
private $stream;
|
27 |
+
|
28 |
/**
|
29 |
* We will treat the buffer object as the body of the stream
|
30 |
*
|
src/vendor/guzzlehttp/psr7/src/DroppingStream.php
CHANGED
@@ -17,6 +17,9 @@ final class DroppingStream implements StreamInterface
|
|
17 |
/** @var int */
|
18 |
private $maxLength;
|
19 |
|
|
|
|
|
|
|
20 |
/**
|
21 |
* @param StreamInterface $stream Underlying stream to decorate.
|
22 |
* @param int $maxLength Maximum size before dropping data.
|
17 |
/** @var int */
|
18 |
private $maxLength;
|
19 |
|
20 |
+
/** @var StreamInterface */
|
21 |
+
private $stream;
|
22 |
+
|
23 |
/**
|
24 |
* @param StreamInterface $stream Underlying stream to decorate.
|
25 |
* @param int $maxLength Maximum size before dropping data.
|
src/vendor/guzzlehttp/psr7/src/FnStream.php
CHANGED
@@ -12,6 +12,7 @@ use Psr\Http\Message\StreamInterface;
|
|
12 |
* Allows for easy testing and extension of a provided stream without needing
|
13 |
* to create a concrete class for a simple extension point.
|
14 |
*/
|
|
|
15 |
final class FnStream implements StreamInterface
|
16 |
{
|
17 |
private const SLOTS = [
|
12 |
* Allows for easy testing and extension of a provided stream without needing
|
13 |
* to create a concrete class for a simple extension point.
|
14 |
*/
|
15 |
+
#[\AllowDynamicProperties]
|
16 |
final class FnStream implements StreamInterface
|
17 |
{
|
18 |
private const SLOTS = [
|
src/vendor/guzzlehttp/psr7/src/InflateStream.php
CHANGED
@@ -21,6 +21,9 @@ final class InflateStream implements StreamInterface
|
|
21 |
{
|
22 |
use StreamDecoratorTrait;
|
23 |
|
|
|
|
|
|
|
24 |
public function __construct(StreamInterface $stream)
|
25 |
{
|
26 |
$resource = StreamWrapper::getResource($stream);
|
21 |
{
|
22 |
use StreamDecoratorTrait;
|
23 |
|
24 |
+
/** @var StreamInterface */
|
25 |
+
private $stream;
|
26 |
+
|
27 |
public function __construct(StreamInterface $stream)
|
28 |
{
|
29 |
$resource = StreamWrapper::getResource($stream);
|
src/vendor/guzzlehttp/psr7/src/LazyOpenStream.php
CHANGED
@@ -10,6 +10,7 @@ use Psr\Http\Message\StreamInterface;
|
|
10 |
* Lazily reads or writes to a file that is opened only after an IO operation
|
11 |
* take place on the stream.
|
12 |
*/
|
|
|
13 |
final class LazyOpenStream implements StreamInterface
|
14 |
{
|
15 |
use StreamDecoratorTrait;
|
10 |
* Lazily reads or writes to a file that is opened only after an IO operation
|
11 |
* take place on the stream.
|
12 |
*/
|
13 |
+
#[\AllowDynamicProperties]
|
14 |
final class LazyOpenStream implements StreamInterface
|
15 |
{
|
16 |
use StreamDecoratorTrait;
|
src/vendor/guzzlehttp/psr7/src/LimitStream.php
CHANGED
@@ -19,6 +19,9 @@ final class LimitStream implements StreamInterface
|
|
19 |
/** @var int Limit the number of bytes that can be read */
|
20 |
private $limit;
|
21 |
|
|
|
|
|
|
|
22 |
/**
|
23 |
* @param StreamInterface $stream Stream to wrap
|
24 |
* @param int $limit Total number of bytes to allow to be read
|
19 |
/** @var int Limit the number of bytes that can be read */
|
20 |
private $limit;
|
21 |
|
22 |
+
/** @var StreamInterface */
|
23 |
+
private $stream;
|
24 |
+
|
25 |
/**
|
26 |
* @param StreamInterface $stream Stream to wrap
|
27 |
* @param int $limit Total number of bytes to allow to be read
|
src/vendor/guzzlehttp/psr7/src/MultipartStream.php
CHANGED
@@ -17,6 +17,9 @@ final class MultipartStream implements StreamInterface
|
|
17 |
/** @var string */
|
18 |
private $boundary;
|
19 |
|
|
|
|
|
|
|
20 |
/**
|
21 |
* @param array $elements Array of associative arrays, each containing a
|
22 |
* required "name" key mapping to the form field,
|
17 |
/** @var string */
|
18 |
private $boundary;
|
19 |
|
20 |
+
/** @var StreamInterface */
|
21 |
+
private $stream;
|
22 |
+
|
23 |
/**
|
24 |
* @param array $elements Array of associative arrays, each containing a
|
25 |
* required "name" key mapping to the form field,
|
src/vendor/guzzlehttp/psr7/src/NoSeekStream.php
CHANGED
@@ -13,6 +13,9 @@ final class NoSeekStream implements StreamInterface
|
|
13 |
{
|
14 |
use StreamDecoratorTrait;
|
15 |
|
|
|
|
|
|
|
16 |
public function seek($offset, $whence = SEEK_SET): void
|
17 |
{
|
18 |
throw new \RuntimeException('Cannot seek a NoSeekStream');
|
13 |
{
|
14 |
use StreamDecoratorTrait;
|
15 |
|
16 |
+
/** @var StreamInterface */
|
17 |
+
private $stream;
|
18 |
+
|
19 |
public function seek($offset, $whence = SEEK_SET): void
|
20 |
{
|
21 |
throw new \RuntimeException('Cannot seek a NoSeekStream');
|
src/vendor/guzzlehttp/psr7/src/UriComparator.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
declare(strict_types=1);
|
4 |
+
|
5 |
+
namespace GuzzleHttp\Psr7;
|
6 |
+
|
7 |
+
use Psr\Http\Message\UriInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Provides methods to determine if a modified URL should be considered cross-origin.
|
11 |
+
*
|
12 |
+
* @author Graham Campbell
|
13 |
+
*/
|
14 |
+
final class UriComparator
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* Determines if a modified URL should be considered cross-origin with
|
18 |
+
* respect to an original URL.
|
19 |
+
*/
|
20 |
+
public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool
|
21 |
+
{
|
22 |
+
if (\strcasecmp($original->getHost(), $modified->getHost()) !== 0) {
|
23 |
+
return true;
|
24 |
+
}
|
25 |
+
|
26 |
+
if ($original->getScheme() !== $modified->getScheme()) {
|
27 |
+
return true;
|
28 |
+
}
|
29 |
+
|
30 |
+
if (self::computePort($original) !== self::computePort($modified)) {
|
31 |
+
return true;
|
32 |
+
}
|
33 |
+
|
34 |
+
return false;
|
35 |
+
}
|
36 |
+
|
37 |
+
private static function computePort(UriInterface $uri): int
|
38 |
+
{
|
39 |
+
$port = $uri->getPort();
|
40 |
+
|
41 |
+
if (null !== $port) {
|
42 |
+
return $port;
|
43 |
+
}
|
44 |
+
|
45 |
+
return 'https' === $uri->getScheme() ? 443 : 80;
|
46 |
+
}
|
47 |
+
|
48 |
+
private function __construct()
|
49 |
+
{
|
50 |
+
// cannot be instantiated
|
51 |
+
}
|
52 |
+
}
|
src/vendor/http-interop/http-factory-guzzle/.github/workflows/ci.yaml
DELETED
@@ -1,60 +0,0 @@
|
|
1 |
-
name: CI
|
2 |
-
|
3 |
-
on:
|
4 |
-
pull_request:
|
5 |
-
push:
|
6 |
-
branches: [ master ]
|
7 |
-
|
8 |
-
jobs:
|
9 |
-
run:
|
10 |
-
runs-on: ubuntu-18.04
|
11 |
-
strategy:
|
12 |
-
fail-fast: false
|
13 |
-
matrix:
|
14 |
-
php:
|
15 |
-
- '7.3'
|
16 |
-
- '7.4'
|
17 |
-
- '8.0'
|
18 |
-
minimum_versions: [false]
|
19 |
-
coverage: ['none']
|
20 |
-
include:
|
21 |
-
- description: 'Minimum version'
|
22 |
-
php: '7.3'
|
23 |
-
minimum_versions: true
|
24 |
-
- description: 'Log Code Coverage'
|
25 |
-
php: '8.0'
|
26 |
-
coverage: 'xdebug'
|
27 |
-
|
28 |
-
name: PHP ${{ matrix.php }} ${{ matrix.description }}
|
29 |
-
steps:
|
30 |
-
- name: Checkout
|
31 |
-
uses: actions/checkout@v2
|
32 |
-
|
33 |
-
- uses: actions/cache@v2
|
34 |
-
with:
|
35 |
-
path: ~/.composer/cache/files
|
36 |
-
key: ${{ matrix.php }}
|
37 |
-
|
38 |
-
- name: Setup PHP
|
39 |
-
uses: shivammathur/setup-php@v2
|
40 |
-
with:
|
41 |
-
php-version: ${{ matrix.php }}
|
42 |
-
coverage: ${{ matrix.coverage }}
|
43 |
-
|
44 |
-
- name: Install dependencies
|
45 |
-
run: composer install
|
46 |
-
if: matrix.minimum_versions == false
|
47 |
-
|
48 |
-
- name: Install dependencies (lowest versions)
|
49 |
-
run: composer update --no-interaction --prefer-lowest
|
50 |
-
if: matrix.minimum_versions == true
|
51 |
-
|
52 |
-
- name: Run PHPUnit tests
|
53 |
-
run: vendor/bin/phpunit
|
54 |
-
|
55 |
-
- name: Upload code coverage
|
56 |
-
uses: codecov/codecov-action@v2
|
57 |
-
if: matrix.coverage == 'xdebug'
|
58 |
-
with:
|
59 |
-
file: './build/logs/clover.xml'
|
60 |
-
fail_ci_if_error: true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/LICENSE
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
The MIT License (MIT)
|
2 |
-
|
3 |
-
Copyright (c) 2016 Woody Gilk
|
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
|
7 |
-
in the Software without restriction, including without limitation the rights
|
8 |
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
-
copies of the Software, and to permit persons to whom the Software is
|
10 |
-
furnished to do so, subject to the following conditions:
|
11 |
-
|
12 |
-
The above copyright notice and this permission notice shall be included in all
|
13 |
-
copies or substantial portions of the Software.
|
14 |
-
|
15 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
-
SOFTWARE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/README.md
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
# HTTP Factory for Guzzle
|
2 |
-
|
3 |
-
HTTP factory implemented for [Guzzle](https://github.com/guzzle/psr7).
|
4 |
-
|
5 |
-
**NOTE:** `guzzlehttp/psr7` includes an HTTP factory implementation starting with
|
6 |
-
version 2.0. Please use the official factory if your project can use
|
7 |
-
`"guzzlehttp/psr7": "^2.0"`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/composer.json
DELETED
@@ -1,37 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "http-interop/http-factory-guzzle",
|
3 |
-
"description": "An HTTP Factory using Guzzle PSR7",
|
4 |
-
"keywords": [
|
5 |
-
"psr-7",
|
6 |
-
"psr-17",
|
7 |
-
"http",
|
8 |
-
"factory"
|
9 |
-
],
|
10 |
-
"license": "MIT",
|
11 |
-
"authors": [
|
12 |
-
{
|
13 |
-
"name": "PHP-FIG",
|
14 |
-
"homepage": "http://www.php-fig.org/"
|
15 |
-
}
|
16 |
-
],
|
17 |
-
"provide": {
|
18 |
-
"psr/http-factory-implementation": "^1.0"
|
19 |
-
},
|
20 |
-
"require": {
|
21 |
-
"php": ">=7.3",
|
22 |
-
"psr/http-factory": "^1.0",
|
23 |
-
"guzzlehttp/psr7": "^1.7||^2.0"
|
24 |
-
},
|
25 |
-
"require-dev": {
|
26 |
-
"http-interop/http-factory-tests": "^0.9",
|
27 |
-
"phpunit/phpunit": "^9.5"
|
28 |
-
},
|
29 |
-
"autoload": {
|
30 |
-
"psr-4": {
|
31 |
-
"Http\\Factory\\Guzzle\\": "src/"
|
32 |
-
}
|
33 |
-
},
|
34 |
-
"suggest": {
|
35 |
-
"guzzlehttp/psr7": "Includes an HTTP factory starting in version 2.0"
|
36 |
-
}
|
37 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/src/RequestFactory.php
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Http\Factory\Guzzle;
|
4 |
-
|
5 |
-
use GuzzleHttp\Psr7\Request;
|
6 |
-
use Psr\Http\Message\RequestFactoryInterface;
|
7 |
-
use Psr\Http\Message\RequestInterface;
|
8 |
-
|
9 |
-
class RequestFactory implements RequestFactoryInterface
|
10 |
-
{
|
11 |
-
public function createRequest(string $method, $uri): RequestInterface
|
12 |
-
{
|
13 |
-
return new Request($method, $uri);
|
14 |
-
}
|
15 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/src/ResponseFactory.php
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Http\Factory\Guzzle;
|
4 |
-
|
5 |
-
use GuzzleHttp\Psr7\Response;
|
6 |
-
use Psr\Http\Message\ResponseFactoryInterface;
|
7 |
-
use Psr\Http\Message\ResponseInterface;
|
8 |
-
|
9 |
-
class ResponseFactory implements ResponseFactoryInterface
|
10 |
-
{
|
11 |
-
public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
|
12 |
-
{
|
13 |
-
return new Response($code, [], null, '1.1', $reasonPhrase);
|
14 |
-
}
|
15 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/src/ServerRequestFactory.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Http\Factory\Guzzle;
|
4 |
-
|
5 |
-
use GuzzleHttp\Psr7\ServerRequest;
|
6 |
-
use Psr\Http\Message\ServerRequestFactoryInterface;
|
7 |
-
use Psr\Http\Message\ServerRequestInterface;
|
8 |
-
|
9 |
-
class ServerRequestFactory implements ServerRequestFactoryInterface
|
10 |
-
{
|
11 |
-
public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
|
12 |
-
{
|
13 |
-
|
14 |
-
if (empty($method)) {
|
15 |
-
if (!empty($serverParams['REQUEST_METHOD'])) {
|
16 |
-
$method = $serverParams['REQUEST_METHOD'];
|
17 |
-
} else {
|
18 |
-
throw new \InvalidArgumentException('Cannot determine HTTP method');
|
19 |
-
}
|
20 |
-
}
|
21 |
-
|
22 |
-
return new ServerRequest($method, $uri, [], null, '1.1', $serverParams);
|
23 |
-
}
|
24 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/src/StreamFactory.php
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Http\Factory\Guzzle;
|
4 |
-
|
5 |
-
use GuzzleHttp\Psr7\Stream;
|
6 |
-
use GuzzleHttp\Psr7\Utils;
|
7 |
-
use Psr\Http\Message\StreamFactoryInterface;
|
8 |
-
use Psr\Http\Message\StreamInterface;
|
9 |
-
|
10 |
-
class StreamFactory implements StreamFactoryInterface
|
11 |
-
{
|
12 |
-
public function createStream(string $content = ''): StreamInterface
|
13 |
-
{
|
14 |
-
return Utils::streamFor($content);
|
15 |
-
}
|
16 |
-
|
17 |
-
public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface
|
18 |
-
{
|
19 |
-
return $this->createStreamFromResource(Utils::tryFopen($file, $mode));
|
20 |
-
}
|
21 |
-
|
22 |
-
public function createStreamFromResource($resource): StreamInterface
|
23 |
-
{
|
24 |
-
return new Stream($resource);
|
25 |
-
}
|
26 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/src/UploadedFileFactory.php
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Http\Factory\Guzzle;
|
4 |
-
|
5 |
-
use GuzzleHttp\Psr7\UploadedFile;
|
6 |
-
use Psr\Http\Message\UploadedFileFactoryInterface;
|
7 |
-
use Psr\Http\Message\StreamInterface;
|
8 |
-
use Psr\Http\Message\UploadedFileInterface;
|
9 |
-
|
10 |
-
class UploadedFileFactory implements UploadedFileFactoryInterface
|
11 |
-
{
|
12 |
-
public function createUploadedFile(
|
13 |
-
StreamInterface $stream,
|
14 |
-
int $size = null,
|
15 |
-
int $error = \UPLOAD_ERR_OK,
|
16 |
-
string $clientFilename = null,
|
17 |
-
string $clientMediaType = null
|
18 |
-
): UploadedFileInterface {
|
19 |
-
if ($size === null) {
|
20 |
-
$size = $stream->getSize();
|
21 |
-
}
|
22 |
-
|
23 |
-
return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType);
|
24 |
-
}
|
25 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/http-interop/http-factory-guzzle/src/UriFactory.php
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Http\Factory\Guzzle;
|
4 |
-
|
5 |
-
use GuzzleHttp\Psr7\Uri;
|
6 |
-
use Psr\Http\Message\UriFactoryInterface;
|
7 |
-
use Psr\Http\Message\UriInterface;
|
8 |
-
|
9 |
-
class UriFactory implements UriFactoryInterface
|
10 |
-
{
|
11 |
-
public function createUri(string $uri = ''): UriInterface
|
12 |
-
{
|
13 |
-
return new Uri($uri);
|
14 |
-
}
|
15 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/php-http/curl-client/.github/workflows/Build-Test.yml
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Tests
|
2 |
+
|
3 |
+
# Run this workflow every time a new commit pushed to your repository
|
4 |
+
on:
|
5 |
+
push:
|
6 |
+
|
7 |
+
jobs:
|
8 |
+
tests:
|
9 |
+
if: "! contains(toJSON(github.event.commits.*.msg), 'skip') && ! contains(toJSON(github.event.commits.*.msg), 'ci')" #skip ci...
|
10 |
+
runs-on: ${{ matrix.operating-system }}
|
11 |
+
|
12 |
+
strategy:
|
13 |
+
fail-fast: false
|
14 |
+
matrix:
|
15 |
+
operating-system: [ubuntu-20.04]
|
16 |
+
php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1']
|
17 |
+
include:
|
18 |
+
- operating-system: ubuntu-16.04
|
19 |
+
php-versions: '7.1'
|
20 |
+
COMPOSER_FLAGS: '--prefer-stable --prefer-lowest'
|
21 |
+
PHPUNIT_FLAGS: '--coverage-clover build/coverage.xml'
|
22 |
+
|
23 |
+
name: PHP ${{ matrix.php-versions }} - ${{ matrix.operating-system }}
|
24 |
+
|
25 |
+
env:
|
26 |
+
extensions: curl json libxml dom
|
27 |
+
key: cache-v1 # can be any string, change to clear the extension cache.
|
28 |
+
|
29 |
+
steps:
|
30 |
+
# Checks out a copy of your repository on the ubuntu machine
|
31 |
+
- name: Checkout code
|
32 |
+
uses: actions/checkout@v2
|
33 |
+
|
34 |
+
- name: Setup cache environment
|
35 |
+
id: extcache
|
36 |
+
uses: shivammathur/cache-extensions@v1
|
37 |
+
with:
|
38 |
+
php-version: ${{ matrix.php-versions }}
|
39 |
+
extensions: ${{ env.extensions }}
|
40 |
+
key: ${{ env.key }}
|
41 |
+
|
42 |
+
- name: Cache PHP Extensions
|
43 |
+
uses: actions/cache@v2
|
44 |
+
with:
|
45 |
+
path: ${{ steps.extcache.outputs.dir }}
|
46 |
+
key: ${{ steps.extcache.outputs.key }}
|
47 |
+
restore-keys: ${{ steps.extcache.outputs.key }}
|
48 |
+
|
49 |
+
- name: Cache Composer Dependencies
|
50 |
+
uses: actions/cache@v1
|
51 |
+
with:
|
52 |
+
path: ~/.composer/cache/files
|
53 |
+
key: dependencies-composer-${{ hashFiles('composer.json') }}
|
54 |
+
|
55 |
+
- name: Setup PHP Action
|
56 |
+
uses: shivammathur/setup-php@2.8.0
|
57 |
+
with:
|
58 |
+
php-version: ${{ matrix.php-versions }}
|
59 |
+
extensions: ${{ env.extensions }}
|
60 |
+
coverage: xdebug
|
61 |
+
tools: pecl, composer
|
62 |
+
|
63 |
+
- name: Get composer cache directory
|
64 |
+
id: composer-cache
|
65 |
+
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
66 |
+
|
67 |
+
- name: Cache dependencies
|
68 |
+
uses: actions/cache@v2
|
69 |
+
with:
|
70 |
+
path: ${{ steps.composer-cache.outputs.dir }}
|
71 |
+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
72 |
+
restore-keys: ${{ runner.os }}-composer-
|
73 |
+
|
74 |
+
- name: Install Composer dependencies
|
75 |
+
run: composer update ${{ matrix.COMPOSER_FLAGS }} --no-interaction
|
76 |
+
|
77 |
+
- name: boot test server
|
78 |
+
run: vendor/bin/http_test_server > /dev/null 2>&1 &
|
79 |
+
|
80 |
+
- name: Run tests
|
81 |
+
run: composer test
|
src/vendor/php-http/curl-client/.php_cs
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return Symfony\CS\Config\Config::create()
|
4 |
+
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
|
5 |
+
->fixers([])
|
6 |
+
->finder(
|
7 |
+
Symfony\CS\Finder\DefaultFinder::create()->in(__DIR__ . '/src')
|
8 |
+
)
|
9 |
+
;
|
src/vendor/php-http/curl-client/CHANGELOG.md
ADDED
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Change Log
|
2 |
+
|
3 |
+
All notable changes to this project will be documented in this file.
|
4 |
+
|
5 |
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6 |
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7 |
+
|
8 |
+
## 2.2.1 - 2021-12-10
|
9 |
+
|
10 |
+
### Added
|
11 |
+
|
12 |
+
- Symfony 6 support
|
13 |
+
- Tested with PHP 8.1
|
14 |
+
|
15 |
+
## 2.2.0 - 2020-12-14
|
16 |
+
|
17 |
+
### Added
|
18 |
+
|
19 |
+
- PHP 8.0 support
|
20 |
+
|
21 |
+
## 2.1.0 - 2019-12-27
|
22 |
+
|
23 |
+
### Added
|
24 |
+
|
25 |
+
- Symfony 5 support
|
26 |
+
|
27 |
+
## 2.0.0 - 2019-03-05
|
28 |
+
|
29 |
+
### Removed
|
30 |
+
|
31 |
+
- HHVM support removed.
|
32 |
+
|
33 |
+
### Changed
|
34 |
+
|
35 |
+
- Minimal PHP version changed to 7.1.
|
36 |
+
- `Client::__construct` now expects PSR-17 factories instead of HTTPlug ones.
|
37 |
+
|
38 |
+
### Added
|
39 |
+
|
40 |
+
- #41: Support [PSR-17](https://www.php-fig.org/psr/psr-17/) and
|
41 |
+
[PSR-18](https://www.php-fig.org/psr/psr-18/).
|
42 |
+
|
43 |
+
|
44 |
+
## 1.7.1 - 2018-03-26
|
45 |
+
|
46 |
+
### Fixed
|
47 |
+
|
48 |
+
- #36: Failure evaluating code: is_resource($handle) (string assertions are deprecated in PHP 7.2)
|
49 |
+
|
50 |
+
|
51 |
+
## 1.7 - 2017-02-09
|
52 |
+
|
53 |
+
### Changed
|
54 |
+
|
55 |
+
- #30: Make sure we rewind streams
|
56 |
+
|
57 |
+
## 1.6.2 - 2017-01-02
|
58 |
+
|
59 |
+
### Fixed
|
60 |
+
|
61 |
+
- #29: Request not using CURLOPT_POSTFIELDS have content-length set to
|
62 |
+
|
63 |
+
### Changed
|
64 |
+
|
65 |
+
- Use binary mode to create response body stream.
|
66 |
+
|
67 |
+
|
68 |
+
## 1.6.1 - 2016-11-11
|
69 |
+
|
70 |
+
### Fixed
|
71 |
+
|
72 |
+
- #27: ErrorPlugin and sendAsyncRequest() incompatibility
|
73 |
+
|
74 |
+
|
75 |
+
## 1.6 - 2016-09-12
|
76 |
+
|
77 |
+
### Changed
|
78 |
+
|
79 |
+
- `Client::sendRequest` now throws `Http\Client\Exception\NetworkException` on network errors.
|
80 |
+
- `\UnexpectedValueException` replaced with `Http\Client\Exception\RequestException` in
|
81 |
+
`Client::sendRequest` and `Client::sendAsyncRequest`
|
82 |
+
|
83 |
+
|
84 |
+
## 1.5.1 - 2016-08-29
|
85 |
+
|
86 |
+
### Fixed
|
87 |
+
|
88 |
+
- #26: Combining CurlClient with StopwatchPlugin causes Promise onRejected handler to never be
|
89 |
+
invoked.
|
90 |
+
|
91 |
+
|
92 |
+
## 1.5 - 2016-08-03
|
93 |
+
|
94 |
+
### Changed
|
95 |
+
|
96 |
+
- Request body can be send with any method except GET, HEAD and TRACE.
|
97 |
+
- #25: Make discovery a hard dependency.
|
98 |
+
|
99 |
+
|
100 |
+
## 1.4.2 - 2016-06-14
|
101 |
+
|
102 |
+
### Added
|
103 |
+
|
104 |
+
- #23: "php-http/async-client-implementation" added to "provide" section.
|
105 |
+
|
106 |
+
|
107 |
+
## 1.4.1 - 2016-05-30
|
108 |
+
|
109 |
+
### Fixed
|
110 |
+
|
111 |
+
- #22: Cannot create the client using `HttpClientDiscovery`.
|
112 |
+
|
113 |
+
|
114 |
+
## 1.4 - 2016-03-30
|
115 |
+
|
116 |
+
### Changed
|
117 |
+
|
118 |
+
- #20: Minimize memory usage when reading large response body.
|
119 |
+
|
120 |
+
|
121 |
+
## 1.3 - 2016-03-14
|
122 |
+
|
123 |
+
### Fixed
|
124 |
+
|
125 |
+
- #18: Invalid "Expect" header.
|
126 |
+
|
127 |
+
### Removed
|
128 |
+
|
129 |
+
- #13: Remove HeaderParser.
|
130 |
+
|
131 |
+
|
132 |
+
## 1.2 - 2016-03-09
|
133 |
+
|
134 |
+
### Added
|
135 |
+
|
136 |
+
- #16: Make sure discovery can find the curl client
|
137 |
+
|
138 |
+
### Fixed
|
139 |
+
|
140 |
+
- #15: "Out of memory" sending large files.
|
141 |
+
|
142 |
+
|
143 |
+
## 1.1.0 - 2016-01-29
|
144 |
+
|
145 |
+
### Changed
|
146 |
+
|
147 |
+
- Switch to php-http/message 1.0.
|
148 |
+
|
149 |
+
|
150 |
+
## 1.0.0 - 2016-01-28
|
151 |
+
|
152 |
+
First stable release.
|
153 |
+
|
154 |
+
|
155 |
+
## 0.7.0 - 2016-01-26
|
156 |
+
|
157 |
+
### Changed
|
158 |
+
|
159 |
+
- Migrate from `php-http/discovery` and `php-http/utils` to `php-http/message`.
|
160 |
+
|
161 |
+
## 0.6.0 - 2016-01-12
|
162 |
+
|
163 |
+
### Changed
|
164 |
+
|
165 |
+
- Root namespace changed from `Http\Curl` to `Http\Client\Curl`.
|
166 |
+
- Main client class name renamed from `CurlHttpClient` to `Client`.
|
167 |
+
- Minimum required [php-http/discovery](https://packagist.org/packages/php-http/discovery)
|
168 |
+
version changed to 0.5.
|
169 |
+
|
170 |
+
|
171 |
+
## 0.5.0 - 2015-12-18
|
172 |
+
|
173 |
+
### Changed
|
174 |
+
|
175 |
+
- Compatibility with php-http/httplug 1.0 beta
|
176 |
+
- Switch to php-http/discovery 0.4
|
177 |
+
|
178 |
+
|
179 |
+
## 0.4.0 - 2015-12-16
|
180 |
+
|
181 |
+
### Changed
|
182 |
+
|
183 |
+
- Switch to php-http/message-factory 1.0
|
184 |
+
|
185 |
+
|
186 |
+
## 0.3.1 - 2015-12-14
|
187 |
+
|
188 |
+
### Changed
|
189 |
+
|
190 |
+
- Requirements fixed.
|
191 |
+
|
192 |
+
|
193 |
+
## 0.3.0 - 2015-11-24
|
194 |
+
|
195 |
+
### Changed
|
196 |
+
|
197 |
+
- Use cURL constants as options keys.
|
198 |
+
|
199 |
+
|
200 |
+
## 0.2.0 - 2015-11-17
|
201 |
+
|
202 |
+
### Added
|
203 |
+
|
204 |
+
- HttpAsyncClient support.
|
205 |
+
|
206 |
+
|
207 |
+
## 0.1.0 - 2015-11-11
|
208 |
+
|
209 |
+
### Added
|
210 |
+
|
211 |
+
- Initial release
|
src/vendor/{symfony/service-contracts → php-http/curl-client}/LICENSE
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
Copyright (c)
|
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
|
1 |
+
Copyright (c) 2015 PHP HTTP Team <team@php-http.org>
|
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
|
src/vendor/php-http/curl-client/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Curl client for PHP HTTP
|
2 |
+
|
3 |
+
[![Latest Version](https://img.shields.io/github/release/php-http/curl-client.svg?style=flat-square)](https://github.com/php-http/curl-client/releases)
|
4 |
+
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
|
5 |
+
[![Build Status](https://img.shields.io/github/workflow/status/php-http/curl-client/Tests.svg?style=flat-square)](https://github.com/php-http/curl-client/actions?query=workflow%3ATests)
|
6 |
+
[![Total Downloads](https://img.shields.io/packagist/dt/php-http/curl-client.svg?style=flat-square)](https://packagist.org/packages/php-http/curl-client)
|
7 |
+
|
8 |
+
The cURL client use the cURL PHP extension which must be activated in your `php.ini`.
|
9 |
+
|
10 |
+
|
11 |
+
## Install
|
12 |
+
|
13 |
+
Via Composer
|
14 |
+
|
15 |
+
``` bash
|
16 |
+
$ composer require php-http/curl-client
|
17 |
+
```
|
18 |
+
|
19 |
+
## Documentation
|
20 |
+
|
21 |
+
Please see the [official documentation](http://docs.php-http.org/en/latest/clients/curl-client.html).
|
22 |
+
|
23 |
+
## Testing
|
24 |
+
|
25 |
+
``` bash
|
26 |
+
$ composer test
|
27 |
+
```
|
28 |
+
|
29 |
+
## Contributing
|
30 |
+
|
31 |
+
Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details.
|
32 |
+
|
33 |
+
|
34 |
+
## Security
|
35 |
+
|
36 |
+
If you discover any security related issues, please contact us at
|
37 |
+
[security@php-http.org](mailto:security@php-http.org).
|
38 |
+
|
39 |
+
|
40 |
+
## License
|
41 |
+
|
42 |
+
The MIT License (MIT). Please see [License File](LICENSE) for more information.
|
src/vendor/php-http/curl-client/composer.json
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "php-http/curl-client",
|
3 |
+
"description": "PSR-18 and HTTPlug Async client with cURL",
|
4 |
+
"license": "MIT",
|
5 |
+
"keywords": [
|
6 |
+
"curl",
|
7 |
+
"http",
|
8 |
+
"psr-18"
|
9 |
+
],
|
10 |
+
"homepage": "http://php-http.org",
|
11 |
+
"authors": [{
|
12 |
+
"name": "Михаил Красильников",
|
13 |
+
"email": "m.krasilnikov@yandex.ru"
|
14 |
+
}],
|
15 |
+
"prefer-stable": true,
|
16 |
+
"minimum-stability": "dev",
|
17 |
+
"require": {
|
18 |
+
"php": "^7.1 || ^8.0",
|
19 |
+
"ext-curl": "*",
|
20 |
+
"php-http/discovery": "^1.6",
|
21 |
+
"php-http/httplug": "^2.0",
|
22 |
+
"php-http/message": "^1.2",
|
23 |
+
"psr/http-client": "^1.0",
|
24 |
+
"psr/http-factory": "^1.0",
|
25 |
+
"symfony/options-resolver": "^3.4 || ^4.0 || ^5.0 || ^6.0"
|
26 |
+
},
|
27 |
+
"require-dev": {
|
28 |
+
"guzzlehttp/psr7": "^1.0",
|
29 |
+
"php-http/client-integration-tests": "^3.0",
|
30 |
+
"phpunit/phpunit": "^7.5 || ^9.4",
|
31 |
+
"laminas/laminas-diactoros": "^2.0"
|
32 |
+
},
|
33 |
+
"autoload": {
|
34 |
+
"psr-4": {
|
35 |
+
"Http\\Client\\Curl\\": "src/"
|
36 |
+
}
|
37 |
+
},
|
38 |
+
"autoload-dev": {
|
39 |
+
"psr-4": {
|
40 |
+
"Http\\Client\\Curl\\Tests\\": "tests/"
|
41 |
+
}
|
42 |
+
},
|
43 |
+
"provide": {
|
44 |
+
"php-http/client-implementation": "1.0",
|
45 |
+
"php-http/async-client-implementation": "1.0",
|
46 |
+
"psr/http-client-implementation": "1.0"
|
47 |
+
},
|
48 |
+
"scripts": {
|
49 |
+
"test": "vendor/bin/phpunit",
|
50 |
+
"test-ci": "vendor/bin/phpunit --coverage-clover build/coverage.xml"
|
51 |
+
},
|
52 |
+
"extra": {
|
53 |
+
"branch-alias": {
|
54 |
+
"dev-master": "2.x-dev"
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
src/vendor/php-http/curl-client/puli.json
ADDED
@@ -0,0 +1,242 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"version": "1.0",
|
3 |
+
"name": "php-http/curl-client",
|
4 |
+
"bindings": {
|
5 |
+
"98239b8b-103b-4f47-94c7-4cba49a05a1f": {
|
6 |
+
"_class": "Puli\\Discovery\\Binding\\ClassBinding",
|
7 |
+
"class": "Http\\Client\\Curl\\Client",
|
8 |
+
"type": "Http\\Client\\HttpAsyncClient"
|
9 |
+
},
|
10 |
+
"a6a79968-2aa5-427c-bbe1-a581d9a48321": {
|
11 |
+
"_class": "Puli\\Discovery\\Binding\\ClassBinding",
|
12 |
+
"class": "Http\\Client\\Curl\\Client",
|
13 |
+
"type": "Http\\Client\\HttpClient"
|
14 |
+
}
|
15 |
+
},
|
16 |
+
"config": {
|
17 |
+
"bootstrap-file": "vendor/autoload.php"
|
18 |
+
},
|
19 |
+
"packages": {
|
20 |
+
"clue/stream-filter": {
|
21 |
+
"install-path": "vendor/clue/stream-filter",
|
22 |
+
"installer": "composer",
|
23 |
+
"env": "dev"
|
24 |
+
},
|
25 |
+
"doctrine/instantiator": {
|
26 |
+
"install-path": "vendor/doctrine/instantiator",
|
27 |
+
"installer": "composer",
|
28 |
+
"env": "dev"
|
29 |
+
},
|
30 |
+
"guzzlehttp/psr7": {
|
31 |
+
"install-path": "vendor/guzzlehttp/psr7",
|
32 |
+
"installer": "composer",
|
33 |
+
"env": "dev"
|
34 |
+
},
|
35 |
+
"justinrainbow/json-schema": {
|
36 |
+
"install-path": "vendor/justinrainbow/json-schema",
|
37 |
+
"installer": "composer",
|
38 |
+
"env": "dev"
|
39 |
+
},
|
40 |
+
"paragonie/random_compat": {
|
41 |
+
"install-path": "vendor/paragonie/random_compat",
|
42 |
+
"installer": "composer",
|
43 |
+
"env": "dev"
|
44 |
+
},
|
45 |
+
"php-http/adapter-integration-tests": {
|
46 |
+
"install-path": "vendor/php-http/adapter-integration-tests",
|
47 |
+
"installer": "composer",
|
48 |
+
"env": "dev"
|
49 |
+
},
|
50 |
+
"php-http/discovery": {
|
51 |
+
"install-path": "vendor/php-http/discovery",
|
52 |
+
"installer": "composer",
|
53 |
+
"env": "dev"
|
54 |
+
},
|
55 |
+
"php-http/httplug": {
|
56 |
+
"install-path": "vendor/php-http/httplug",
|
57 |
+
"installer": "composer"
|
58 |
+
},
|
59 |
+
"php-http/message": {
|
60 |
+
"install-path": "vendor/php-http/message",
|
61 |
+
"installer": "composer",
|
62 |
+
"env": "dev"
|
63 |
+
},
|
64 |
+
"php-http/message-factory": {
|
65 |
+
"install-path": "vendor/php-http/message-factory",
|
66 |
+
"installer": "composer"
|
67 |
+
},
|
68 |
+
"php-http/promise": {
|
69 |
+
"install-path": "vendor/php-http/promise",
|
70 |
+
"installer": "composer"
|
71 |
+
},
|
72 |
+
"phpdocumentor/reflection-docblock": {
|
73 |
+
"install-path": "vendor/phpdocumentor/reflection-docblock",
|
74 |
+
"installer": "composer",
|
75 |
+
"env": "dev"
|
76 |
+
},
|
77 |
+
"phpspec/prophecy": {
|
78 |
+
"install-path": "vendor/phpspec/prophecy",
|
79 |
+
"installer": "composer",
|
80 |
+
"env": "dev"
|
81 |
+
},
|
82 |
+
"phpunit/php-code-coverage": {
|
83 |
+
"install-path": "vendor/phpunit/php-code-coverage",
|
84 |
+
"installer": "composer",
|
85 |
+
"env": "dev"
|
86 |
+
},
|
87 |
+
"phpunit/php-file-iterator": {
|
88 |
+
"install-path": "vendor/phpunit/php-file-iterator",
|
89 |
+
"installer": "composer",
|
90 |
+
"env": "dev"
|
91 |
+
},
|
92 |
+
"phpunit/php-text-template": {
|
93 |
+
"install-path": "vendor/phpunit/php-text-template",
|
94 |
+
"installer": "composer",
|
95 |
+
"env": "dev"
|
96 |
+
},
|
97 |
+
"phpunit/php-timer": {
|
98 |
+
"install-path": "vendor/phpunit/php-timer",
|
99 |
+
"installer": "composer",
|
100 |
+
"env": "dev"
|
101 |
+
},
|
102 |
+
"phpunit/php-token-stream": {
|
103 |
+
"install-path": "vendor/phpunit/php-token-stream",
|
104 |
+
"installer": "composer",
|
105 |
+
"env": "dev"
|
106 |
+
},
|
107 |
+
"phpunit/phpunit": {
|
108 |
+
"install-path": "vendor/phpunit/phpunit",
|
109 |
+
"installer": "composer",
|
110 |
+
"env": "dev"
|
111 |
+
},
|
112 |
+
"phpunit/phpunit-mock-objects": {
|
113 |
+
"install-path": "vendor/phpunit/phpunit-mock-objects",
|
114 |
+
"installer": "composer",
|
115 |
+
"env": "dev"
|
116 |
+
},
|
117 |
+
"psr/http-message": {
|
118 |
+
"install-path": "vendor/psr/http-message",
|
119 |
+
"installer": "composer"
|
120 |
+
},
|
121 |
+
"psr/log": {
|
122 |
+
"install-path": "vendor/psr/log",
|
123 |
+
"installer": "composer",
|
124 |
+
"env": "dev"
|
125 |
+
},
|
126 |
+
"puli/composer-plugin": {
|
127 |
+
"install-path": "vendor/puli/composer-plugin",
|
128 |
+
"installer": "composer",
|
129 |
+
"env": "dev"
|
130 |
+
},
|
131 |
+
"puli/discovery": {
|
132 |
+
"install-path": "vendor/puli/discovery",
|
133 |
+
"installer": "composer",
|
134 |
+
"env": "dev"
|
135 |
+
},
|
136 |
+
"puli/repository": {
|
137 |
+
"install-path": "vendor/puli/repository",
|
138 |
+
"installer": "composer",
|
139 |
+
"env": "dev"
|
140 |
+
},
|
141 |
+
"puli/url-generator": {
|
142 |
+
"install-path": "vendor/puli/url-generator",
|
143 |
+
"installer": "composer",
|
144 |
+
"env": "dev"
|
145 |
+
},
|
146 |
+
"ramsey/uuid": {
|
147 |
+
"install-path": "vendor/ramsey/uuid",
|
148 |
+
"installer": "composer",
|
149 |
+
"env": "dev"
|
150 |
+
},
|
151 |
+
"sebastian/comparator": {
|
152 |
+
"install-path": "vendor/sebastian/comparator",
|
153 |
+
"installer": "composer",
|
154 |
+
"env": "dev"
|
155 |
+
},
|
156 |
+
"sebastian/diff": {
|
157 |
+
"install-path": "vendor/sebastian/diff",
|
158 |
+
"installer": "composer",
|
159 |
+
"env": "dev"
|
160 |
+
},
|
161 |
+
"sebastian/environment": {
|
162 |
+
"install-path": "vendor/sebastian/environment",
|
163 |
+
"installer": "composer",
|
164 |
+
"env": "dev"
|
165 |
+
},
|
166 |
+
"sebastian/exporter": {
|
167 |
+
"install-path": "vendor/sebastian/exporter",
|
168 |
+
"installer": "composer",
|
169 |
+
"env": "dev"
|
170 |
+
},
|
171 |
+
"sebastian/global-state": {
|
172 |
+
"install-path": "vendor/sebastian/global-state",
|
173 |
+
"installer": "composer",
|
174 |
+
"env": "dev"
|
175 |
+
},
|
176 |
+
"sebastian/recursion-context": {
|
177 |
+
"install-path": "vendor/sebastian/recursion-context",
|
178 |
+
"installer": "composer",
|
179 |
+
"env": "dev"
|
180 |
+
},
|
181 |
+
"sebastian/version": {
|
182 |
+
"install-path": "vendor/sebastian/version",
|
183 |
+
"installer": "composer",
|
184 |
+
"env": "dev"
|
185 |
+
},
|
186 |
+
"seld/jsonlint": {
|
187 |
+
"install-path": "vendor/seld/jsonlint",
|
188 |
+
"installer": "composer",
|
189 |
+
"env": "dev"
|
190 |
+
},
|
191 |
+
"symfony/filesystem": {
|
192 |
+
"install-path": "vendor/symfony/filesystem",
|
193 |
+
"installer": "composer",
|
194 |
+
"env": "dev"
|
195 |
+
},
|
196 |
+
"symfony/process": {
|
197 |
+
"install-path": "vendor/symfony/process",
|
198 |
+
"installer": "composer",
|
199 |
+
"env": "dev"
|
200 |
+
},
|
201 |
+
"symfony/yaml": {
|
202 |
+
"install-path": "vendor/symfony/yaml",
|
203 |
+
"installer": "composer",
|
204 |
+
"env": "dev"
|
205 |
+
},
|
206 |
+
"th3n3rd/cartesian-product": {
|
207 |
+
"install-path": "vendor/th3n3rd/cartesian-product",
|
208 |
+
"installer": "composer",
|
209 |
+
"env": "dev"
|
210 |
+
},
|
211 |
+
"webmozart/assert": {
|
212 |
+
"install-path": "vendor/webmozart/assert",
|
213 |
+
"installer": "composer",
|
214 |
+
"env": "dev"
|
215 |
+
},
|
216 |
+
"webmozart/expression": {
|
217 |
+
"install-path": "vendor/webmozart/expression",
|
218 |
+
"installer": "composer",
|
219 |
+
"env": "dev"
|
220 |
+
},
|
221 |
+
"webmozart/glob": {
|
222 |
+
"install-path": "vendor/webmozart/glob",
|
223 |
+
"installer": "composer",
|
224 |
+
"env": "dev"
|
225 |
+
},
|
226 |
+
"webmozart/json": {
|
227 |
+
"install-path": "vendor/webmozart/json",
|
228 |
+
"installer": "composer",
|
229 |
+
"env": "dev"
|
230 |
+
},
|
231 |
+
"webmozart/path-util": {
|
232 |
+
"install-path": "vendor/webmozart/path-util",
|
233 |
+
"installer": "composer",
|
234 |
+
"env": "dev"
|
235 |
+
},
|
236 |
+
"zendframework/zend-diactoros": {
|
237 |
+
"install-path": "vendor/zendframework/zend-diactoros",
|
238 |
+
"installer": "composer",
|
239 |
+
"env": "dev"
|
240 |
+
}
|
241 |
+
}
|
242 |
+
}
|
src/vendor/php-http/curl-client/src/Client.php
ADDED
@@ -0,0 +1,398 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
declare(strict_types=1);
|
4 |
+
|
5 |
+
namespace Http\Client\Curl;
|
6 |
+
|
7 |
+
use Http\Client\Exception;
|
8 |
+
use Http\Client\HttpAsyncClient;
|
9 |
+
use Http\Client\HttpClient;
|
10 |
+
use Http\Discovery\Exception\NotFoundException;
|
11 |
+
use Http\Discovery\Psr17FactoryDiscovery;
|
12 |
+
use Http\Promise\Promise;
|
13 |
+
use Psr\Http\Message\RequestInterface;
|
14 |
+
use Psr\Http\Message\ResponseFactoryInterface;
|
15 |
+
use Psr\Http\Message\ResponseInterface;
|
16 |
+
use Psr\Http\Message\StreamFactoryInterface;
|
17 |
+
use Symfony\Component\OptionsResolver\OptionsResolver;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* PSR-18 and HTTPlug Async client based on lib-curl.
|
21 |
+
*
|
22 |
+
* @license http://opensource.org/licenses/MIT MIT
|
23 |
+
* @author Михаил Красильников <m.krasilnikov@yandex.ru>
|
24 |
+
* @author Blake Williams <github@shabbyrobe.org>
|
25 |
+
*
|
26 |
+
* @api
|
27 |
+
*
|
28 |
+
* @since 1.0
|
29 |
+
*/
|
30 |
+
class Client implements HttpClient, HttpAsyncClient
|
31 |
+
{
|
32 |
+
/**
|
33 |
+
* cURL options.
|
34 |
+
*
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
private $curlOptions;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* PSR-17 response factory.
|
41 |
+
*
|
42 |
+
* @var ResponseFactoryInterface
|
43 |
+
*/
|
44 |
+
private $responseFactory;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* PSR-17 stream factory.
|
48 |
+
*
|
49 |
+
* @var StreamFactoryInterface
|
50 |
+
*/
|
51 |
+
private $streamFactory;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* cURL synchronous requests handle.
|
55 |
+
*
|
56 |
+
* @var resource|\CurlHandle|null
|
57 |
+
*/
|
58 |
+
private $handle;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Simultaneous requests runner.
|
62 |
+
*
|
63 |
+
* @var MultiRunner|null
|
64 |
+
*/
|
65 |
+
private $multiRunner;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Create HTTP client.
|
69 |
+
*
|
70 |
+
* @param ResponseFactoryInterface|null $responseFactory PSR-17 HTTP response factory.
|
71 |
+
* @param StreamFactoryInterface|null $streamFactory PSR-17 HTTP stream factory.
|
72 |
+
* @param array $options cURL options
|
73 |
+
* {@link http://php.net/curl_setopt}.
|
74 |
+
*
|
75 |
+
* @throws NotFoundException If factory discovery failed.
|
76 |
+
*
|
77 |
+
* @since 2.0 Accepts PSR-17 factories instead of HTTPlug ones.
|
78 |
+
*/
|
79 |
+
public function __construct(
|
80 |
+
ResponseFactoryInterface $responseFactory = null,
|
81 |
+
StreamFactoryInterface $streamFactory = null,
|
82 |
+
array $options = []
|
83 |
+
) {
|
84 |
+
$this->responseFactory = $responseFactory ?: Psr17FactoryDiscovery::findResponseFactory();
|
85 |
+
$this->streamFactory = $streamFactory ?: Psr17FactoryDiscovery::findStreamFactory();
|
86 |
+
$resolver = new OptionsResolver();
|
87 |
+
$resolver->setDefaults(
|
88 |
+
[
|
89 |
+
CURLOPT_HEADER => false,
|
90 |
+
CURLOPT_RETURNTRANSFER => false,
|
91 |
+
CURLOPT_FOLLOWLOCATION => false
|
92 |
+
]
|
93 |
+
);
|
94 |
+
|
95 |
+
// Our parsing will fail if this is set to true.
|
96 |
+
$resolver->setAllowedValues(
|
97 |
+
(string)CURLOPT_HEADER,
|
98 |
+
[false]
|
99 |
+
);
|
100 |
+
|
101 |
+
// Our parsing will fail if this is set to true.
|
102 |
+
$resolver->setAllowedValues(
|
103 |
+
(string)CURLOPT_RETURNTRANSFER,
|
104 |
+
[false]
|
105 |
+
);
|
106 |
+
|
107 |
+
// We do not know what everything curl supports and might support in the future.
|
108 |
+
// Make sure that we accept everything that is in the options.
|
109 |
+
$resolver->setDefined(array_keys($options));
|
110 |
+
|
111 |
+
$this->curlOptions = $resolver->resolve($options);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Release resources if still active.
|
116 |
+
*/
|
117 |
+
public function __destruct()
|
118 |
+
{
|
119 |
+
if (is_resource($this->handle)) {
|
120 |
+
curl_close($this->handle);
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Sends a PSR-7 request and returns a PSR-7 response.
|
126 |
+
*
|
127 |
+
* @param RequestInterface $request
|
128 |
+
*
|
129 |
+
* @return ResponseInterface
|
130 |
+
*
|
131 |
+
* @throws \InvalidArgumentException For invalid header names or values.
|
132 |
+
* @throws \RuntimeException If creating the body stream fails.
|
133 |
+
* @throws Exception\NetworkException In case of network problems.
|
134 |
+
* @throws Exception\RequestException On invalid request.
|
135 |
+
*
|
136 |
+
* @since 1.6 \UnexpectedValueException replaced with RequestException
|
137 |
+
* @since 1.6 Throw NetworkException on network errors
|
138 |
+
* @since 1.0
|
139 |
+
*/
|
140 |
+
public function sendRequest(RequestInterface $request): ResponseInterface
|
141 |
+
{
|
142 |
+
$responseBuilder = $this->createResponseBuilder();
|
143 |
+
$requestOptions = $this->prepareRequestOptions($request, $responseBuilder);
|
144 |
+
|
145 |
+
if (is_resource($this->handle)) {
|
146 |
+
curl_reset($this->handle);
|
147 |
+
} else {
|
148 |
+
$this->handle = curl_init();
|
149 |
+
}
|
150 |
+
|
151 |
+
curl_setopt_array($this->handle, $requestOptions);
|
152 |
+
curl_exec($this->handle);
|
153 |
+
|
154 |
+
$errno = curl_errno($this->handle);
|
155 |
+
switch ($errno) {
|
156 |
+
case CURLE_OK:
|
157 |
+
// All OK, no actions needed.
|
158 |
+
break;
|
159 |
+
case CURLE_COULDNT_RESOLVE_PROXY:
|
160 |
+
case CURLE_COULDNT_RESOLVE_HOST:
|
161 |
+
case CURLE_COULDNT_CONNECT:
|
162 |
+
case CURLE_OPERATION_TIMEOUTED:
|
163 |
+
case CURLE_SSL_CONNECT_ERROR:
|
164 |
+
throw new Exception\NetworkException(curl_error($this->handle), $request);
|
165 |
+
default:
|
166 |
+
throw new Exception\RequestException(curl_error($this->handle), $request);
|
167 |
+
}
|
168 |
+
|
169 |
+
$response = $responseBuilder->getResponse();
|
170 |
+
$response->getBody()->seek(0);
|
171 |
+
|
172 |
+
return $response;
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Create builder to use for building response object.
|
177 |
+
*
|
178 |
+
* @return ResponseBuilder
|
179 |
+
*/
|
180 |
+
private function createResponseBuilder(): ResponseBuilder
|
181 |
+
{
|
182 |
+
$body = $this->streamFactory->createStreamFromFile('php://temp', 'w+b');
|
183 |
+
|
184 |
+
$response = $this->responseFactory
|
185 |
+
->createResponse(200)
|
186 |
+
->withBody($body);
|
187 |
+
|
188 |
+
return new ResponseBuilder($response);
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Update cURL options for given request and hook in the response builder.
|
193 |
+
*
|
194 |
+
* @param RequestInterface $request Request on which to create options.
|
195 |
+
* @param ResponseBuilder $responseBuilder Builder to use for building response.
|
196 |
+
*
|
197 |
+
* @return array cURL options based on request.
|
198 |
+
*
|
199 |
+
* @throws \InvalidArgumentException For invalid header names or values.
|
200 |
+
* @throws \RuntimeException If can not read body.
|
201 |
+
* @throws Exception\RequestException On invalid request.
|
202 |
+
*/
|
203 |
+
private function prepareRequestOptions(
|
204 |
+
RequestInterface $request,
|
205 |
+
ResponseBuilder $responseBuilder
|
206 |
+
): array {
|
207 |
+
$curlOptions = $this->curlOptions;
|
208 |
+
|
209 |
+
try {
|
210 |
+
$curlOptions[CURLOPT_HTTP_VERSION]
|
211 |
+
= $this->getProtocolVersion($request->getProtocolVersion());
|
212 |
+
} catch (\UnexpectedValueException $e) {
|
213 |
+
throw new Exception\RequestException($e->getMessage(), $request);
|
214 |
+
}
|
215 |
+
$curlOptions[CURLOPT_URL] = (string)$request->getUri();
|
216 |
+
|
217 |
+
$curlOptions = $this->addRequestBodyOptions($request, $curlOptions);
|
218 |
+
|
219 |
+
$curlOptions[CURLOPT_HTTPHEADER] = $this->createHeaders($request, $curlOptions);
|
220 |
+
|
221 |
+
if ($request->getUri()->getUserInfo()) {
|
222 |
+
$curlOptions[CURLOPT_USERPWD] = $request->getUri()->getUserInfo();
|
223 |
+
}
|
224 |
+
|
225 |
+
$curlOptions[CURLOPT_HEADERFUNCTION] = function ($ch, $data) use ($responseBuilder) {
|
226 |
+
$str = trim($data);
|
227 |
+
if ('' !== $str) {
|
228 |
+
if (stripos($str, 'http/') === 0) {
|
229 |
+
$responseBuilder->setStatus($str)->getResponse();
|
230 |
+
} else {
|
231 |
+
$responseBuilder->addHeader($str);
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
return strlen($data);
|
236 |
+
};
|
237 |
+
|
238 |
+
$curlOptions[CURLOPT_WRITEFUNCTION] = function ($ch, $data) use ($responseBuilder) {
|
239 |
+
return $responseBuilder->getResponse()->getBody()->write($data);
|
240 |
+
};
|
241 |
+
|
242 |
+
return $curlOptions;
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* Return cURL constant for specified HTTP version.
|
247 |
+
*
|
248 |
+
* @param string $requestVersion HTTP version ("1.0", "1.1" or "2.0").
|
249 |
+
*
|
250 |
+
* @return int Respective CURL_HTTP_VERSION_x_x constant.
|
251 |
+
*
|
252 |
+
* @throws \UnexpectedValueException If unsupported version requested.
|
253 |
+
*/
|
254 |
+
private function getProtocolVersion(string $requestVersion): int
|
255 |
+
{
|
256 |
+
switch ($requestVersion) {
|
257 |
+
case '1.0':
|
258 |
+
return CURL_HTTP_VERSION_1_0;
|
259 |
+
case '1.1':
|
260 |
+
return CURL_HTTP_VERSION_1_1;
|
261 |
+
case '2.0':
|
262 |
+
if (defined('CURL_HTTP_VERSION_2_0')) {
|
263 |
+
return CURL_HTTP_VERSION_2_0;
|
264 |
+
}
|
265 |
+
throw new \UnexpectedValueException('libcurl 7.33 needed for HTTP 2.0 support');
|
266 |
+
}
|
267 |
+
|
268 |
+
return CURL_HTTP_VERSION_NONE;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Add request body related cURL options.
|
273 |
+
*
|
274 |
+
* @param RequestInterface $request Request on which to create options.
|
275 |
+
* @param array $curlOptions Options created by prepareRequestOptions().
|
276 |
+
*
|
277 |
+
* @return array cURL options based on request.
|
278 |
+
*/
|
279 |
+
private function addRequestBodyOptions(RequestInterface $request, array $curlOptions): array
|
280 |
+
{
|
281 |
+
/*
|
282 |
+
* Some HTTP methods cannot have payload:
|
283 |
+
*
|
284 |
+
* - GET — cURL will automatically change method to PUT or POST if we set CURLOPT_UPLOAD or
|
285 |
+
* CURLOPT_POSTFIELDS.
|
286 |
+
* - HEAD — cURL treats HEAD as GET request with a same restrictions.
|
287 |
+
* - TRACE — According to RFC7231: a client MUST NOT send a message body in a TRACE request.
|
288 |
+
*/
|
289 |
+
if (!in_array($request->getMethod(), ['GET', 'HEAD', 'TRACE'], true)) {
|
290 |
+
$body = $request->getBody();
|
291 |
+
$bodySize = $body->getSize();
|
292 |
+
if ($bodySize !== 0) {
|
293 |
+
if ($body->isSeekable()) {
|
294 |
+
$body->rewind();
|
295 |
+
}
|
296 |
+
|
297 |
+
// Message has non empty body.
|
298 |
+
if (null === $bodySize || $bodySize > 1024 * 1024) {
|
299 |
+
// Avoid full loading large or unknown size body into memory
|
300 |
+
$curlOptions[CURLOPT_UPLOAD] = true;
|
301 |
+
if (null !== $bodySize) {
|
302 |
+
$curlOptions[CURLOPT_INFILESIZE] = $bodySize;
|
303 |
+
}
|
304 |
+
$curlOptions[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
|
305 |
+
return $body->read($length);
|
306 |
+
};
|
307 |
+
} else {
|
308 |
+
// Small body can be loaded into memory
|
309 |
+
$curlOptions[CURLOPT_POSTFIELDS] = (string)$body;
|
310 |
+
}
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
if ($request->getMethod() === 'HEAD') {
|
315 |
+
// This will set HTTP method to "HEAD".
|
316 |
+
$curlOptions[CURLOPT_NOBODY] = true;
|
317 |
+
} elseif ($request->getMethod() !== 'GET') {
|
318 |
+
// GET is a default method. Other methods should be specified explicitly.
|
319 |
+
$curlOptions[CURLOPT_CUSTOMREQUEST] = $request->getMethod();
|
320 |
+
}
|
321 |
+
|
322 |
+
return $curlOptions;
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Create headers array for CURLOPT_HTTPHEADER.
|
327 |
+
*
|
328 |
+
* @param RequestInterface $request Request on which to create headers.
|
329 |
+
* @param array $curlOptions Options created by prepareRequestOptions().
|
330 |
+
*
|
331 |
+
* @return string[]
|
332 |
+
*/
|
333 |
+
private function createHeaders(RequestInterface $request, array $curlOptions): array
|
334 |
+
{
|
335 |
+
$curlHeaders = [];
|
336 |
+
$headers = $request->getHeaders();
|
337 |
+
foreach ($headers as $name => $values) {
|
338 |
+
$header = strtolower($name);
|
339 |
+
if ('expect' === $header) {
|
340 |
+
// curl-client does not support "Expect-Continue", so dropping "expect" headers
|
341 |
+
continue;
|
342 |
+
}
|
343 |
+
if ('content-length' === $header) {
|
344 |
+
if (array_key_exists(CURLOPT_POSTFIELDS, $curlOptions)) {
|
345 |
+
// Small body content length can be calculated here.
|
346 |
+
$values = [strlen($curlOptions[CURLOPT_POSTFIELDS])];
|
347 |
+
} elseif (!array_key_exists(CURLOPT_READFUNCTION, $curlOptions)) {
|
348 |
+
// Else if there is no body, forcing "Content-length" to 0
|
349 |
+
$values = [0];
|
350 |
+
}
|
351 |
+
}
|
352 |
+
foreach ($values as $value) {
|
353 |
+
$curlHeaders[] = $name . ': ' . $value;
|
354 |
+
}
|
355 |
+
}
|
356 |
+
/*
|
357 |
+
* curl-client does not support "Expect-Continue", but cURL adds "Expect" header by default.
|
358 |
+
* We can not suppress it, but we can set it to empty.
|
359 |
+
*/
|
360 |
+
$curlHeaders[] = 'Expect:';
|
361 |
+
|
362 |
+
return $curlHeaders;
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Sends a PSR-7 request in an asynchronous way.
|
367 |
+
*
|
368 |
+
* Exceptions related to processing the request are available from the returned Promise.
|
369 |
+
*
|
370 |
+
* @param RequestInterface $request
|
371 |
+
*
|
372 |
+
* @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception.
|
373 |
+
*
|
374 |
+
* @throws \InvalidArgumentException For invalid header names or values.
|
375 |
+
* @throws \RuntimeException If creating the body stream fails.
|
376 |
+
* @throws Exception\RequestException On invalid request.
|
377 |
+
*
|
378 |
+
* @since 1.6 \UnexpectedValueException replaced with RequestException
|
379 |
+
* @since 1.0
|
380 |
+
*/
|
381 |
+
public function sendAsyncRequest(RequestInterface $request)
|
382 |
+
{
|
383 |
+
if (!$this->multiRunner instanceof MultiRunner) {
|
384 |
+
$this->multiRunner = new MultiRunner();
|
385 |
+
}
|
386 |
+
|
387 |
+
$handle = curl_init();
|
388 |
+
$responseBuilder = $this->createResponseBuilder();
|
389 |
+
$requestOptions = $this->prepareRequestOptions($request, $responseBuilder);
|
390 |
+
curl_setopt_array($handle, $requestOptions);
|
391 |
+
|
392 |
+
$core = new PromiseCore($request, $handle, $responseBuilder);
|
393 |
+
$promise = new CurlPromise($core, $this->multiRunner);
|
394 |
+
$this->multiRunner->add($core);
|
395 |
+
|
396 |
+
return $promise;
|
397 |
+
}
|
398 |
+
}
|
src/vendor/php-http/curl-client/src/CurlPromise.php
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
declare(strict_types=1);
|
4 |
+
|
5 |
+
namespace Http\Client\Curl;
|
6 |
+
|
7 |
+
use Http\Promise\Promise;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Promise represents a response that may not be available yet, but will be resolved at some point
|
11 |
+
* in future. It acts like a proxy to the actual response.
|
12 |
+
*
|
13 |
+
* This interface is an extension of the promises/a+ specification https://promisesaplus.com/
|
14 |
+
* Value is replaced by an object where its class implement a Psr\Http\Message\RequestInterface.
|
15 |
+
* Reason is replaced by an object where its class implement a Http\Client\Exception.
|
16 |
+
*
|
17 |
+
* @license http://opensource.org/licenses/MIT MIT
|
18 |
+
* @author Михаил Красильников <m.krasilnikov@yandex.ru>
|
19 |
+
*/
|
20 |
+
class CurlPromise implements Promise
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* Shared promise core.
|
24 |
+
*
|
25 |
+
* @var PromiseCore
|
26 |
+
*/
|
27 |
+
private $core;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Requests runner.
|
31 |
+
*
|
32 |
+
* @var MultiRunner
|
33 |
+
*/
|
34 |
+
private $runner;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Create new promise.
|
38 |
+
*
|
39 |
+
* @param PromiseCore $core Shared promise core
|
40 |
+
* @param MultiRunner $runner Simultaneous requests runner
|
41 |
+
*/
|
42 |
+
public function __construct(PromiseCore $core, MultiRunner $runner)
|
43 |
+
{
|
44 |
+
$this->core = $core;
|
45 |
+
$this->runner = $runner;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Add behavior for when the promise is resolved or rejected.
|
50 |
+
*
|
51 |
+
* If you do not care about one of the cases, you can set the corresponding callable to null
|
52 |
+
* The callback will be called when the response or exception arrived and never more than once.
|
53 |
+
*
|
54 |
+
* @param callable $onFulfilled Called when a response will be available
|
55 |
+
* @param callable $onRejected Called when an error happens.
|
56 |
+
*
|
57 |
+
* You must always return the Response in the interface or throw an Exception
|
58 |
+
*
|
59 |
+
* @return Promise Always returns a new promise which is resolved with value of the executed
|
60 |
+
* callback (onFulfilled / onRejected)
|
61 |
+
*/
|
62 |
+
public function then(callable $onFulfilled = null, callable $onRejected = null)
|
63 |
+
{
|
64 |
+
if ($onFulfilled) {
|
65 |
+
$this->core->addOnFulfilled($onFulfilled);
|
66 |
+
}
|
67 |
+
if ($onRejected) {
|
68 |
+
$this->core->addOnRejected($onRejected);
|
69 |
+
}
|
70 |
+
|
71 |
+
return new self($this->core, $this->runner);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Get the state of the promise, one of PENDING, FULFILLED or REJECTED.
|
76 |
+
*
|
77 |
+
* @return string
|
78 |
+
*/
|
79 |
+
public function getState()
|
80 |
+
{
|
81 |
+
return $this->core->getState();
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Wait for the promise to be fulfilled or rejected.
|
86 |
+
*
|
87 |
+
* When this method returns, the request has been resolved and the appropriate callable has terminated.
|
88 |
+
*
|
89 |
+
* When called with the unwrap option
|
90 |
+
*
|
91 |
+
* @param bool $unwrap Whether to return resolved value / throw reason or not
|
92 |
+
*
|
93 |
+
* @return \Psr\Http\Message\ResponseInterface|null Resolved value, null if $unwrap is set to false
|
94 |
+
*
|
95 |
+
* @throws \Http\Client\Exception The rejection reason
|
96 |
+
*/
|
97 |
+
public function wait($unwrap = true)
|
98 |
+
{
|
99 |
+
$this->runner->wait($this->core);
|
100 |
+
|
101 |
+
if ($unwrap) {
|
102 |
+
if ($this->core->getState() === self::REJECTED) {
|
103 |
+
throw $this->core->getException();
|
104 |
+
}
|
105 |
+
|
106 |
+
return $this->core->getResponse();
|
107 |
+
}
|
108 |
+
|
109 |
+
return null;
|
110 |
+
}
|
111 |
+
}
|
src/vendor/php-http/curl-client/src/MultiRunner.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
declare(strict_types=1);
|
4 |
+
|
5 |
+
namespace Http\Client\Curl;
|
6 |
+
|
7 |
+
use Http\Client\Exception\RequestException;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Simultaneous requests runner.
|
11 |
+
*
|
12 |
+
* @license http://opensource.org/licenses/MIT MIT
|
13 |
+
* @author Михаил Красильников <m.krasilnikov@yandex.ru>
|
14 |
+
*/
|
15 |
+
class MultiRunner
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* cURL multi handle.
|
19 |
+
*
|
20 |
+
* @var resource|null
|
21 |
+
*/
|
22 |
+
private $multiHandle;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Awaiting cores.
|
26 |
+
*
|
27 |
+
* @var PromiseCore[]
|
28 |
+
*/
|
29 |
+
private $cores = [];
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Release resources if still active.
|
33 |
+
*/
|
34 |
+
public function __destruct()
|
35 |
+
{
|
36 |
+
if (is_resource($this->multiHandle)) {
|
37 |
+
curl_multi_close($this->multiHandle);
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Add promise to runner.
|
43 |
+
*
|
44 |
+
* @param PromiseCore $core
|
45 |
+
*/
|
46 |
+
public function add(PromiseCore $core): void
|
47 |
+
{
|
48 |
+
foreach ($this->cores as $existed) {
|
49 |
+
if ($existed === $core) {
|
50 |
+
return;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
$this->cores[] = $core;
|
55 |
+
|
56 |
+
if (null === $this->multiHandle) {
|
57 |
+
$this->multiHandle = curl_multi_init();
|
58 |
+
}
|
59 |
+
curl_multi_add_handle($this->multiHandle, $core->getHandle());
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Remove promise from runner.
|
64 |
+
*
|
65 |
+
* @param PromiseCore $core
|
66 |
+
*/
|
67 |
+
public function remove(PromiseCore $core): void
|
68 |
+
{
|
69 |
+
foreach ($this->cores as $index => $existed) {
|
70 |
+
if ($existed === $core) {
|
71 |
+
curl_multi_remove_handle($this->multiHandle, $core->getHandle());
|
72 |
+
unset($this->cores[$index]);
|
73 |
+
|
74 |
+
return;
|
75 |
+
}
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Wait for request(s) to be completed.
|
81 |
+
*
|
82 |
+
* @param PromiseCore|null $targetCore
|
83 |
+
*/
|
84 |
+
public function wait(PromiseCore $targetCore = null): void
|
85 |
+
{
|
86 |
+
do {
|
87 |
+
$status = curl_multi_exec($this->multiHandle, $active);
|
88 |
+
$info = curl_multi_info_read($this->multiHandle);
|
89 |
+
if (false !== $info) {
|
90 |
+
$core = $this->findCoreByHandle($info['handle']);
|
91 |
+
|
92 |
+
if (null === $core) {
|
93 |
+
// We have no promise for this handle. Drop it.
|
94 |
+
curl_multi_remove_handle($this->multiHandle, $info['handle']);
|
95 |
+
continue;
|
96 |
+
}
|
97 |
+
|
98 |
+
if (CURLE_OK === $info['result']) {
|
99 |
+
$core->fulfill();
|
100 |
+
} else {
|
101 |
+
$error = curl_error($core->getHandle());
|
102 |
+
$core->reject(new RequestException($error, $core->getRequest()));
|
103 |
+
}
|
104 |
+
$this->remove($core);
|
105 |
+
|
106 |
+
// This is a promise we are waited for. So exiting wait().
|
107 |
+
if ($core === $targetCore) {
|
108 |
+
return;
|
109 |
+
}
|
110 |
+
}
|
111 |
+
} while ($status === CURLM_CALL_MULTI_PERFORM || $active);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Find core by handle.
|
116 |
+
*
|
117 |
+
* @param resource $handle
|
118 |
+
*
|
119 |
+
* @return PromiseCore|null
|
120 |
+
*/
|
121 |
+
private function findCoreByHandle($handle): ?PromiseCore
|
122 |
+
{
|
123 |
+
foreach ($this->cores as $core) {
|
124 |
+
if ($core->getHandle() === $handle) {
|
125 |
+
return $core;
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
return null;
|
130 |
+
}
|
131 |
+
}
|
src/vendor/php-http/curl-client/src/PromiseCore.php
ADDED
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
declare(strict_types=1);
|
4 |
+
|
5 |
+
namespace Http\Client\Curl;
|
6 |
+
|
7 |
+
use Http\Client\Exception;
|
8 |
+
use Http\Promise\Promise;
|
9 |
+
use Psr\Http\Message\RequestInterface;
|
10 |
+
use Psr\Http\Message\ResponseInterface;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Shared promises core.
|
14 |
+
*
|
15 |
+
* @license http://opensource.org/licenses/MIT MIT
|
16 |
+
* @author Михаил Красильников <m.krasilnikov@yandex.ru>
|
17 |
+
*/
|
18 |
+
class PromiseCore
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* HTTP request.
|
22 |
+
*
|
23 |
+
* @var RequestInterface
|
24 |
+
*/
|
25 |
+
private $request;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* cURL handle.
|
29 |
+
*
|
30 |
+
* @var resource
|
31 |
+
*/
|
32 |
+
private $handle;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Response builder.
|
36 |
+
*
|
37 |
+
* @var ResponseBuilder
|
38 |
+
*/
|
39 |
+
private $responseBuilder;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Promise state.
|
43 |
+
*
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
+
private $state;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Exception.
|
50 |
+
*
|
51 |
+
* @var Exception|null
|
52 |
+
*/
|
53 |
+
private $exception = null;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Functions to call when a response will be available.
|
57 |
+
*
|
58 |
+
* @var callable[]
|
59 |
+
*/
|
60 |
+
private $onFulfilled = [];
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Functions to call when an error happens.
|
64 |
+
*
|
65 |
+
* @var callable[]
|
66 |
+
*/
|
67 |
+
private $onRejected = [];
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Create shared core.
|
71 |
+
*
|
72 |
+
* @param RequestInterface $request HTTP request.
|
73 |
+
* @param resource|\CurlHandle $handle cURL handle.
|
74 |
+
* @param ResponseBuilder $responseBuilder Response builder.
|
75 |
+
*
|
76 |
+
* @throws \InvalidArgumentException If $handle is not a cURL resource.
|
77 |
+
*/
|
78 |
+
public function __construct(
|
79 |
+
RequestInterface $request,
|
80 |
+
$handle,
|
81 |
+
ResponseBuilder $responseBuilder
|
82 |
+
) {
|
83 |
+
if (PHP_MAJOR_VERSION === 7) {
|
84 |
+
if (!is_resource($handle)) {
|
85 |
+
throw new \InvalidArgumentException(
|
86 |
+
sprintf(
|
87 |
+
'Parameter $handle expected to be a cURL resource, %s given',
|
88 |
+
gettype($handle)
|
89 |
+
)
|
90 |
+
);
|
91 |
+
} elseif (get_resource_type($handle) !== 'curl') {
|
92 |
+
throw new \InvalidArgumentException(
|
93 |
+
sprintf(
|
94 |
+
'Parameter $handle expected to be a cURL resource, %s resource given',
|
95 |
+
get_resource_type($handle)
|
96 |
+
)
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
if (PHP_MAJOR_VERSION > 7 && !$handle instanceof \CurlHandle) {
|
102 |
+
throw new \InvalidArgumentException(
|
103 |
+
sprintf(
|
104 |
+
'Parameter $handle expected to be a cURL resource, %s given',
|
105 |
+
get_debug_type($handle)
|
106 |
+
)
|
107 |
+
);
|
108 |
+
}
|
109 |
+
|
110 |
+
$this->request = $request;
|
111 |
+
$this->handle = $handle;
|
112 |
+
$this->responseBuilder = $responseBuilder;
|
113 |
+
$this->state = Promise::PENDING;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Add on fulfilled callback.
|
118 |
+
*
|
119 |
+
* @param callable $callback
|
120 |
+
*/
|
121 |
+
public function addOnFulfilled(callable $callback): void
|
122 |
+
{
|
123 |
+
if ($this->getState() === Promise::PENDING) {
|
124 |
+
$this->onFulfilled[] = $callback;
|
125 |
+
} elseif ($this->getState() === Promise::FULFILLED) {
|
126 |
+
$response = call_user_func($callback, $this->responseBuilder->getResponse());
|
127 |
+
if ($response instanceof ResponseInterface) {
|
128 |
+
$this->responseBuilder->setResponse($response);
|
129 |
+
}
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Add on rejected callback.
|
135 |
+
*
|
136 |
+
* @param callable $callback
|
137 |
+
*/
|
138 |
+
public function addOnRejected(callable $callback): void
|
139 |
+
{
|
140 |
+
if ($this->getState() === Promise::PENDING) {
|
141 |
+
$this->onRejected[] = $callback;
|
142 |
+
} elseif ($this->getState() === Promise::REJECTED) {
|
143 |
+
$this->exception = call_user_func($callback, $this->exception);
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Return cURL handle.
|
149 |
+
*
|
150 |
+
* @return resource|\CurlHandle
|
151 |
+
*/
|
152 |
+
public function getHandle()
|
153 |
+
{
|
154 |
+
return $this->handle;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Get the state of the promise, one of PENDING, FULFILLED or REJECTED.
|
159 |
+
*
|
160 |
+
* @return string
|
161 |
+
*/
|
162 |
+
public function getState(): string
|
163 |
+
{
|
164 |
+
return $this->state;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Return request.
|
169 |
+
*
|
170 |
+
* @return RequestInterface
|
171 |
+
*/
|
172 |
+
public function getRequest(): RequestInterface
|
173 |
+
{
|
174 |
+
return $this->request;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Return the value of the promise (fulfilled).
|
179 |
+
*
|
180 |
+
* @return ResponseInterface Response object only when the Promise is fulfilled
|
181 |
+
*/
|
182 |
+
public function getResponse(): ResponseInterface
|
183 |
+
{
|
184 |
+
return $this->responseBuilder->getResponse();
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Get the reason why the promise was rejected.
|
189 |
+
*
|
190 |
+
* If the exception is an instance of Http\Client\Exception\HttpException it will contain
|
191 |
+
* the response object with the status code and the http reason.
|
192 |
+
*
|
193 |
+
* @return \Throwable Exception Object only when the Promise is rejected
|
194 |
+
*
|
195 |
+
* @throws \LogicException When the promise is not rejected
|
196 |
+
*/
|
197 |
+
public function getException(): \Throwable
|
198 |
+
{
|
199 |
+
if (null === $this->exception) {
|
200 |
+
throw new \LogicException('Promise is not rejected');
|
201 |
+
}
|
202 |
+
|
203 |
+
return $this->exception;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Fulfill promise.
|
208 |
+
*/
|
209 |
+
public function fulfill(): void
|
210 |
+
{
|
211 |
+
$this->state = Promise::FULFILLED;
|
212 |
+
$response = $this->responseBuilder->getResponse();
|
213 |
+
try {
|
214 |
+
$response->getBody()->seek(0);
|
215 |
+
} catch (\RuntimeException $e) {
|
216 |
+
$exception = new Exception\TransferException($e->getMessage(), $e->getCode(), $e);
|
217 |
+
$this->reject($exception);
|
218 |
+
|
219 |
+
return;
|
220 |
+
}
|
221 |
+
|
222 |
+
while (count($this->onFulfilled) > 0) {
|
223 |
+
$callback = array_shift($this->onFulfilled);
|
224 |
+
$response = call_user_func($callback, $response);
|
225 |
+
}
|
226 |
+
|
227 |
+
if ($response instanceof ResponseInterface) {
|
228 |
+
$this->responseBuilder->setResponse($response);
|
229 |
+
}
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Reject promise.
|
234 |
+
*
|
235 |
+
* @param Exception $exception Reject reason
|
236 |
+
*/
|
237 |
+
public function reject(Exception $exception): void
|
238 |
+
{
|
239 |
+
$this->exception = $exception;
|
240 |
+
$this->state = Promise::REJECTED;
|
241 |
+
|
242 |
+
while (count($this->onRejected) > 0) {
|
243 |
+
$callback = array_shift($this->onRejected);
|
244 |
+
try {
|
245 |
+
$exception = call_user_func($callback, $this->exception);
|
246 |
+
$this->exception = $exception;
|
247 |
+
} catch (Exception $exception) {
|
248 |
+
$this->exception = $exception;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
}
|
252 |
+
}
|
src/vendor/php-http/curl-client/src/ResponseBuilder.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
declare(strict_types=1);
|
4 |
+
|
5 |
+
namespace Http\Client\Curl;
|
6 |
+
|
7 |
+
use Http\Message\Builder\ResponseBuilder as OriginalResponseBuilder;
|
8 |
+
use Psr\Http\Message\ResponseInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Extended response builder.
|
12 |
+
*/
|
13 |
+
class ResponseBuilder extends OriginalResponseBuilder
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Replace response with a new instance.
|
17 |
+
*
|
18 |
+
* @param ResponseInterface $response
|
19 |
+
*/
|
20 |
+
public function setResponse(ResponseInterface $response): void
|
21 |
+
{
|
22 |
+
$this->response = $response;
|
23 |
+
}
|
24 |
+
}
|
src/vendor/php-http/discovery/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1 |
# Change Log
|
2 |
|
|
|
|
|
|
|
|
|
3 |
## 1.14.2 - 2022-05-25
|
4 |
|
5 |
- [#202](https://github.com/php-http/discovery/pull/202) - Avoid error when the Symfony PSR-18 client exists but its dependencies are not installed
|
1 |
# Change Log
|
2 |
|
3 |
+
## 1.14.3 - 2022-07-11
|
4 |
+
|
5 |
+
- [#207](https://github.com/php-http/discovery/pull/207) - Updates Exception to extend Throwable solving static analysis errors for consumers
|
6 |
+
|
7 |
## 1.14.2 - 2022-05-25
|
8 |
|
9 |
- [#202](https://github.com/php-http/discovery/pull/202) - Avoid error when the Symfony PSR-18 client exists but its dependencies are not installed
|
src/vendor/php-http/discovery/src/Exception.php
CHANGED
@@ -2,11 +2,13 @@
|
|
2 |
|
3 |
namespace Http\Discovery;
|
4 |
|
|
|
|
|
5 |
/**
|
6 |
* An interface implemented by all discovery related exceptions.
|
7 |
*
|
8 |
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
9 |
*/
|
10 |
-
interface Exception
|
11 |
{
|
12 |
}
|
2 |
|
3 |
namespace Http\Discovery;
|
4 |
|
5 |
+
use Throwable;
|
6 |
+
|
7 |
/**
|
8 |
* An interface implemented by all discovery related exceptions.
|
9 |
*
|
10 |
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
11 |
*/
|
12 |
+
interface Exception extends Throwable
|
13 |
{
|
14 |
}
|
src/vendor/psr/container/.gitignore
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
composer.lock
|
2 |
-
composer.phar
|
3 |
-
/vendor/
|
|
|
|
|
|
src/vendor/psr/container/LICENSE
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
The MIT License (MIT)
|
2 |
-
|
3 |
-
Copyright (c) 2013-2016 container-interop
|
4 |
-
Copyright (c) 2016 PHP Framework Interoperability Group
|
5 |
-
|
6 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
7 |
-
this software and associated documentation files (the "Software"), to deal in
|
8 |
-
the Software without restriction, including without limitation the rights to
|
9 |
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
10 |
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
11 |
-
subject to the following conditions:
|
12 |
-
|
13 |
-
The above copyright notice and this permission notice shall be included in all
|
14 |
-
copies or substantial portions of the Software.
|
15 |
-
|
16 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
18 |
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
19 |
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
20 |
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
21 |
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/psr/container/README.md
DELETED
@@ -1,13 +0,0 @@
|
|
1 |
-
Container interface
|
2 |
-
==============
|
3 |
-
|
4 |
-
This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url].
|
5 |
-
|
6 |
-
Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.
|
7 |
-
|
8 |
-
The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.
|
9 |
-
|
10 |
-
[psr-url]: https://www.php-fig.org/psr/psr-11/
|
11 |
-
[package-url]: https://packagist.org/packages/psr/container
|
12 |
-
[implementation-url]: https://packagist.org/providers/psr/container-implementation
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/psr/container/composer.json
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "psr/container",
|
3 |
-
"type": "library",
|
4 |
-
"description": "Common Container Interface (PHP FIG PSR-11)",
|
5 |
-
"keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
|
6 |
-
"homepage": "https://github.com/php-fig/container",
|
7 |
-
"license": "MIT",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "PHP-FIG",
|
11 |
-
"homepage": "https://www.php-fig.org/"
|
12 |
-
}
|
13 |
-
],
|
14 |
-
"require": {
|
15 |
-
"php": ">=7.4.0"
|
16 |
-
},
|
17 |
-
"autoload": {
|
18 |
-
"psr-4": {
|
19 |
-
"Psr\\Container\\": "src/"
|
20 |
-
}
|
21 |
-
}
|
22 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/psr/container/src/ContainerExceptionInterface.php
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Psr\Container;
|
4 |
-
|
5 |
-
use Throwable;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Base interface representing a generic exception in a container.
|
9 |
-
*/
|
10 |
-
interface ContainerExceptionInterface extends Throwable
|
11 |
-
{
|
12 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/psr/container/src/ContainerInterface.php
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
declare(strict_types=1);
|
4 |
-
|
5 |
-
namespace Psr\Container;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Describes the interface of a container that exposes methods to read its entries.
|
9 |
-
*/
|
10 |
-
interface ContainerInterface
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Finds an entry of the container by its identifier and returns it.
|
14 |
-
*
|
15 |
-
* @param string $id Identifier of the entry to look for.
|
16 |
-
*
|
17 |
-
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
|
18 |
-
* @throws ContainerExceptionInterface Error while retrieving the entry.
|
19 |
-
*
|
20 |
-
* @return mixed Entry.
|
21 |
-
*/
|
22 |
-
public function get(string $id);
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Returns true if the container can return an entry for the given identifier.
|
26 |
-
* Returns false otherwise.
|
27 |
-
*
|
28 |
-
* `has($id)` returning true does not mean that `get($id)` will not throw an exception.
|
29 |
-
* It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
|
30 |
-
*
|
31 |
-
* @param string $id Identifier of the entry to look for.
|
32 |
-
*
|
33 |
-
* @return bool
|
34 |
-
*/
|
35 |
-
public function has(string $id);
|
36 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/psr/container/src/NotFoundExceptionInterface.php
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Psr\Container;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* No entry was found in the container.
|
7 |
-
*/
|
8 |
-
interface NotFoundExceptionInterface extends ContainerExceptionInterface
|
9 |
-
{
|
10 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/sentry/sentry/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2 |
|
3 |
## Unreleased
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
## 3.6.0 (2022-06-10)
|
6 |
|
7 |
- Add support for `monolog/monolog:^3.0` (#1321)
|
2 |
|
3 |
## Unreleased
|
4 |
|
5 |
+
## 3.7.0 (2022-07-18)
|
6 |
+
|
7 |
+
- Fix `Scope::getTransaction()` so that it returns also unsampled transactions (#1334)
|
8 |
+
- Set the event extras by taking the data from the Monolog record's extra (#1330)
|
9 |
+
|
10 |
+
## 3.6.1 (2022-06-27)
|
11 |
+
|
12 |
+
- Set the `sentry-trace` header when using the tracing middleware (#1331)
|
13 |
+
|
14 |
## 3.6.0 (2022-06-10)
|
15 |
|
16 |
- Add support for `monolog/monolog:^3.0` (#1321)
|
src/vendor/sentry/sentry/composer.json
CHANGED
@@ -96,7 +96,7 @@
|
|
96 |
"prefer-stable": true,
|
97 |
"extra": {
|
98 |
"branch-alias": {
|
99 |
-
"dev-master": "3.
|
100 |
}
|
101 |
}
|
102 |
}
|
96 |
"prefer-stable": true,
|
97 |
"extra": {
|
98 |
"branch-alias": {
|
99 |
+
"dev-master": "3.7.x-dev"
|
100 |
}
|
101 |
}
|
102 |
}
|
src/vendor/sentry/sentry/src/Monolog/Handler.php
CHANGED
@@ -69,10 +69,16 @@ final class Handler extends AbstractProcessingHandler
|
|
69 |
|
70 |
$monologContextData = $this->getMonologContextData($record['context']);
|
71 |
|
72 |
-
if (
|
73 |
$scope->setExtra('monolog.context', $monologContextData);
|
74 |
}
|
75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
$this->hub->captureEvent($event, $hint);
|
77 |
});
|
78 |
}
|
@@ -101,4 +107,24 @@ final class Handler extends AbstractProcessingHandler
|
|
101 |
|
102 |
return $contextData;
|
103 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
69 |
|
70 |
$monologContextData = $this->getMonologContextData($record['context']);
|
71 |
|
72 |
+
if ([] !== $monologContextData) {
|
73 |
$scope->setExtra('monolog.context', $monologContextData);
|
74 |
}
|
75 |
|
76 |
+
$monologExtraData = $this->getMonologExtraData($record['extra']);
|
77 |
+
|
78 |
+
if ([] !== $monologExtraData) {
|
79 |
+
$scope->setExtra('monolog.extra', $monologExtraData);
|
80 |
+
}
|
81 |
+
|
82 |
$this->hub->captureEvent($event, $hint);
|
83 |
});
|
84 |
}
|
107 |
|
108 |
return $contextData;
|
109 |
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* @param mixed[] $context
|
113 |
+
*
|
114 |
+
* @return mixed[]
|
115 |
+
*/
|
116 |
+
private function getMonologExtraData(array $context): array
|
117 |
+
{
|
118 |
+
if (!$this->fillExtraContext) {
|
119 |
+
return [];
|
120 |
+
}
|
121 |
+
|
122 |
+
$extraData = [];
|
123 |
+
|
124 |
+
foreach ($context as $key => $value) {
|
125 |
+
$extraData[$key] = $value;
|
126 |
+
}
|
127 |
+
|
128 |
+
return $extraData;
|
129 |
+
}
|
130 |
}
|
src/vendor/sentry/sentry/src/State/Scope.php
CHANGED
@@ -408,12 +408,8 @@ final class Scope
|
|
408 |
*/
|
409 |
public function getTransaction(): ?Transaction
|
410 |
{
|
411 |
-
|
412 |
-
|
413 |
-
if (null !== $span && null !== $span->getSpanRecorder() && !empty($span->getSpanRecorder()->getSpans())) {
|
414 |
-
// The first span in the recorder is considered to be a Transaction
|
415 |
-
/** @var Transaction */
|
416 |
-
return $span->getSpanRecorder()->getSpans()[0];
|
417 |
}
|
418 |
|
419 |
return null;
|
408 |
*/
|
409 |
public function getTransaction(): ?Transaction
|
410 |
{
|
411 |
+
if (null !== $this->span) {
|
412 |
+
return $this->span->getTransaction();
|
|
|
|
|
|
|
|
|
413 |
}
|
414 |
|
415 |
return null;
|
src/vendor/sentry/sentry/src/Tracing/GuzzleTracingMiddleware.php
CHANGED
@@ -34,7 +34,7 @@ final class GuzzleTracingMiddleware
|
|
34 |
|
35 |
$childSpan = $span->startChild($spanContext);
|
36 |
|
37 |
-
$request->withHeader('sentry-trace', $childSpan->toTraceparent());
|
38 |
|
39 |
$handlerPromiseCallback = static function ($responseOrException) use ($hub, $request, $childSpan) {
|
40 |
// We finish the span (which means setting the span end timestamp) first to ensure the measured time
|
34 |
|
35 |
$childSpan = $span->startChild($spanContext);
|
36 |
|
37 |
+
$request = $request->withHeader('sentry-trace', $childSpan->toTraceparent());
|
38 |
|
39 |
$handlerPromiseCallback = static function ($responseOrException) use ($hub, $request, $childSpan) {
|
40 |
// We finish the span (which means setting the span end timestamp) first to ensure the measured time
|
src/vendor/sentry/sentry/src/Tracing/Span.php
CHANGED
@@ -7,7 +7,7 @@ namespace Sentry\Tracing;
|
|
7 |
use Sentry\EventId;
|
8 |
|
9 |
/**
|
10 |
-
* This class stores all the information about a
|
11 |
*/
|
12 |
class Span
|
13 |
{
|
@@ -22,22 +22,22 @@ class Span
|
|
22 |
protected $traceId;
|
23 |
|
24 |
/**
|
25 |
-
* @var string|null Description of the
|
26 |
*/
|
27 |
protected $description;
|
28 |
|
29 |
/**
|
30 |
-
* @var string|null Operation of the
|
31 |
*/
|
32 |
protected $op;
|
33 |
|
34 |
/**
|
35 |
-
* @var SpanStatus|null Completion status of the
|
36 |
*/
|
37 |
protected $status;
|
38 |
|
39 |
/**
|
40 |
-
* @var SpanId|null ID of the parent
|
41 |
*/
|
42 |
protected $parentSpanId;
|
43 |
|
@@ -47,7 +47,7 @@ class Span
|
|
47 |
protected $sampled;
|
48 |
|
49 |
/**
|
50 |
-
* @var array<string, string> A List of tags associated to this
|
51 |
*/
|
52 |
protected $tags = [];
|
53 |
|
@@ -67,10 +67,15 @@ class Span
|
|
67 |
protected $endTimestamp;
|
68 |
|
69 |
/**
|
70 |
-
* @var SpanRecorder|null Reference instance to the SpanRecorder
|
71 |
*/
|
72 |
protected $spanRecorder;
|
73 |
|
|
|
|
|
|
|
|
|
|
|
74 |
/**
|
75 |
* Constructor.
|
76 |
*
|
@@ -390,6 +395,7 @@ class Span
|
|
390 |
$context->setTraceId($this->traceId);
|
391 |
|
392 |
$span = new self($context);
|
|
|
393 |
$span->spanRecorder = $this->spanRecorder;
|
394 |
|
395 |
if (null != $span->spanRecorder) {
|
@@ -417,6 +423,14 @@ class Span
|
|
417 |
$this->spanRecorder = null;
|
418 |
}
|
419 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
/**
|
421 |
* Returns a string that can be used for the `sentry-trace` header.
|
422 |
*/
|
7 |
use Sentry\EventId;
|
8 |
|
9 |
/**
|
10 |
+
* This class stores all the information about a span.
|
11 |
*/
|
12 |
class Span
|
13 |
{
|
22 |
protected $traceId;
|
23 |
|
24 |
/**
|
25 |
+
* @var string|null Description of the span
|
26 |
*/
|
27 |
protected $description;
|
28 |
|
29 |
/**
|
30 |
+
* @var string|null Operation of the span
|
31 |
*/
|
32 |
protected $op;
|
33 |
|
34 |
/**
|
35 |
+
* @var SpanStatus|null Completion status of the span
|
36 |
*/
|
37 |
protected $status;
|
38 |
|
39 |
/**
|
40 |
+
* @var SpanId|null ID of the parent span
|
41 |
*/
|
42 |
protected $parentSpanId;
|
43 |
|
47 |
protected $sampled;
|
48 |
|
49 |
/**
|
50 |
+
* @var array<string, string> A List of tags associated to this span
|
51 |
*/
|
52 |
protected $tags = [];
|
53 |
|
67 |
protected $endTimestamp;
|
68 |
|
69 |
/**
|
70 |
+
* @var SpanRecorder|null Reference instance to the {@see SpanRecorder}
|
71 |
*/
|
72 |
protected $spanRecorder;
|
73 |
|
74 |
+
/**
|
75 |
+
* @var Transaction|null The transaction containing this span
|
76 |
+
*/
|
77 |
+
protected $transaction;
|
78 |
+
|
79 |
/**
|
80 |
* Constructor.
|
81 |
*
|
395 |
$context->setTraceId($this->traceId);
|
396 |
|
397 |
$span = new self($context);
|
398 |
+
$span->transaction = $this->transaction;
|
399 |
$span->spanRecorder = $this->spanRecorder;
|
400 |
|
401 |
if (null != $span->spanRecorder) {
|
423 |
$this->spanRecorder = null;
|
424 |
}
|
425 |
|
426 |
+
/**
|
427 |
+
* Returns the transaction containing this span.
|
428 |
+
*/
|
429 |
+
public function getTransaction(): ?Transaction
|
430 |
+
{
|
431 |
+
return $this->transaction;
|
432 |
+
}
|
433 |
+
|
434 |
/**
|
435 |
* Returns a string that can be used for the `sentry-trace` header.
|
436 |
*/
|
src/vendor/sentry/sentry/src/Tracing/Transaction.php
CHANGED
@@ -38,6 +38,7 @@ final class Transaction extends Span
|
|
38 |
|
39 |
$this->hub = $hub ?? SentrySdk::getCurrentHub();
|
40 |
$this->name = $context->getName();
|
|
|
41 |
}
|
42 |
|
43 |
/**
|
38 |
|
39 |
$this->hub = $hub ?? SentrySdk::getCurrentHub();
|
40 |
$this->name = $context->getName();
|
41 |
+
$this->transaction = $this;
|
42 |
}
|
43 |
|
44 |
/**
|
src/vendor/symfony/http-client-contracts/.gitignore
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
vendor/
|
2 |
-
composer.lock
|
3 |
-
phpunit.xml
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/CHANGELOG.md
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
CHANGELOG
|
2 |
-
=========
|
3 |
-
|
4 |
-
The changelog is maintained for all Symfony contracts at the following URL:
|
5 |
-
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/ChunkInterface.php
DELETED
@@ -1,71 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* The interface of chunks returned by ResponseStreamInterface::current().
|
18 |
-
*
|
19 |
-
* When the chunk is first, last or timeout, the content MUST be empty.
|
20 |
-
* When an unchecked timeout or a network error occurs, a TransportExceptionInterface
|
21 |
-
* MUST be thrown by the destructor unless one was already thrown by another method.
|
22 |
-
*
|
23 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
24 |
-
*/
|
25 |
-
interface ChunkInterface
|
26 |
-
{
|
27 |
-
/**
|
28 |
-
* Tells when the idle timeout has been reached.
|
29 |
-
*
|
30 |
-
* @throws TransportExceptionInterface on a network error
|
31 |
-
*/
|
32 |
-
public function isTimeout(): bool;
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Tells when headers just arrived.
|
36 |
-
*
|
37 |
-
* @throws TransportExceptionInterface on a network error or when the idle timeout is reached
|
38 |
-
*/
|
39 |
-
public function isFirst(): bool;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Tells when the body just completed.
|
43 |
-
*
|
44 |
-
* @throws TransportExceptionInterface on a network error or when the idle timeout is reached
|
45 |
-
*/
|
46 |
-
public function isLast(): bool;
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Returns a [status code, headers] tuple when a 1xx status code was just received.
|
50 |
-
*
|
51 |
-
* @throws TransportExceptionInterface on a network error or when the idle timeout is reached
|
52 |
-
*/
|
53 |
-
public function getInformationalStatus(): ?array;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Returns the content of the response chunk.
|
57 |
-
*
|
58 |
-
* @throws TransportExceptionInterface on a network error or when the idle timeout is reached
|
59 |
-
*/
|
60 |
-
public function getContent(): string;
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Returns the offset of the chunk in the response body.
|
64 |
-
*/
|
65 |
-
public function getOffset(): int;
|
66 |
-
|
67 |
-
/**
|
68 |
-
* In case of error, returns the message that describes it.
|
69 |
-
*/
|
70 |
-
public function getError(): ?string;
|
71 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/ClientExceptionInterface.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* When a 4xx response is returned.
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
interface ClientExceptionInterface extends HttpExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/DecodingExceptionInterface.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* When a content-type cannot be decoded to the expected representation.
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
interface DecodingExceptionInterface extends ExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/ExceptionInterface.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* The base interface for all exceptions in the contract.
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
interface ExceptionInterface extends \Throwable
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/HttpExceptionInterface.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Base interface for HTTP-related exceptions.
|
18 |
-
*
|
19 |
-
* @author Anton Chernikov <anton_ch1989@mail.ru>
|
20 |
-
*/
|
21 |
-
interface HttpExceptionInterface extends ExceptionInterface
|
22 |
-
{
|
23 |
-
public function getResponse(): ResponseInterface;
|
24 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/RedirectionExceptionInterface.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* When a 3xx response is returned and the "max_redirects" option has been reached.
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
interface RedirectionExceptionInterface extends HttpExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/ServerExceptionInterface.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* When a 5xx response is returned.
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
interface ServerExceptionInterface extends HttpExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/TimeoutExceptionInterface.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* When an idle timeout occurs.
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
interface TimeoutExceptionInterface extends TransportExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Exception/TransportExceptionInterface.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Exception;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* When any error happens at the transport level.
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
interface TransportExceptionInterface extends ExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/HttpClientInterface.php
DELETED
@@ -1,95 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
15 |
-
use Symfony\Contracts\HttpClient\Test\HttpClientTestCase;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Provides flexible methods for requesting HTTP resources synchronously or asynchronously.
|
19 |
-
*
|
20 |
-
* @see HttpClientTestCase for a reference test suite
|
21 |
-
*
|
22 |
-
* @method static withOptions(array $options) Returns a new instance of the client with new default options
|
23 |
-
*
|
24 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
25 |
-
*/
|
26 |
-
interface HttpClientInterface
|
27 |
-
{
|
28 |
-
public const OPTIONS_DEFAULTS = [
|
29 |
-
'auth_basic' => null, // array|string - an array containing the username as first value, and optionally the
|
30 |
-
// password as the second one; or string like username:password - enabling HTTP Basic
|
31 |
-
// authentication (RFC 7617)
|
32 |
-
'auth_bearer' => null, // string - a token enabling HTTP Bearer authorization (RFC 6750)
|
33 |
-
'query' => [], // string[] - associative array of query string values to merge with the request's URL
|
34 |
-
'headers' => [], // iterable|string[]|string[][] - headers names provided as keys or as part of values
|
35 |
-
'body' => '', // array|string|resource|\Traversable|\Closure - the callback SHOULD yield a string
|
36 |
-
// smaller than the amount requested as argument; the empty string signals EOF; if
|
37 |
-
// an array is passed, it is meant as a form payload of field names and values
|
38 |
-
'json' => null, // mixed - if set, implementations MUST set the "body" option to the JSON-encoded
|
39 |
-
// value and set the "content-type" header to a JSON-compatible value if it is not
|
40 |
-
// explicitly defined in the headers option - typically "application/json"
|
41 |
-
'user_data' => null, // mixed - any extra data to attach to the request (scalar, callable, object...) that
|
42 |
-
// MUST be available via $response->getInfo('user_data') - not used internally
|
43 |
-
'max_redirects' => 20, // int - the maximum number of redirects to follow; a value lower than or equal to 0
|
44 |
-
// means redirects should not be followed; "Authorization" and "Cookie" headers MUST
|
45 |
-
// NOT follow except for the initial host name
|
46 |
-
'http_version' => null, // string - defaults to the best supported version, typically 1.1 or 2.0
|
47 |
-
'base_uri' => null, // string - the URI to resolve relative URLs, following rules in RFC 3986, section 2
|
48 |
-
'buffer' => true, // bool|resource|\Closure - whether the content of the response should be buffered or not,
|
49 |
-
// or a stream resource where the response body should be written,
|
50 |
-
// or a closure telling if/where the response should be buffered based on its headers
|
51 |
-
'on_progress' => null, // callable(int $dlNow, int $dlSize, array $info) - throwing any exceptions MUST abort
|
52 |
-
// the request; it MUST be called on DNS resolution, on arrival of headers and on
|
53 |
-
// completion; it SHOULD be called on upload/download of data and at least 1/s
|
54 |
-
'resolve' => [], // string[] - a map of host to IP address that SHOULD replace DNS resolution
|
55 |
-
'proxy' => null, // string - by default, the proxy-related env vars handled by curl SHOULD be honored
|
56 |
-
'no_proxy' => null, // string - a comma separated list of hosts that do not require a proxy to be reached
|
57 |
-
'timeout' => null, // float - the idle timeout - defaults to ini_get('default_socket_timeout')
|
58 |
-
'max_duration' => 0, // float - the maximum execution time for the request+response as a whole;
|
59 |
-
// a value lower than or equal to 0 means it is unlimited
|
60 |
-
'bindto' => '0', // string - the interface or the local socket to bind to
|
61 |
-
'verify_peer' => true, // see https://php.net/context.ssl for the following options
|
62 |
-
'verify_host' => true,
|
63 |
-
'cafile' => null,
|
64 |
-
'capath' => null,
|
65 |
-
'local_cert' => null,
|
66 |
-
'local_pk' => null,
|
67 |
-
'passphrase' => null,
|
68 |
-
'ciphers' => null,
|
69 |
-
'peer_fingerprint' => null,
|
70 |
-
'capture_peer_cert_chain' => false,
|
71 |
-
'extra' => [], // array - additional options that can be ignored if unsupported, unlike regular options
|
72 |
-
];
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Requests an HTTP resource.
|
76 |
-
*
|
77 |
-
* Responses MUST be lazy, but their status code MUST be
|
78 |
-
* checked even if none of their public methods are called.
|
79 |
-
*
|
80 |
-
* Implementations are not required to support all options described above; they can also
|
81 |
-
* support more custom options; but in any case, they MUST throw a TransportExceptionInterface
|
82 |
-
* when an unsupported option is passed.
|
83 |
-
*
|
84 |
-
* @throws TransportExceptionInterface When an unsupported option is passed
|
85 |
-
*/
|
86 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface;
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Yields responses chunk by chunk as they complete.
|
90 |
-
*
|
91 |
-
* @param ResponseInterface|iterable<array-key, ResponseInterface> $responses One or more responses created by the current HTTP client
|
92 |
-
* @param float|null $timeout The idle timeout before yielding timeout chunks
|
93 |
-
*/
|
94 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface;
|
95 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/LICENSE
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
Copyright (c) 2018-2022 Fabien Potencier
|
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 furnished
|
8 |
-
to do so, subject to the following conditions:
|
9 |
-
|
10 |
-
The above copyright notice and this permission notice shall be included in all
|
11 |
-
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/README.md
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
Symfony HttpClient Contracts
|
2 |
-
============================
|
3 |
-
|
4 |
-
A set of abstractions extracted out of the Symfony components.
|
5 |
-
|
6 |
-
Can be used to build on semantics that the Symfony components proved useful - and
|
7 |
-
that already have battle tested implementations.
|
8 |
-
|
9 |
-
See https://github.com/symfony/contracts/blob/main/README.md for more information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/ResponseInterface.php
DELETED
@@ -1,109 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
15 |
-
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
|
16 |
-
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
|
17 |
-
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
18 |
-
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
19 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* A (lazily retrieved) HTTP response.
|
23 |
-
*
|
24 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
25 |
-
*/
|
26 |
-
interface ResponseInterface
|
27 |
-
{
|
28 |
-
/**
|
29 |
-
* Gets the HTTP status code of the response.
|
30 |
-
*
|
31 |
-
* @throws TransportExceptionInterface when a network error occurs
|
32 |
-
*/
|
33 |
-
public function getStatusCode(): int;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Gets the HTTP headers of the response.
|
37 |
-
*
|
38 |
-
* @param bool $throw Whether an exception should be thrown on 3/4/5xx status codes
|
39 |
-
*
|
40 |
-
* @return string[][] The headers of the response keyed by header names in lowercase
|
41 |
-
*
|
42 |
-
* @throws TransportExceptionInterface When a network error occurs
|
43 |
-
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
|
44 |
-
* @throws ClientExceptionInterface On a 4xx when $throw is true
|
45 |
-
* @throws ServerExceptionInterface On a 5xx when $throw is true
|
46 |
-
*/
|
47 |
-
public function getHeaders(bool $throw = true): array;
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Gets the response body as a string.
|
51 |
-
*
|
52 |
-
* @param bool $throw Whether an exception should be thrown on 3/4/5xx status codes
|
53 |
-
*
|
54 |
-
* @throws TransportExceptionInterface When a network error occurs
|
55 |
-
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
|
56 |
-
* @throws ClientExceptionInterface On a 4xx when $throw is true
|
57 |
-
* @throws ServerExceptionInterface On a 5xx when $throw is true
|
58 |
-
*/
|
59 |
-
public function getContent(bool $throw = true): string;
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Gets the response body decoded as array, typically from a JSON payload.
|
63 |
-
*
|
64 |
-
* @param bool $throw Whether an exception should be thrown on 3/4/5xx status codes
|
65 |
-
*
|
66 |
-
* @throws DecodingExceptionInterface When the body cannot be decoded to an array
|
67 |
-
* @throws TransportExceptionInterface When a network error occurs
|
68 |
-
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
|
69 |
-
* @throws ClientExceptionInterface On a 4xx when $throw is true
|
70 |
-
* @throws ServerExceptionInterface On a 5xx when $throw is true
|
71 |
-
*/
|
72 |
-
public function toArray(bool $throw = true): array;
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Closes the response stream and all related buffers.
|
76 |
-
*
|
77 |
-
* No further chunk will be yielded after this method has been called.
|
78 |
-
*/
|
79 |
-
public function cancel(): void;
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Returns info coming from the transport layer.
|
83 |
-
*
|
84 |
-
* This method SHOULD NOT throw any ExceptionInterface and SHOULD be non-blocking.
|
85 |
-
* The returned info is "live": it can be empty and can change from one call to
|
86 |
-
* another, as the request/response progresses.
|
87 |
-
*
|
88 |
-
* The following info MUST be returned:
|
89 |
-
* - canceled (bool) - true if the response was canceled using ResponseInterface::cancel(), false otherwise
|
90 |
-
* - error (string|null) - the error message when the transfer was aborted, null otherwise
|
91 |
-
* - http_code (int) - the last response code or 0 when it is not known yet
|
92 |
-
* - http_method (string) - the HTTP verb of the last request
|
93 |
-
* - redirect_count (int) - the number of redirects followed while executing the request
|
94 |
-
* - redirect_url (string|null) - the resolved location of redirect responses, null otherwise
|
95 |
-
* - response_headers (array) - an array modelled after the special $http_response_header variable
|
96 |
-
* - start_time (float) - the time when the request was sent or 0.0 when it's pending
|
97 |
-
* - url (string) - the last effective URL of the request
|
98 |
-
* - user_data (mixed) - the value of the "user_data" request option, null if not set
|
99 |
-
*
|
100 |
-
* When the "capture_peer_cert_chain" option is true, the "peer_certificate_chain"
|
101 |
-
* attribute SHOULD list the peer certificates as an array of OpenSSL X.509 resources.
|
102 |
-
*
|
103 |
-
* Other info SHOULD be named after curl_getinfo()'s associative return value.
|
104 |
-
*
|
105 |
-
* @return mixed An array of all available info, or one of them when $type is
|
106 |
-
* provided, or null when an unsupported type is requested
|
107 |
-
*/
|
108 |
-
public function getInfo(string $type = null);
|
109 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/ResponseStreamInterface.php
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Yields response chunks, returned by HttpClientInterface::stream().
|
16 |
-
*
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*
|
19 |
-
* @extends \Iterator<ResponseInterface, ChunkInterface>
|
20 |
-
*/
|
21 |
-
interface ResponseStreamInterface extends \Iterator
|
22 |
-
{
|
23 |
-
public function key(): ResponseInterface;
|
24 |
-
|
25 |
-
public function current(): ChunkInterface;
|
26 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php
DELETED
@@ -1,192 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ('cli-server' !== \PHP_SAPI) {
|
4 |
-
// safe guard against unwanted execution
|
5 |
-
throw new \Exception("You cannot run this script directly, it's a fixture for TestHttpServer.");
|
6 |
-
}
|
7 |
-
|
8 |
-
$vars = [];
|
9 |
-
|
10 |
-
if (!$_POST) {
|
11 |
-
$_POST = json_decode(file_get_contents('php://input'), true);
|
12 |
-
$_POST['content-type'] = $_SERVER['HTTP_CONTENT_TYPE'] ?? '?';
|
13 |
-
}
|
14 |
-
|
15 |
-
foreach ($_SERVER as $k => $v) {
|
16 |
-
switch ($k) {
|
17 |
-
default:
|
18 |
-
if (0 !== strpos($k, 'HTTP_')) {
|
19 |
-
continue 2;
|
20 |
-
}
|
21 |
-
// no break
|
22 |
-
case 'SERVER_NAME':
|
23 |
-
case 'SERVER_PROTOCOL':
|
24 |
-
case 'REQUEST_URI':
|
25 |
-
case 'REQUEST_METHOD':
|
26 |
-
case 'PHP_AUTH_USER':
|
27 |
-
case 'PHP_AUTH_PW':
|
28 |
-
$vars[$k] = $v;
|
29 |
-
}
|
30 |
-
}
|
31 |
-
|
32 |
-
$json = json_encode($vars, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
|
33 |
-
|
34 |
-
switch ($vars['REQUEST_URI']) {
|
35 |
-
default:
|
36 |
-
exit;
|
37 |
-
|
38 |
-
case '/head':
|
39 |
-
header('Content-Length: '.strlen($json), true);
|
40 |
-
break;
|
41 |
-
|
42 |
-
case '/':
|
43 |
-
case '/?a=a&b=b':
|
44 |
-
case 'http://127.0.0.1:8057/':
|
45 |
-
case 'http://localhost:8057/':
|
46 |
-
ob_start('ob_gzhandler');
|
47 |
-
break;
|
48 |
-
|
49 |
-
case '/103':
|
50 |
-
header('HTTP/1.1 103 Early Hints');
|
51 |
-
header('Link: </style.css>; rel=preload; as=style', false);
|
52 |
-
header('Link: </script.js>; rel=preload; as=script', false);
|
53 |
-
flush();
|
54 |
-
usleep(1000);
|
55 |
-
echo "HTTP/1.1 200 OK\r\n";
|
56 |
-
echo "Date: Fri, 26 May 2017 10:02:11 GMT\r\n";
|
57 |
-
echo "Content-Length: 13\r\n";
|
58 |
-
echo "\r\n";
|
59 |
-
echo 'Here the body';
|
60 |
-
exit;
|
61 |
-
|
62 |
-
case '/404':
|
63 |
-
header('Content-Type: application/json', true, 404);
|
64 |
-
break;
|
65 |
-
|
66 |
-
case '/404-gzipped':
|
67 |
-
header('Content-Type: text/plain', true, 404);
|
68 |
-
ob_start('ob_gzhandler');
|
69 |
-
@ob_flush();
|
70 |
-
flush();
|
71 |
-
usleep(300000);
|
72 |
-
echo 'some text';
|
73 |
-
exit;
|
74 |
-
|
75 |
-
case '/301':
|
76 |
-
if ('Basic Zm9vOmJhcg==' === $vars['HTTP_AUTHORIZATION']) {
|
77 |
-
header('Location: http://127.0.0.1:8057/302', true, 301);
|
78 |
-
}
|
79 |
-
break;
|
80 |
-
|
81 |
-
case '/301/bad-tld':
|
82 |
-
header('Location: http://foo.example.', true, 301);
|
83 |
-
break;
|
84 |
-
|
85 |
-
case '/301/invalid':
|
86 |
-
header('Location: //?foo=bar', true, 301);
|
87 |
-
break;
|
88 |
-
|
89 |
-
case '/302':
|
90 |
-
if (!isset($vars['HTTP_AUTHORIZATION'])) {
|
91 |
-
header('Location: http://localhost:8057/', true, 302);
|
92 |
-
}
|
93 |
-
break;
|
94 |
-
|
95 |
-
case '/302/relative':
|
96 |
-
header('Location: ..', true, 302);
|
97 |
-
break;
|
98 |
-
|
99 |
-
case '/304':
|
100 |
-
header('Content-Length: 10', true, 304);
|
101 |
-
echo '12345';
|
102 |
-
|
103 |
-
return;
|
104 |
-
|
105 |
-
case '/307':
|
106 |
-
header('Location: http://localhost:8057/post', true, 307);
|
107 |
-
break;
|
108 |
-
|
109 |
-
case '/length-broken':
|
110 |
-
header('Content-Length: 1000');
|
111 |
-
break;
|
112 |
-
|
113 |
-
case '/post':
|
114 |
-
$output = json_encode($_POST + ['REQUEST_METHOD' => $vars['REQUEST_METHOD']], \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
|
115 |
-
header('Content-Type: application/json', true);
|
116 |
-
header('Content-Length: '.strlen($output));
|
117 |
-
echo $output;
|
118 |
-
exit;
|
119 |
-
|
120 |
-
case '/timeout-header':
|
121 |
-
usleep(300000);
|
122 |
-
break;
|
123 |
-
|
124 |
-
case '/timeout-body':
|
125 |
-
echo '<1>';
|
126 |
-
@ob_flush();
|
127 |
-
flush();
|
128 |
-
usleep(500000);
|
129 |
-
echo '<2>';
|
130 |
-
exit;
|
131 |
-
|
132 |
-
case '/timeout-long':
|
133 |
-
ignore_user_abort(false);
|
134 |
-
sleep(1);
|
135 |
-
while (true) {
|
136 |
-
echo '<1>';
|
137 |
-
@ob_flush();
|
138 |
-
flush();
|
139 |
-
usleep(500);
|
140 |
-
}
|
141 |
-
exit;
|
142 |
-
|
143 |
-
case '/chunked':
|
144 |
-
header('Transfer-Encoding: chunked');
|
145 |
-
echo "8\r\nSymfony \r\n5\r\nis aw\r\n6\r\nesome!\r\n0\r\n\r\n";
|
146 |
-
exit;
|
147 |
-
|
148 |
-
case '/chunked-broken':
|
149 |
-
header('Transfer-Encoding: chunked');
|
150 |
-
echo "8\r\nSymfony \r\n5\r\nis aw\r\n6\r\ne";
|
151 |
-
exit;
|
152 |
-
|
153 |
-
case '/gzip-broken':
|
154 |
-
header('Content-Encoding: gzip');
|
155 |
-
echo str_repeat('-', 1000);
|
156 |
-
exit;
|
157 |
-
|
158 |
-
case '/max-duration':
|
159 |
-
ignore_user_abort(false);
|
160 |
-
while (true) {
|
161 |
-
echo '<1>';
|
162 |
-
@ob_flush();
|
163 |
-
flush();
|
164 |
-
usleep(500);
|
165 |
-
}
|
166 |
-
exit;
|
167 |
-
|
168 |
-
case '/json':
|
169 |
-
header('Content-Type: application/json');
|
170 |
-
echo json_encode([
|
171 |
-
'documents' => [
|
172 |
-
['id' => '/json/1'],
|
173 |
-
['id' => '/json/2'],
|
174 |
-
['id' => '/json/3'],
|
175 |
-
],
|
176 |
-
]);
|
177 |
-
exit;
|
178 |
-
|
179 |
-
case '/json/1':
|
180 |
-
case '/json/2':
|
181 |
-
case '/json/3':
|
182 |
-
header('Content-Type: application/json');
|
183 |
-
echo json_encode([
|
184 |
-
'title' => $vars['REQUEST_URI'],
|
185 |
-
]);
|
186 |
-
|
187 |
-
exit;
|
188 |
-
}
|
189 |
-
|
190 |
-
header('Content-Type: application/json', true);
|
191 |
-
|
192 |
-
echo $json;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php
DELETED
@@ -1,1132 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Test;
|
13 |
-
|
14 |
-
use PHPUnit\Framework\TestCase;
|
15 |
-
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
16 |
-
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
17 |
-
use Symfony\Contracts\HttpClient\Exception\TimeoutExceptionInterface;
|
18 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
19 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* A reference test suite for HttpClientInterface implementations.
|
23 |
-
*/
|
24 |
-
abstract class HttpClientTestCase extends TestCase
|
25 |
-
{
|
26 |
-
public static function setUpBeforeClass(): void
|
27 |
-
{
|
28 |
-
TestHttpServer::start();
|
29 |
-
}
|
30 |
-
|
31 |
-
abstract protected function getHttpClient(string $testCase): HttpClientInterface;
|
32 |
-
|
33 |
-
public function testGetRequest()
|
34 |
-
{
|
35 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
36 |
-
$response = $client->request('GET', 'http://localhost:8057', [
|
37 |
-
'headers' => ['Foo' => 'baR'],
|
38 |
-
'user_data' => $data = new \stdClass(),
|
39 |
-
]);
|
40 |
-
|
41 |
-
$this->assertSame([], $response->getInfo('response_headers'));
|
42 |
-
$this->assertSame($data, $response->getInfo()['user_data']);
|
43 |
-
$this->assertSame(200, $response->getStatusCode());
|
44 |
-
|
45 |
-
$info = $response->getInfo();
|
46 |
-
$this->assertNull($info['error']);
|
47 |
-
$this->assertSame(0, $info['redirect_count']);
|
48 |
-
$this->assertSame('HTTP/1.1 200 OK', $info['response_headers'][0]);
|
49 |
-
$this->assertSame('Host: localhost:8057', $info['response_headers'][1]);
|
50 |
-
$this->assertSame('http://localhost:8057/', $info['url']);
|
51 |
-
|
52 |
-
$headers = $response->getHeaders();
|
53 |
-
|
54 |
-
$this->assertSame('localhost:8057', $headers['host'][0]);
|
55 |
-
$this->assertSame(['application/json'], $headers['content-type']);
|
56 |
-
|
57 |
-
$body = json_decode($response->getContent(), true);
|
58 |
-
$this->assertSame($body, $response->toArray());
|
59 |
-
|
60 |
-
$this->assertSame('HTTP/1.1', $body['SERVER_PROTOCOL']);
|
61 |
-
$this->assertSame('/', $body['REQUEST_URI']);
|
62 |
-
$this->assertSame('GET', $body['REQUEST_METHOD']);
|
63 |
-
$this->assertSame('localhost:8057', $body['HTTP_HOST']);
|
64 |
-
$this->assertSame('baR', $body['HTTP_FOO']);
|
65 |
-
|
66 |
-
$response = $client->request('GET', 'http://localhost:8057/length-broken');
|
67 |
-
|
68 |
-
$this->expectException(TransportExceptionInterface::class);
|
69 |
-
$response->getContent();
|
70 |
-
}
|
71 |
-
|
72 |
-
public function testHeadRequest()
|
73 |
-
{
|
74 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
75 |
-
$response = $client->request('HEAD', 'http://localhost:8057/head', [
|
76 |
-
'headers' => ['Foo' => 'baR'],
|
77 |
-
'user_data' => $data = new \stdClass(),
|
78 |
-
'buffer' => false,
|
79 |
-
]);
|
80 |
-
|
81 |
-
$this->assertSame([], $response->getInfo('response_headers'));
|
82 |
-
$this->assertSame(200, $response->getStatusCode());
|
83 |
-
|
84 |
-
$info = $response->getInfo();
|
85 |
-
$this->assertSame('HTTP/1.1 200 OK', $info['response_headers'][0]);
|
86 |
-
$this->assertSame('Host: localhost:8057', $info['response_headers'][1]);
|
87 |
-
|
88 |
-
$headers = $response->getHeaders();
|
89 |
-
|
90 |
-
$this->assertSame('localhost:8057', $headers['host'][0]);
|
91 |
-
$this->assertSame(['application/json'], $headers['content-type']);
|
92 |
-
$this->assertTrue(0 < $headers['content-length'][0]);
|
93 |
-
|
94 |
-
$this->assertSame('', $response->getContent());
|
95 |
-
}
|
96 |
-
|
97 |
-
public function testNonBufferedGetRequest()
|
98 |
-
{
|
99 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
100 |
-
$response = $client->request('GET', 'http://localhost:8057', [
|
101 |
-
'buffer' => false,
|
102 |
-
'headers' => ['Foo' => 'baR'],
|
103 |
-
]);
|
104 |
-
|
105 |
-
$body = $response->toArray();
|
106 |
-
$this->assertSame('baR', $body['HTTP_FOO']);
|
107 |
-
|
108 |
-
$this->expectException(TransportExceptionInterface::class);
|
109 |
-
$response->getContent();
|
110 |
-
}
|
111 |
-
|
112 |
-
public function testBufferSink()
|
113 |
-
{
|
114 |
-
$sink = fopen('php://temp', 'w+');
|
115 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
116 |
-
$response = $client->request('GET', 'http://localhost:8057', [
|
117 |
-
'buffer' => $sink,
|
118 |
-
'headers' => ['Foo' => 'baR'],
|
119 |
-
]);
|
120 |
-
|
121 |
-
$body = $response->toArray();
|
122 |
-
$this->assertSame('baR', $body['HTTP_FOO']);
|
123 |
-
|
124 |
-
rewind($sink);
|
125 |
-
$sink = stream_get_contents($sink);
|
126 |
-
$this->assertSame($sink, $response->getContent());
|
127 |
-
}
|
128 |
-
|
129 |
-
public function testConditionalBuffering()
|
130 |
-
{
|
131 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
132 |
-
$response = $client->request('GET', 'http://localhost:8057');
|
133 |
-
$firstContent = $response->getContent();
|
134 |
-
$secondContent = $response->getContent();
|
135 |
-
|
136 |
-
$this->assertSame($firstContent, $secondContent);
|
137 |
-
|
138 |
-
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => function () { return false; }]);
|
139 |
-
$response->getContent();
|
140 |
-
|
141 |
-
$this->expectException(TransportExceptionInterface::class);
|
142 |
-
$response->getContent();
|
143 |
-
}
|
144 |
-
|
145 |
-
public function testReentrantBufferCallback()
|
146 |
-
{
|
147 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
148 |
-
|
149 |
-
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => function () use (&$response) {
|
150 |
-
$response->cancel();
|
151 |
-
|
152 |
-
return true;
|
153 |
-
}]);
|
154 |
-
|
155 |
-
$this->assertSame(200, $response->getStatusCode());
|
156 |
-
|
157 |
-
$this->expectException(TransportExceptionInterface::class);
|
158 |
-
$response->getContent();
|
159 |
-
}
|
160 |
-
|
161 |
-
public function testThrowingBufferCallback()
|
162 |
-
{
|
163 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
164 |
-
|
165 |
-
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => function () {
|
166 |
-
throw new \Exception('Boo.');
|
167 |
-
}]);
|
168 |
-
|
169 |
-
$this->assertSame(200, $response->getStatusCode());
|
170 |
-
|
171 |
-
$this->expectException(TransportExceptionInterface::class);
|
172 |
-
$this->expectExceptionMessage('Boo');
|
173 |
-
$response->getContent();
|
174 |
-
}
|
175 |
-
|
176 |
-
public function testUnsupportedOption()
|
177 |
-
{
|
178 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
179 |
-
|
180 |
-
$this->expectException(\InvalidArgumentException::class);
|
181 |
-
$client->request('GET', 'http://localhost:8057', [
|
182 |
-
'capture_peer_cert' => 1.0,
|
183 |
-
]);
|
184 |
-
}
|
185 |
-
|
186 |
-
public function testHttpVersion()
|
187 |
-
{
|
188 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
189 |
-
$response = $client->request('GET', 'http://localhost:8057', [
|
190 |
-
'http_version' => 1.0,
|
191 |
-
]);
|
192 |
-
|
193 |
-
$this->assertSame(200, $response->getStatusCode());
|
194 |
-
$this->assertSame('HTTP/1.0 200 OK', $response->getInfo('response_headers')[0]);
|
195 |
-
|
196 |
-
$body = $response->toArray();
|
197 |
-
|
198 |
-
$this->assertSame('HTTP/1.0', $body['SERVER_PROTOCOL']);
|
199 |
-
$this->assertSame('GET', $body['REQUEST_METHOD']);
|
200 |
-
$this->assertSame('/', $body['REQUEST_URI']);
|
201 |
-
}
|
202 |
-
|
203 |
-
public function testChunkedEncoding()
|
204 |
-
{
|
205 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
206 |
-
$response = $client->request('GET', 'http://localhost:8057/chunked');
|
207 |
-
|
208 |
-
$this->assertSame(['chunked'], $response->getHeaders()['transfer-encoding']);
|
209 |
-
$this->assertSame('Symfony is awesome!', $response->getContent());
|
210 |
-
|
211 |
-
$response = $client->request('GET', 'http://localhost:8057/chunked-broken');
|
212 |
-
|
213 |
-
$this->expectException(TransportExceptionInterface::class);
|
214 |
-
$response->getContent();
|
215 |
-
}
|
216 |
-
|
217 |
-
public function testClientError()
|
218 |
-
{
|
219 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
220 |
-
$response = $client->request('GET', 'http://localhost:8057/404');
|
221 |
-
|
222 |
-
$client->stream($response)->valid();
|
223 |
-
|
224 |
-
$this->assertSame(404, $response->getInfo('http_code'));
|
225 |
-
|
226 |
-
try {
|
227 |
-
$response->getHeaders();
|
228 |
-
$this->fail(ClientExceptionInterface::class.' expected');
|
229 |
-
} catch (ClientExceptionInterface $e) {
|
230 |
-
}
|
231 |
-
|
232 |
-
try {
|
233 |
-
$response->getContent();
|
234 |
-
$this->fail(ClientExceptionInterface::class.' expected');
|
235 |
-
} catch (ClientExceptionInterface $e) {
|
236 |
-
}
|
237 |
-
|
238 |
-
$this->assertSame(404, $response->getStatusCode());
|
239 |
-
$this->assertSame(['application/json'], $response->getHeaders(false)['content-type']);
|
240 |
-
$this->assertNotEmpty($response->getContent(false));
|
241 |
-
|
242 |
-
$response = $client->request('GET', 'http://localhost:8057/404');
|
243 |
-
|
244 |
-
try {
|
245 |
-
foreach ($client->stream($response) as $chunk) {
|
246 |
-
$this->assertTrue($chunk->isFirst());
|
247 |
-
}
|
248 |
-
$this->fail(ClientExceptionInterface::class.' expected');
|
249 |
-
} catch (ClientExceptionInterface $e) {
|
250 |
-
}
|
251 |
-
}
|
252 |
-
|
253 |
-
public function testIgnoreErrors()
|
254 |
-
{
|
255 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
256 |
-
$response = $client->request('GET', 'http://localhost:8057/404');
|
257 |
-
|
258 |
-
$this->assertSame(404, $response->getStatusCode());
|
259 |
-
}
|
260 |
-
|
261 |
-
public function testDnsError()
|
262 |
-
{
|
263 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
264 |
-
$response = $client->request('GET', 'http://localhost:8057/301/bad-tld');
|
265 |
-
|
266 |
-
try {
|
267 |
-
$response->getStatusCode();
|
268 |
-
$this->fail(TransportExceptionInterface::class.' expected');
|
269 |
-
} catch (TransportExceptionInterface $e) {
|
270 |
-
$this->addToAssertionCount(1);
|
271 |
-
}
|
272 |
-
|
273 |
-
try {
|
274 |
-
$response->getStatusCode();
|
275 |
-
$this->fail(TransportExceptionInterface::class.' still expected');
|
276 |
-
} catch (TransportExceptionInterface $e) {
|
277 |
-
$this->addToAssertionCount(1);
|
278 |
-
}
|
279 |
-
|
280 |
-
$response = $client->request('GET', 'http://localhost:8057/301/bad-tld');
|
281 |
-
|
282 |
-
try {
|
283 |
-
foreach ($client->stream($response) as $r => $chunk) {
|
284 |
-
}
|
285 |
-
$this->fail(TransportExceptionInterface::class.' expected');
|
286 |
-
} catch (TransportExceptionInterface $e) {
|
287 |
-
$this->addToAssertionCount(1);
|
288 |
-
}
|
289 |
-
|
290 |
-
$this->assertSame($response, $r);
|
291 |
-
$this->assertNotNull($chunk->getError());
|
292 |
-
|
293 |
-
$this->expectException(TransportExceptionInterface::class);
|
294 |
-
foreach ($client->stream($response) as $chunk) {
|
295 |
-
}
|
296 |
-
}
|
297 |
-
|
298 |
-
public function testInlineAuth()
|
299 |
-
{
|
300 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
301 |
-
$response = $client->request('GET', 'http://foo:bar%3Dbar@localhost:8057');
|
302 |
-
|
303 |
-
$body = $response->toArray();
|
304 |
-
|
305 |
-
$this->assertSame('foo', $body['PHP_AUTH_USER']);
|
306 |
-
$this->assertSame('bar=bar', $body['PHP_AUTH_PW']);
|
307 |
-
}
|
308 |
-
|
309 |
-
public function testBadRequestBody()
|
310 |
-
{
|
311 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
312 |
-
|
313 |
-
$this->expectException(TransportExceptionInterface::class);
|
314 |
-
|
315 |
-
$response = $client->request('POST', 'http://localhost:8057/', [
|
316 |
-
'body' => function () { yield []; },
|
317 |
-
]);
|
318 |
-
|
319 |
-
$response->getStatusCode();
|
320 |
-
}
|
321 |
-
|
322 |
-
public function test304()
|
323 |
-
{
|
324 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
325 |
-
$response = $client->request('GET', 'http://localhost:8057/304', [
|
326 |
-
'headers' => ['If-Match' => '"abc"'],
|
327 |
-
'buffer' => false,
|
328 |
-
]);
|
329 |
-
|
330 |
-
$this->assertSame(304, $response->getStatusCode());
|
331 |
-
$this->assertSame('', $response->getContent(false));
|
332 |
-
}
|
333 |
-
|
334 |
-
public function testRedirects()
|
335 |
-
{
|
336 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
337 |
-
$response = $client->request('POST', 'http://localhost:8057/301', [
|
338 |
-
'auth_basic' => 'foo:bar',
|
339 |
-
'body' => function () {
|
340 |
-
yield 'foo=bar';
|
341 |
-
},
|
342 |
-
]);
|
343 |
-
|
344 |
-
$body = $response->toArray();
|
345 |
-
$this->assertSame('GET', $body['REQUEST_METHOD']);
|
346 |
-
$this->assertSame('Basic Zm9vOmJhcg==', $body['HTTP_AUTHORIZATION']);
|
347 |
-
$this->assertSame('http://localhost:8057/', $response->getInfo('url'));
|
348 |
-
|
349 |
-
$this->assertSame(2, $response->getInfo('redirect_count'));
|
350 |
-
$this->assertNull($response->getInfo('redirect_url'));
|
351 |
-
|
352 |
-
$expected = [
|
353 |
-
'HTTP/1.1 301 Moved Permanently',
|
354 |
-
'Location: http://127.0.0.1:8057/302',
|
355 |
-
'Content-Type: application/json',
|
356 |
-
'HTTP/1.1 302 Found',
|
357 |
-
'Location: http://localhost:8057/',
|
358 |
-
'Content-Type: application/json',
|
359 |
-
'HTTP/1.1 200 OK',
|
360 |
-
'Content-Type: application/json',
|
361 |
-
];
|
362 |
-
|
363 |
-
$filteredHeaders = array_values(array_filter($response->getInfo('response_headers'), function ($h) {
|
364 |
-
return \in_array(substr($h, 0, 4), ['HTTP', 'Loca', 'Cont'], true) && 'Content-Encoding: gzip' !== $h;
|
365 |
-
}));
|
366 |
-
|
367 |
-
$this->assertSame($expected, $filteredHeaders);
|
368 |
-
}
|
369 |
-
|
370 |
-
public function testInvalidRedirect()
|
371 |
-
{
|
372 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
373 |
-
$response = $client->request('GET', 'http://localhost:8057/301/invalid');
|
374 |
-
|
375 |
-
$this->assertSame(301, $response->getStatusCode());
|
376 |
-
$this->assertSame(['//?foo=bar'], $response->getHeaders(false)['location']);
|
377 |
-
$this->assertSame(0, $response->getInfo('redirect_count'));
|
378 |
-
$this->assertNull($response->getInfo('redirect_url'));
|
379 |
-
|
380 |
-
$this->expectException(RedirectionExceptionInterface::class);
|
381 |
-
$response->getHeaders();
|
382 |
-
}
|
383 |
-
|
384 |
-
public function testRelativeRedirects()
|
385 |
-
{
|
386 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
387 |
-
$response = $client->request('GET', 'http://localhost:8057/302/relative');
|
388 |
-
|
389 |
-
$body = $response->toArray();
|
390 |
-
|
391 |
-
$this->assertSame('/', $body['REQUEST_URI']);
|
392 |
-
$this->assertNull($response->getInfo('redirect_url'));
|
393 |
-
|
394 |
-
$response = $client->request('GET', 'http://localhost:8057/302/relative', [
|
395 |
-
'max_redirects' => 0,
|
396 |
-
]);
|
397 |
-
|
398 |
-
$this->assertSame(302, $response->getStatusCode());
|
399 |
-
$this->assertSame('http://localhost:8057/', $response->getInfo('redirect_url'));
|
400 |
-
}
|
401 |
-
|
402 |
-
public function testRedirect307()
|
403 |
-
{
|
404 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
405 |
-
|
406 |
-
$response = $client->request('POST', 'http://localhost:8057/307', [
|
407 |
-
'body' => function () {
|
408 |
-
yield 'foo=bar';
|
409 |
-
},
|
410 |
-
'max_redirects' => 0,
|
411 |
-
]);
|
412 |
-
|
413 |
-
$this->assertSame(307, $response->getStatusCode());
|
414 |
-
|
415 |
-
$response = $client->request('POST', 'http://localhost:8057/307', [
|
416 |
-
'body' => 'foo=bar',
|
417 |
-
]);
|
418 |
-
|
419 |
-
$body = $response->toArray();
|
420 |
-
|
421 |
-
$this->assertSame(['foo' => 'bar', 'REQUEST_METHOD' => 'POST'], $body);
|
422 |
-
}
|
423 |
-
|
424 |
-
public function testMaxRedirects()
|
425 |
-
{
|
426 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
427 |
-
$response = $client->request('GET', 'http://localhost:8057/301', [
|
428 |
-
'max_redirects' => 1,
|
429 |
-
'auth_basic' => 'foo:bar',
|
430 |
-
]);
|
431 |
-
|
432 |
-
try {
|
433 |
-
$response->getHeaders();
|
434 |
-
$this->fail(RedirectionExceptionInterface::class.' expected');
|
435 |
-
} catch (RedirectionExceptionInterface $e) {
|
436 |
-
}
|
437 |
-
|
438 |
-
$this->assertSame(302, $response->getStatusCode());
|
439 |
-
$this->assertSame(1, $response->getInfo('redirect_count'));
|
440 |
-
$this->assertSame('http://localhost:8057/', $response->getInfo('redirect_url'));
|
441 |
-
|
442 |
-
$expected = [
|
443 |
-
'HTTP/1.1 301 Moved Permanently',
|
444 |
-
'Location: http://127.0.0.1:8057/302',
|
445 |
-
'Content-Type: application/json',
|
446 |
-
'HTTP/1.1 302 Found',
|
447 |
-
'Location: http://localhost:8057/',
|
448 |
-
'Content-Type: application/json',
|
449 |
-
];
|
450 |
-
|
451 |
-
$filteredHeaders = array_values(array_filter($response->getInfo('response_headers'), function ($h) {
|
452 |
-
return \in_array(substr($h, 0, 4), ['HTTP', 'Loca', 'Cont'], true);
|
453 |
-
}));
|
454 |
-
|
455 |
-
$this->assertSame($expected, $filteredHeaders);
|
456 |
-
}
|
457 |
-
|
458 |
-
public function testStream()
|
459 |
-
{
|
460 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
461 |
-
|
462 |
-
$response = $client->request('GET', 'http://localhost:8057');
|
463 |
-
$chunks = $client->stream($response);
|
464 |
-
$result = [];
|
465 |
-
|
466 |
-
foreach ($chunks as $r => $chunk) {
|
467 |
-
if ($chunk->isTimeout()) {
|
468 |
-
$result[] = 't';
|
469 |
-
} elseif ($chunk->isLast()) {
|
470 |
-
$result[] = 'l';
|
471 |
-
} elseif ($chunk->isFirst()) {
|
472 |
-
$result[] = 'f';
|
473 |
-
}
|
474 |
-
}
|
475 |
-
|
476 |
-
$this->assertSame($response, $r);
|
477 |
-
$this->assertSame(['f', 'l'], $result);
|
478 |
-
|
479 |
-
$chunk = null;
|
480 |
-
$i = 0;
|
481 |
-
|
482 |
-
foreach ($client->stream($response) as $chunk) {
|
483 |
-
++$i;
|
484 |
-
}
|
485 |
-
|
486 |
-
$this->assertSame(1, $i);
|
487 |
-
$this->assertTrue($chunk->isLast());
|
488 |
-
}
|
489 |
-
|
490 |
-
public function testAddToStream()
|
491 |
-
{
|
492 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
493 |
-
|
494 |
-
$r1 = $client->request('GET', 'http://localhost:8057');
|
495 |
-
|
496 |
-
$completed = [];
|
497 |
-
|
498 |
-
$pool = [$r1];
|
499 |
-
|
500 |
-
while ($pool) {
|
501 |
-
$chunks = $client->stream($pool);
|
502 |
-
$pool = [];
|
503 |
-
|
504 |
-
foreach ($chunks as $r => $chunk) {
|
505 |
-
if (!$chunk->isLast()) {
|
506 |
-
continue;
|
507 |
-
}
|
508 |
-
|
509 |
-
if ($r1 === $r) {
|
510 |
-
$r2 = $client->request('GET', 'http://localhost:8057');
|
511 |
-
$pool[] = $r2;
|
512 |
-
}
|
513 |
-
|
514 |
-
$completed[] = $r;
|
515 |
-
}
|
516 |
-
}
|
517 |
-
|
518 |
-
$this->assertSame([$r1, $r2], $completed);
|
519 |
-
}
|
520 |
-
|
521 |
-
public function testCompleteTypeError()
|
522 |
-
{
|
523 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
524 |
-
|
525 |
-
$this->expectException(\TypeError::class);
|
526 |
-
$client->stream(123);
|
527 |
-
}
|
528 |
-
|
529 |
-
public function testOnProgress()
|
530 |
-
{
|
531 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
532 |
-
$response = $client->request('POST', 'http://localhost:8057/post', [
|
533 |
-
'headers' => ['Content-Length' => 14],
|
534 |
-
'body' => 'foo=0123456789',
|
535 |
-
'on_progress' => function (...$state) use (&$steps) { $steps[] = $state; },
|
536 |
-
]);
|
537 |
-
|
538 |
-
$body = $response->toArray();
|
539 |
-
|
540 |
-
$this->assertSame(['foo' => '0123456789', 'REQUEST_METHOD' => 'POST'], $body);
|
541 |
-
$this->assertSame([0, 0], \array_slice($steps[0], 0, 2));
|
542 |
-
$lastStep = \array_slice($steps, -1)[0];
|
543 |
-
$this->assertSame([57, 57], \array_slice($lastStep, 0, 2));
|
544 |
-
$this->assertSame('http://localhost:8057/post', $steps[0][2]['url']);
|
545 |
-
}
|
546 |
-
|
547 |
-
public function testPostJson()
|
548 |
-
{
|
549 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
550 |
-
|
551 |
-
$response = $client->request('POST', 'http://localhost:8057/post', [
|
552 |
-
'json' => ['foo' => 'bar'],
|
553 |
-
]);
|
554 |
-
|
555 |
-
$body = $response->toArray();
|
556 |
-
|
557 |
-
$this->assertStringContainsString('json', $body['content-type']);
|
558 |
-
unset($body['content-type']);
|
559 |
-
$this->assertSame(['foo' => 'bar', 'REQUEST_METHOD' => 'POST'], $body);
|
560 |
-
}
|
561 |
-
|
562 |
-
public function testPostArray()
|
563 |
-
{
|
564 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
565 |
-
|
566 |
-
$response = $client->request('POST', 'http://localhost:8057/post', [
|
567 |
-
'body' => ['foo' => 'bar'],
|
568 |
-
]);
|
569 |
-
|
570 |
-
$this->assertSame(['foo' => 'bar', 'REQUEST_METHOD' => 'POST'], $response->toArray());
|
571 |
-
}
|
572 |
-
|
573 |
-
public function testPostResource()
|
574 |
-
{
|
575 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
576 |
-
|
577 |
-
$h = fopen('php://temp', 'w+');
|
578 |
-
fwrite($h, 'foo=0123456789');
|
579 |
-
rewind($h);
|
580 |
-
|
581 |
-
$response = $client->request('POST', 'http://localhost:8057/post', [
|
582 |
-
'body' => $h,
|
583 |
-
]);
|
584 |
-
|
585 |
-
$body = $response->toArray();
|
586 |
-
|
587 |
-
$this->assertSame(['foo' => '0123456789', 'REQUEST_METHOD' => 'POST'], $body);
|
588 |
-
}
|
589 |
-
|
590 |
-
public function testPostCallback()
|
591 |
-
{
|
592 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
593 |
-
|
594 |
-
$response = $client->request('POST', 'http://localhost:8057/post', [
|
595 |
-
'body' => function () {
|
596 |
-
yield 'foo';
|
597 |
-
yield '';
|
598 |
-
yield '=';
|
599 |
-
yield '0123456789';
|
600 |
-
},
|
601 |
-
]);
|
602 |
-
|
603 |
-
$this->assertSame(['foo' => '0123456789', 'REQUEST_METHOD' => 'POST'], $response->toArray());
|
604 |
-
}
|
605 |
-
|
606 |
-
public function testCancel()
|
607 |
-
{
|
608 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
609 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-header');
|
610 |
-
|
611 |
-
$response->cancel();
|
612 |
-
$this->expectException(TransportExceptionInterface::class);
|
613 |
-
$response->getHeaders();
|
614 |
-
}
|
615 |
-
|
616 |
-
public function testInfoOnCanceledResponse()
|
617 |
-
{
|
618 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
619 |
-
|
620 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-header');
|
621 |
-
|
622 |
-
$this->assertFalse($response->getInfo('canceled'));
|
623 |
-
$response->cancel();
|
624 |
-
$this->assertTrue($response->getInfo('canceled'));
|
625 |
-
}
|
626 |
-
|
627 |
-
public function testCancelInStream()
|
628 |
-
{
|
629 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
630 |
-
$response = $client->request('GET', 'http://localhost:8057/404');
|
631 |
-
|
632 |
-
foreach ($client->stream($response) as $chunk) {
|
633 |
-
$response->cancel();
|
634 |
-
}
|
635 |
-
|
636 |
-
$this->expectException(TransportExceptionInterface::class);
|
637 |
-
|
638 |
-
foreach ($client->stream($response) as $chunk) {
|
639 |
-
}
|
640 |
-
}
|
641 |
-
|
642 |
-
public function testOnProgressCancel()
|
643 |
-
{
|
644 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
645 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-body', [
|
646 |
-
'on_progress' => function ($dlNow) {
|
647 |
-
if (0 < $dlNow) {
|
648 |
-
throw new \Exception('Aborting the request.');
|
649 |
-
}
|
650 |
-
},
|
651 |
-
]);
|
652 |
-
|
653 |
-
try {
|
654 |
-
foreach ($client->stream([$response]) as $chunk) {
|
655 |
-
}
|
656 |
-
$this->fail(ClientExceptionInterface::class.' expected');
|
657 |
-
} catch (TransportExceptionInterface $e) {
|
658 |
-
$this->assertSame('Aborting the request.', $e->getPrevious()->getMessage());
|
659 |
-
}
|
660 |
-
|
661 |
-
$this->assertNotNull($response->getInfo('error'));
|
662 |
-
$this->expectException(TransportExceptionInterface::class);
|
663 |
-
$response->getContent();
|
664 |
-
}
|
665 |
-
|
666 |
-
public function testOnProgressError()
|
667 |
-
{
|
668 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
669 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-body', [
|
670 |
-
'on_progress' => function ($dlNow) {
|
671 |
-
if (0 < $dlNow) {
|
672 |
-
throw new \Error('BUG.');
|
673 |
-
}
|
674 |
-
},
|
675 |
-
]);
|
676 |
-
|
677 |
-
try {
|
678 |
-
foreach ($client->stream([$response]) as $chunk) {
|
679 |
-
}
|
680 |
-
$this->fail('Error expected');
|
681 |
-
} catch (\Error $e) {
|
682 |
-
$this->assertSame('BUG.', $e->getMessage());
|
683 |
-
}
|
684 |
-
|
685 |
-
$this->assertNotNull($response->getInfo('error'));
|
686 |
-
$this->expectException(TransportExceptionInterface::class);
|
687 |
-
$response->getContent();
|
688 |
-
}
|
689 |
-
|
690 |
-
public function testResolve()
|
691 |
-
{
|
692 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
693 |
-
$response = $client->request('GET', 'http://symfony.com:8057/', [
|
694 |
-
'resolve' => ['symfony.com' => '127.0.0.1'],
|
695 |
-
]);
|
696 |
-
|
697 |
-
$this->assertSame(200, $response->getStatusCode());
|
698 |
-
$this->assertSame(200, $client->request('GET', 'http://symfony.com:8057/')->getStatusCode());
|
699 |
-
|
700 |
-
$response = null;
|
701 |
-
$this->expectException(TransportExceptionInterface::class);
|
702 |
-
$client->request('GET', 'http://symfony.com:8057/', ['timeout' => 1]);
|
703 |
-
}
|
704 |
-
|
705 |
-
public function testIdnResolve()
|
706 |
-
{
|
707 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
708 |
-
|
709 |
-
$response = $client->request('GET', 'http://0-------------------------------------------------------------0.com:8057/', [
|
710 |
-
'resolve' => ['0-------------------------------------------------------------0.com' => '127.0.0.1'],
|
711 |
-
]);
|
712 |
-
|
713 |
-
$this->assertSame(200, $response->getStatusCode());
|
714 |
-
|
715 |
-
$response = $client->request('GET', 'http://Bücher.example:8057/', [
|
716 |
-
'resolve' => ['xn--bcher-kva.example' => '127.0.0.1'],
|
717 |
-
]);
|
718 |
-
|
719 |
-
$this->assertSame(200, $response->getStatusCode());
|
720 |
-
}
|
721 |
-
|
722 |
-
public function testNotATimeout()
|
723 |
-
{
|
724 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
725 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-header', [
|
726 |
-
'timeout' => 0.9,
|
727 |
-
]);
|
728 |
-
sleep(1);
|
729 |
-
$this->assertSame(200, $response->getStatusCode());
|
730 |
-
}
|
731 |
-
|
732 |
-
public function testTimeoutOnAccess()
|
733 |
-
{
|
734 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
735 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-header', [
|
736 |
-
'timeout' => 0.1,
|
737 |
-
]);
|
738 |
-
|
739 |
-
$this->expectException(TransportExceptionInterface::class);
|
740 |
-
$response->getHeaders();
|
741 |
-
}
|
742 |
-
|
743 |
-
public function testTimeoutIsNotAFatalError()
|
744 |
-
{
|
745 |
-
usleep(300000); // wait for the previous test to release the server
|
746 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
747 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-body', [
|
748 |
-
'timeout' => 0.25,
|
749 |
-
]);
|
750 |
-
|
751 |
-
try {
|
752 |
-
$response->getContent();
|
753 |
-
$this->fail(TimeoutExceptionInterface::class.' expected');
|
754 |
-
} catch (TimeoutExceptionInterface $e) {
|
755 |
-
}
|
756 |
-
|
757 |
-
for ($i = 0; $i < 10; ++$i) {
|
758 |
-
try {
|
759 |
-
$this->assertSame('<1><2>', $response->getContent());
|
760 |
-
break;
|
761 |
-
} catch (TimeoutExceptionInterface $e) {
|
762 |
-
}
|
763 |
-
}
|
764 |
-
|
765 |
-
if (10 === $i) {
|
766 |
-
throw $e;
|
767 |
-
}
|
768 |
-
}
|
769 |
-
|
770 |
-
public function testTimeoutOnStream()
|
771 |
-
{
|
772 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
773 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-body');
|
774 |
-
|
775 |
-
$this->assertSame(200, $response->getStatusCode());
|
776 |
-
$chunks = $client->stream([$response], 0.2);
|
777 |
-
|
778 |
-
$result = [];
|
779 |
-
|
780 |
-
foreach ($chunks as $r => $chunk) {
|
781 |
-
if ($chunk->isTimeout()) {
|
782 |
-
$result[] = 't';
|
783 |
-
} else {
|
784 |
-
$result[] = $chunk->getContent();
|
785 |
-
}
|
786 |
-
}
|
787 |
-
|
788 |
-
$this->assertSame(['<1>', 't'], $result);
|
789 |
-
|
790 |
-
$chunks = $client->stream([$response]);
|
791 |
-
|
792 |
-
foreach ($chunks as $r => $chunk) {
|
793 |
-
$this->assertSame('<2>', $chunk->getContent());
|
794 |
-
$this->assertSame('<1><2>', $r->getContent());
|
795 |
-
|
796 |
-
return;
|
797 |
-
}
|
798 |
-
|
799 |
-
$this->fail('The response should have completed');
|
800 |
-
}
|
801 |
-
|
802 |
-
public function testUncheckedTimeoutThrows()
|
803 |
-
{
|
804 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
805 |
-
$response = $client->request('GET', 'http://localhost:8057/timeout-body');
|
806 |
-
$chunks = $client->stream([$response], 0.1);
|
807 |
-
|
808 |
-
$this->expectException(TransportExceptionInterface::class);
|
809 |
-
|
810 |
-
foreach ($chunks as $r => $chunk) {
|
811 |
-
}
|
812 |
-
}
|
813 |
-
|
814 |
-
public function testTimeoutWithActiveConcurrentStream()
|
815 |
-
{
|
816 |
-
$p1 = TestHttpServer::start(8067);
|
817 |
-
$p2 = TestHttpServer::start(8077);
|
818 |
-
|
819 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
820 |
-
$streamingResponse = $client->request('GET', 'http://localhost:8067/max-duration');
|
821 |
-
$blockingResponse = $client->request('GET', 'http://localhost:8077/timeout-body', [
|
822 |
-
'timeout' => 0.25,
|
823 |
-
]);
|
824 |
-
|
825 |
-
$this->assertSame(200, $streamingResponse->getStatusCode());
|
826 |
-
$this->assertSame(200, $blockingResponse->getStatusCode());
|
827 |
-
|
828 |
-
$this->expectException(TransportExceptionInterface::class);
|
829 |
-
|
830 |
-
try {
|
831 |
-
$blockingResponse->getContent();
|
832 |
-
} finally {
|
833 |
-
$p1->stop();
|
834 |
-
$p2->stop();
|
835 |
-
}
|
836 |
-
}
|
837 |
-
|
838 |
-
public function testTimeoutOnInitialize()
|
839 |
-
{
|
840 |
-
$p1 = TestHttpServer::start(8067);
|
841 |
-
$p2 = TestHttpServer::start(8077);
|
842 |
-
|
843 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
844 |
-
$start = microtime(true);
|
845 |
-
$responses = [];
|
846 |
-
|
847 |
-
$responses[] = $client->request('GET', 'http://localhost:8067/timeout-header', ['timeout' => 0.25]);
|
848 |
-
$responses[] = $client->request('GET', 'http://localhost:8077/timeout-header', ['timeout' => 0.25]);
|
849 |
-
$responses[] = $client->request('GET', 'http://localhost:8067/timeout-header', ['timeout' => 0.25]);
|
850 |
-
$responses[] = $client->request('GET', 'http://localhost:8077/timeout-header', ['timeout' => 0.25]);
|
851 |
-
|
852 |
-
try {
|
853 |
-
foreach ($responses as $response) {
|
854 |
-
try {
|
855 |
-
$response->getContent();
|
856 |
-
$this->fail(TransportExceptionInterface::class.' expected');
|
857 |
-
} catch (TransportExceptionInterface $e) {
|
858 |
-
}
|
859 |
-
}
|
860 |
-
$responses = [];
|
861 |
-
|
862 |
-
$duration = microtime(true) - $start;
|
863 |
-
|
864 |
-
$this->assertLessThan(1.0, $duration);
|
865 |
-
} finally {
|
866 |
-
$p1->stop();
|
867 |
-
$p2->stop();
|
868 |
-
}
|
869 |
-
}
|
870 |
-
|
871 |
-
public function testTimeoutOnDestruct()
|
872 |
-
{
|
873 |
-
$p1 = TestHttpServer::start(8067);
|
874 |
-
$p2 = TestHttpServer::start(8077);
|
875 |
-
|
876 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
877 |
-
$start = microtime(true);
|
878 |
-
$responses = [];
|
879 |
-
|
880 |
-
$responses[] = $client->request('GET', 'http://localhost:8067/timeout-header', ['timeout' => 0.25]);
|
881 |
-
$responses[] = $client->request('GET', 'http://localhost:8077/timeout-header', ['timeout' => 0.25]);
|
882 |
-
$responses[] = $client->request('GET', 'http://localhost:8067/timeout-header', ['timeout' => 0.25]);
|
883 |
-
$responses[] = $client->request('GET', 'http://localhost:8077/timeout-header', ['timeout' => 0.25]);
|
884 |
-
|
885 |
-
try {
|
886 |
-
while ($response = array_shift($responses)) {
|
887 |
-
try {
|
888 |
-
unset($response);
|
889 |
-
$this->fail(TransportExceptionInterface::class.' expected');
|
890 |
-
} catch (TransportExceptionInterface $e) {
|
891 |
-
}
|
892 |
-
}
|
893 |
-
|
894 |
-
$duration = microtime(true) - $start;
|
895 |
-
|
896 |
-
$this->assertLessThan(1.0, $duration);
|
897 |
-
} finally {
|
898 |
-
$p1->stop();
|
899 |
-
$p2->stop();
|
900 |
-
}
|
901 |
-
}
|
902 |
-
|
903 |
-
public function testDestruct()
|
904 |
-
{
|
905 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
906 |
-
|
907 |
-
$start = microtime(true);
|
908 |
-
$client->request('GET', 'http://localhost:8057/timeout-long');
|
909 |
-
$client = null;
|
910 |
-
$duration = microtime(true) - $start;
|
911 |
-
|
912 |
-
$this->assertGreaterThan(1, $duration);
|
913 |
-
$this->assertLessThan(4, $duration);
|
914 |
-
}
|
915 |
-
|
916 |
-
public function testGetContentAfterDestruct()
|
917 |
-
{
|
918 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
919 |
-
|
920 |
-
try {
|
921 |
-
$client->request('GET', 'http://localhost:8057/404');
|
922 |
-
$this->fail(ClientExceptionInterface::class.' expected');
|
923 |
-
} catch (ClientExceptionInterface $e) {
|
924 |
-
$this->assertSame('GET', $e->getResponse()->toArray(false)['REQUEST_METHOD']);
|
925 |
-
}
|
926 |
-
}
|
927 |
-
|
928 |
-
public function testGetEncodedContentAfterDestruct()
|
929 |
-
{
|
930 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
931 |
-
|
932 |
-
try {
|
933 |
-
$client->request('GET', 'http://localhost:8057/404-gzipped');
|
934 |
-
$this->fail(ClientExceptionInterface::class.' expected');
|
935 |
-
} catch (ClientExceptionInterface $e) {
|
936 |
-
$this->assertSame('some text', $e->getResponse()->getContent(false));
|
937 |
-
}
|
938 |
-
}
|
939 |
-
|
940 |
-
public function testProxy()
|
941 |
-
{
|
942 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
943 |
-
$response = $client->request('GET', 'http://localhost:8057/', [
|
944 |
-
'proxy' => 'http://localhost:8057',
|
945 |
-
]);
|
946 |
-
|
947 |
-
$body = $response->toArray();
|
948 |
-
$this->assertSame('localhost:8057', $body['HTTP_HOST']);
|
949 |
-
$this->assertMatchesRegularExpression('#^http://(localhost|127\.0\.0\.1):8057/$#', $body['REQUEST_URI']);
|
950 |
-
|
951 |
-
$response = $client->request('GET', 'http://localhost:8057/', [
|
952 |
-
'proxy' => 'http://foo:b%3Dar@localhost:8057',
|
953 |
-
]);
|
954 |
-
|
955 |
-
$body = $response->toArray();
|
956 |
-
$this->assertSame('Basic Zm9vOmI9YXI=', $body['HTTP_PROXY_AUTHORIZATION']);
|
957 |
-
|
958 |
-
$_SERVER['http_proxy'] = 'http://localhost:8057';
|
959 |
-
try {
|
960 |
-
$response = $client->request('GET', 'http://localhost:8057/');
|
961 |
-
$body = $response->toArray();
|
962 |
-
$this->assertSame('localhost:8057', $body['HTTP_HOST']);
|
963 |
-
$this->assertMatchesRegularExpression('#^http://(localhost|127\.0\.0\.1):8057/$#', $body['REQUEST_URI']);
|
964 |
-
} finally {
|
965 |
-
unset($_SERVER['http_proxy']);
|
966 |
-
}
|
967 |
-
}
|
968 |
-
|
969 |
-
public function testNoProxy()
|
970 |
-
{
|
971 |
-
putenv('no_proxy='.$_SERVER['no_proxy'] = 'example.com, localhost');
|
972 |
-
|
973 |
-
try {
|
974 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
975 |
-
$response = $client->request('GET', 'http://localhost:8057/', [
|
976 |
-
'proxy' => 'http://localhost:8057',
|
977 |
-
]);
|
978 |
-
|
979 |
-
$body = $response->toArray();
|
980 |
-
|
981 |
-
$this->assertSame('HTTP/1.1', $body['SERVER_PROTOCOL']);
|
982 |
-
$this->assertSame('/', $body['REQUEST_URI']);
|
983 |
-
$this->assertSame('GET', $body['REQUEST_METHOD']);
|
984 |
-
} finally {
|
985 |
-
putenv('no_proxy');
|
986 |
-
unset($_SERVER['no_proxy']);
|
987 |
-
}
|
988 |
-
}
|
989 |
-
|
990 |
-
/**
|
991 |
-
* @requires extension zlib
|
992 |
-
*/
|
993 |
-
public function testAutoEncodingRequest()
|
994 |
-
{
|
995 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
996 |
-
$response = $client->request('GET', 'http://localhost:8057');
|
997 |
-
|
998 |
-
$this->assertSame(200, $response->getStatusCode());
|
999 |
-
|
1000 |
-
$headers = $response->getHeaders();
|
1001 |
-
|
1002 |
-
$this->assertSame(['Accept-Encoding'], $headers['vary']);
|
1003 |
-
$this->assertStringContainsString('gzip', $headers['content-encoding'][0]);
|
1004 |
-
|
1005 |
-
$body = $response->toArray();
|
1006 |
-
|
1007 |
-
$this->assertStringContainsString('gzip', $body['HTTP_ACCEPT_ENCODING']);
|
1008 |
-
}
|
1009 |
-
|
1010 |
-
public function testBaseUri()
|
1011 |
-
{
|
1012 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1013 |
-
$response = $client->request('GET', '../404', [
|
1014 |
-
'base_uri' => 'http://localhost:8057/abc/',
|
1015 |
-
]);
|
1016 |
-
|
1017 |
-
$this->assertSame(404, $response->getStatusCode());
|
1018 |
-
$this->assertSame(['application/json'], $response->getHeaders(false)['content-type']);
|
1019 |
-
}
|
1020 |
-
|
1021 |
-
public function testQuery()
|
1022 |
-
{
|
1023 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1024 |
-
$response = $client->request('GET', 'http://localhost:8057/?a=a', [
|
1025 |
-
'query' => ['b' => 'b'],
|
1026 |
-
]);
|
1027 |
-
|
1028 |
-
$body = $response->toArray();
|
1029 |
-
$this->assertSame('GET', $body['REQUEST_METHOD']);
|
1030 |
-
$this->assertSame('/?a=a&b=b', $body['REQUEST_URI']);
|
1031 |
-
}
|
1032 |
-
|
1033 |
-
public function testInformationalResponse()
|
1034 |
-
{
|
1035 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1036 |
-
$response = $client->request('GET', 'http://localhost:8057/103');
|
1037 |
-
|
1038 |
-
$this->assertSame('Here the body', $response->getContent());
|
1039 |
-
$this->assertSame(200, $response->getStatusCode());
|
1040 |
-
}
|
1041 |
-
|
1042 |
-
public function testInformationalResponseStream()
|
1043 |
-
{
|
1044 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1045 |
-
$response = $client->request('GET', 'http://localhost:8057/103');
|
1046 |
-
|
1047 |
-
$chunks = [];
|
1048 |
-
foreach ($client->stream($response) as $chunk) {
|
1049 |
-
$chunks[] = $chunk;
|
1050 |
-
}
|
1051 |
-
|
1052 |
-
$this->assertSame(103, $chunks[0]->getInformationalStatus()[0]);
|
1053 |
-
$this->assertSame(['</style.css>; rel=preload; as=style', '</script.js>; rel=preload; as=script'], $chunks[0]->getInformationalStatus()[1]['link']);
|
1054 |
-
$this->assertTrue($chunks[1]->isFirst());
|
1055 |
-
$this->assertSame('Here the body', $chunks[2]->getContent());
|
1056 |
-
$this->assertTrue($chunks[3]->isLast());
|
1057 |
-
$this->assertNull($chunks[3]->getInformationalStatus());
|
1058 |
-
|
1059 |
-
$this->assertSame(['date', 'content-length'], array_keys($response->getHeaders()));
|
1060 |
-
$this->assertContains('Link: </style.css>; rel=preload; as=style', $response->getInfo('response_headers'));
|
1061 |
-
}
|
1062 |
-
|
1063 |
-
/**
|
1064 |
-
* @requires extension zlib
|
1065 |
-
*/
|
1066 |
-
public function testUserlandEncodingRequest()
|
1067 |
-
{
|
1068 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1069 |
-
$response = $client->request('GET', 'http://localhost:8057', [
|
1070 |
-
'headers' => ['Accept-Encoding' => 'gzip'],
|
1071 |
-
]);
|
1072 |
-
|
1073 |
-
$headers = $response->getHeaders();
|
1074 |
-
|
1075 |
-
$this->assertSame(['Accept-Encoding'], $headers['vary']);
|
1076 |
-
$this->assertStringContainsString('gzip', $headers['content-encoding'][0]);
|
1077 |
-
|
1078 |
-
$body = $response->getContent();
|
1079 |
-
$this->assertSame("\x1F", $body[0]);
|
1080 |
-
|
1081 |
-
$body = json_decode(gzdecode($body), true);
|
1082 |
-
$this->assertSame('gzip', $body['HTTP_ACCEPT_ENCODING']);
|
1083 |
-
}
|
1084 |
-
|
1085 |
-
/**
|
1086 |
-
* @requires extension zlib
|
1087 |
-
*/
|
1088 |
-
public function testGzipBroken()
|
1089 |
-
{
|
1090 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1091 |
-
$response = $client->request('GET', 'http://localhost:8057/gzip-broken');
|
1092 |
-
|
1093 |
-
$this->expectException(TransportExceptionInterface::class);
|
1094 |
-
$response->getContent();
|
1095 |
-
}
|
1096 |
-
|
1097 |
-
public function testMaxDuration()
|
1098 |
-
{
|
1099 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1100 |
-
$response = $client->request('GET', 'http://localhost:8057/max-duration', [
|
1101 |
-
'max_duration' => 0.1,
|
1102 |
-
]);
|
1103 |
-
|
1104 |
-
$start = microtime(true);
|
1105 |
-
|
1106 |
-
try {
|
1107 |
-
$response->getContent();
|
1108 |
-
} catch (TransportExceptionInterface $e) {
|
1109 |
-
$this->addToAssertionCount(1);
|
1110 |
-
}
|
1111 |
-
|
1112 |
-
$duration = microtime(true) - $start;
|
1113 |
-
|
1114 |
-
$this->assertLessThan(10, $duration);
|
1115 |
-
}
|
1116 |
-
|
1117 |
-
public function testWithOptions()
|
1118 |
-
{
|
1119 |
-
$client = $this->getHttpClient(__FUNCTION__);
|
1120 |
-
if (!method_exists($client, 'withOptions')) {
|
1121 |
-
$this->markTestSkipped(sprintf('Not implementing "%s::withOptions()" is deprecated.', get_debug_type($client)));
|
1122 |
-
}
|
1123 |
-
|
1124 |
-
$client2 = $client->withOptions(['base_uri' => 'http://localhost:8057/']);
|
1125 |
-
|
1126 |
-
$this->assertNotSame($client, $client2);
|
1127 |
-
$this->assertSame(\get_class($client), \get_class($client2));
|
1128 |
-
|
1129 |
-
$response = $client2->request('GET', '/');
|
1130 |
-
$this->assertSame(200, $response->getStatusCode());
|
1131 |
-
}
|
1132 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/Test/TestHttpServer.php
DELETED
@@ -1,46 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\HttpClient\Test;
|
13 |
-
|
14 |
-
use Symfony\Component\Process\PhpExecutableFinder;
|
15 |
-
use Symfony\Component\Process\Process;
|
16 |
-
|
17 |
-
class TestHttpServer
|
18 |
-
{
|
19 |
-
private static $process = [];
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @return Process
|
23 |
-
*/
|
24 |
-
public static function start(int $port = 8057)
|
25 |
-
{
|
26 |
-
if (isset(self::$process[$port])) {
|
27 |
-
self::$process[$port]->stop();
|
28 |
-
} else {
|
29 |
-
register_shutdown_function(static function () use ($port) {
|
30 |
-
self::$process[$port]->stop();
|
31 |
-
});
|
32 |
-
}
|
33 |
-
|
34 |
-
$finder = new PhpExecutableFinder();
|
35 |
-
$process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', '127.0.0.1:'.$port]));
|
36 |
-
$process->setWorkingDirectory(__DIR__.'/Fixtures/web');
|
37 |
-
$process->start();
|
38 |
-
self::$process[$port] = $process;
|
39 |
-
|
40 |
-
do {
|
41 |
-
usleep(50000);
|
42 |
-
} while (!@fopen('http://127.0.0.1:'.$port, 'r'));
|
43 |
-
|
44 |
-
return $process;
|
45 |
-
}
|
46 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client-contracts/composer.json
DELETED
@@ -1,37 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "symfony/http-client-contracts",
|
3 |
-
"type": "library",
|
4 |
-
"description": "Generic abstractions related to HTTP clients",
|
5 |
-
"keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
|
6 |
-
"homepage": "https://symfony.com",
|
7 |
-
"license": "MIT",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "Nicolas Grekas",
|
11 |
-
"email": "p@tchwork.com"
|
12 |
-
},
|
13 |
-
{
|
14 |
-
"name": "Symfony Community",
|
15 |
-
"homepage": "https://symfony.com/contributors"
|
16 |
-
}
|
17 |
-
],
|
18 |
-
"require": {
|
19 |
-
"php": ">=7.2.5"
|
20 |
-
},
|
21 |
-
"suggest": {
|
22 |
-
"symfony/http-client-implementation": ""
|
23 |
-
},
|
24 |
-
"autoload": {
|
25 |
-
"psr-4": { "Symfony\\Contracts\\HttpClient\\": "" }
|
26 |
-
},
|
27 |
-
"minimum-stability": "dev",
|
28 |
-
"extra": {
|
29 |
-
"branch-alias": {
|
30 |
-
"dev-main": "2.5-dev"
|
31 |
-
},
|
32 |
-
"thanks": {
|
33 |
-
"name": "symfony/contracts",
|
34 |
-
"url": "https://github.com/symfony/contracts"
|
35 |
-
}
|
36 |
-
}
|
37 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/AmpHttpClient.php
DELETED
@@ -1,176 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Amp\CancelledException;
|
15 |
-
use Amp\Http\Client\DelegateHttpClient;
|
16 |
-
use Amp\Http\Client\InterceptedHttpClient;
|
17 |
-
use Amp\Http\Client\PooledHttpClient;
|
18 |
-
use Amp\Http\Client\Request;
|
19 |
-
use Amp\Http\Tunnel\Http1TunnelConnector;
|
20 |
-
use Psr\Log\LoggerAwareInterface;
|
21 |
-
use Psr\Log\LoggerAwareTrait;
|
22 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
23 |
-
use Symfony\Component\HttpClient\Internal\AmpClientState;
|
24 |
-
use Symfony\Component\HttpClient\Response\AmpResponse;
|
25 |
-
use Symfony\Component\HttpClient\Response\ResponseStream;
|
26 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
27 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
28 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
29 |
-
use Symfony\Contracts\Service\ResetInterface;
|
30 |
-
|
31 |
-
if (!interface_exists(DelegateHttpClient::class)) {
|
32 |
-
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\AmpHttpClient" as the "amphp/http-client" package is not installed. Try running "composer require amphp/http-client".');
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* A portable implementation of the HttpClientInterface contracts based on Amp's HTTP client.
|
37 |
-
*
|
38 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
39 |
-
*/
|
40 |
-
final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, ResetInterface
|
41 |
-
{
|
42 |
-
use HttpClientTrait;
|
43 |
-
use LoggerAwareTrait;
|
44 |
-
|
45 |
-
private $defaultOptions = self::OPTIONS_DEFAULTS;
|
46 |
-
private static $emptyDefaults = self::OPTIONS_DEFAULTS;
|
47 |
-
|
48 |
-
/** @var AmpClientState */
|
49 |
-
private $multi;
|
50 |
-
|
51 |
-
/**
|
52 |
-
* @param array $defaultOptions Default requests' options
|
53 |
-
* @param callable $clientConfigurator A callable that builds a {@see DelegateHttpClient} from a {@see PooledHttpClient};
|
54 |
-
* passing null builds an {@see InterceptedHttpClient} with 2 retries on failures
|
55 |
-
* @param int $maxHostConnections The maximum number of connections to a single host
|
56 |
-
* @param int $maxPendingPushes The maximum number of pushed responses to accept in the queue
|
57 |
-
*
|
58 |
-
* @see HttpClientInterface::OPTIONS_DEFAULTS for available options
|
59 |
-
*/
|
60 |
-
public function __construct(array $defaultOptions = [], callable $clientConfigurator = null, int $maxHostConnections = 6, int $maxPendingPushes = 50)
|
61 |
-
{
|
62 |
-
$this->defaultOptions['buffer'] = $this->defaultOptions['buffer'] ?? \Closure::fromCallable([__CLASS__, 'shouldBuffer']);
|
63 |
-
|
64 |
-
if ($defaultOptions) {
|
65 |
-
[, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions);
|
66 |
-
}
|
67 |
-
|
68 |
-
$this->multi = new AmpClientState($clientConfigurator, $maxHostConnections, $maxPendingPushes, $this->logger);
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* @see HttpClientInterface::OPTIONS_DEFAULTS for available options
|
73 |
-
*
|
74 |
-
* {@inheritdoc}
|
75 |
-
*/
|
76 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
77 |
-
{
|
78 |
-
[$url, $options] = self::prepareRequest($method, $url, $options, $this->defaultOptions);
|
79 |
-
|
80 |
-
$options['proxy'] = self::getProxy($options['proxy'], $url, $options['no_proxy']);
|
81 |
-
|
82 |
-
if (null !== $options['proxy'] && !class_exists(Http1TunnelConnector::class)) {
|
83 |
-
throw new \LogicException('You cannot use the "proxy" option as the "amphp/http-tunnel" package is not installed. Try running "composer require amphp/http-tunnel".');
|
84 |
-
}
|
85 |
-
|
86 |
-
if ($options['bindto']) {
|
87 |
-
if (0 === strpos($options['bindto'], 'if!')) {
|
88 |
-
throw new TransportException(__CLASS__.' cannot bind to network interfaces, use e.g. CurlHttpClient instead.');
|
89 |
-
}
|
90 |
-
if (0 === strpos($options['bindto'], 'host!')) {
|
91 |
-
$options['bindto'] = substr($options['bindto'], 5);
|
92 |
-
}
|
93 |
-
}
|
94 |
-
|
95 |
-
if (('' !== $options['body'] || 'POST' === $method || isset($options['normalized_headers']['content-length'])) && !isset($options['normalized_headers']['content-type'])) {
|
96 |
-
$options['headers'][] = 'Content-Type: application/x-www-form-urlencoded';
|
97 |
-
}
|
98 |
-
|
99 |
-
if (!isset($options['normalized_headers']['user-agent'])) {
|
100 |
-
$options['headers'][] = 'User-Agent: Symfony HttpClient/Amp';
|
101 |
-
}
|
102 |
-
|
103 |
-
if (0 < $options['max_duration']) {
|
104 |
-
$options['timeout'] = min($options['max_duration'], $options['timeout']);
|
105 |
-
}
|
106 |
-
|
107 |
-
if ($options['resolve']) {
|
108 |
-
$this->multi->dnsCache = $options['resolve'] + $this->multi->dnsCache;
|
109 |
-
}
|
110 |
-
|
111 |
-
if ($options['peer_fingerprint'] && !isset($options['peer_fingerprint']['pin-sha256'])) {
|
112 |
-
throw new TransportException(__CLASS__.' supports only "pin-sha256" fingerprints.');
|
113 |
-
}
|
114 |
-
|
115 |
-
$request = new Request(implode('', $url), $method);
|
116 |
-
|
117 |
-
if ($options['http_version']) {
|
118 |
-
switch ((float) $options['http_version']) {
|
119 |
-
case 1.0: $request->setProtocolVersions(['1.0']); break;
|
120 |
-
case 1.1: $request->setProtocolVersions(['1.1', '1.0']); break;
|
121 |
-
default: $request->setProtocolVersions(['2', '1.1', '1.0']); break;
|
122 |
-
}
|
123 |
-
}
|
124 |
-
|
125 |
-
foreach ($options['headers'] as $v) {
|
126 |
-
$h = explode(': ', $v, 2);
|
127 |
-
$request->addHeader($h[0], $h[1]);
|
128 |
-
}
|
129 |
-
|
130 |
-
$request->setTcpConnectTimeout(1000 * $options['timeout']);
|
131 |
-
$request->setTlsHandshakeTimeout(1000 * $options['timeout']);
|
132 |
-
$request->setTransferTimeout(1000 * $options['max_duration']);
|
133 |
-
if (method_exists($request, 'setInactivityTimeout')) {
|
134 |
-
$request->setInactivityTimeout(0);
|
135 |
-
}
|
136 |
-
|
137 |
-
if ('' !== $request->getUri()->getUserInfo() && !$request->hasHeader('authorization')) {
|
138 |
-
$auth = explode(':', $request->getUri()->getUserInfo(), 2);
|
139 |
-
$auth = array_map('rawurldecode', $auth) + [1 => ''];
|
140 |
-
$request->setHeader('Authorization', 'Basic '.base64_encode(implode(':', $auth)));
|
141 |
-
}
|
142 |
-
|
143 |
-
return new AmpResponse($this->multi, $request, $options, $this->logger);
|
144 |
-
}
|
145 |
-
|
146 |
-
/**
|
147 |
-
* {@inheritdoc}
|
148 |
-
*/
|
149 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
150 |
-
{
|
151 |
-
if ($responses instanceof AmpResponse) {
|
152 |
-
$responses = [$responses];
|
153 |
-
} elseif (!is_iterable($responses)) {
|
154 |
-
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of AmpResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
|
155 |
-
}
|
156 |
-
|
157 |
-
return new ResponseStream(AmpResponse::stream($responses, $timeout));
|
158 |
-
}
|
159 |
-
|
160 |
-
public function reset()
|
161 |
-
{
|
162 |
-
$this->multi->dnsCache = [];
|
163 |
-
|
164 |
-
foreach ($this->multi->pushedResponses as $authority => $pushedResponses) {
|
165 |
-
foreach ($pushedResponses as [$pushedUrl, $pushDeferred]) {
|
166 |
-
$pushDeferred->fail(new CancelledException());
|
167 |
-
|
168 |
-
if ($this->logger) {
|
169 |
-
$this->logger->debug(sprintf('Unused pushed response: "%s"', $pushedUrl));
|
170 |
-
}
|
171 |
-
}
|
172 |
-
}
|
173 |
-
|
174 |
-
$this->multi->pushedResponses = [];
|
175 |
-
}
|
176 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/AsyncDecoratorTrait.php
DELETED
@@ -1,48 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Response\AsyncResponse;
|
15 |
-
use Symfony\Component\HttpClient\Response\ResponseStream;
|
16 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
17 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Eases with processing responses while streaming them.
|
21 |
-
*
|
22 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
23 |
-
*/
|
24 |
-
trait AsyncDecoratorTrait
|
25 |
-
{
|
26 |
-
use DecoratorTrait;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* {@inheritdoc}
|
30 |
-
*
|
31 |
-
* @return AsyncResponse
|
32 |
-
*/
|
33 |
-
abstract public function request(string $method, string $url, array $options = []): ResponseInterface;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* {@inheritdoc}
|
37 |
-
*/
|
38 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
39 |
-
{
|
40 |
-
if ($responses instanceof AsyncResponse) {
|
41 |
-
$responses = [$responses];
|
42 |
-
} elseif (!is_iterable($responses)) {
|
43 |
-
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of AsyncResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
|
44 |
-
}
|
45 |
-
|
46 |
-
return new ResponseStream(AsyncResponse::stream($responses, $timeout, static::class));
|
47 |
-
}
|
48 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/CHANGELOG.md
DELETED
@@ -1,54 +0,0 @@
|
|
1 |
-
CHANGELOG
|
2 |
-
=========
|
3 |
-
|
4 |
-
5.4
|
5 |
-
---
|
6 |
-
|
7 |
-
* Add `MockHttpClient::setResponseFactory()` method to be able to set response factory after client creating
|
8 |
-
|
9 |
-
5.3
|
10 |
-
---
|
11 |
-
|
12 |
-
* Implement `HttpClientInterface::withOptions()` from `symfony/contracts` v2.4
|
13 |
-
* Add `DecoratorTrait` to ease writing simple decorators
|
14 |
-
|
15 |
-
5.2.0
|
16 |
-
-----
|
17 |
-
|
18 |
-
* added `AsyncDecoratorTrait` to ease processing responses without breaking async
|
19 |
-
* added support for pausing responses with a new `pause_handler` callable exposed as an info item
|
20 |
-
* added `StreamableInterface` to ease turning responses into PHP streams
|
21 |
-
* added `MockResponse::getRequestMethod()` and `getRequestUrl()` to allow inspecting which request has been sent
|
22 |
-
* added `EventSourceHttpClient` a Server-Sent events stream implementing the [EventSource specification](https://www.w3.org/TR/eventsource/#eventsource)
|
23 |
-
* added option "extra.curl" to allow setting additional curl options in `CurlHttpClient`
|
24 |
-
* added `RetryableHttpClient` to automatically retry failed HTTP requests.
|
25 |
-
* added `extra.trace_content` option to `TraceableHttpClient` to prevent it from keeping the content in memory
|
26 |
-
|
27 |
-
5.1.0
|
28 |
-
-----
|
29 |
-
|
30 |
-
* added `NoPrivateNetworkHttpClient` decorator
|
31 |
-
* added `AmpHttpClient`, a portable HTTP/2 implementation based on Amp
|
32 |
-
* added `LoggerAwareInterface` to `ScopingHttpClient` and `TraceableHttpClient`
|
33 |
-
* made `HttpClient::create()` return an `AmpHttpClient` when `amphp/http-client` is found but curl is not or too old
|
34 |
-
|
35 |
-
4.4.0
|
36 |
-
-----
|
37 |
-
|
38 |
-
* added `canceled` to `ResponseInterface::getInfo()`
|
39 |
-
* added `HttpClient::createForBaseUri()`
|
40 |
-
* added `HttplugClient` with support for sync and async requests
|
41 |
-
* added `max_duration` option
|
42 |
-
* added support for NTLM authentication
|
43 |
-
* added `StreamWrapper` to cast any `ResponseInterface` instances to PHP streams.
|
44 |
-
* added `$response->toStream()` to cast responses to regular PHP streams
|
45 |
-
* made `Psr18Client` implement relevant PSR-17 factories and have streaming responses
|
46 |
-
* added `TraceableHttpClient`, `HttpClientDataCollector` and `HttpClientPass` to integrate with the web profiler
|
47 |
-
* allow enabling buffering conditionally with a Closure
|
48 |
-
* allow option "buffer" to be a stream resource
|
49 |
-
* allow arbitrary values for the "json" option
|
50 |
-
|
51 |
-
4.3.0
|
52 |
-
-----
|
53 |
-
|
54 |
-
* added the component
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/CachingHttpClient.php
DELETED
@@ -1,152 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Response\MockResponse;
|
15 |
-
use Symfony\Component\HttpClient\Response\ResponseStream;
|
16 |
-
use Symfony\Component\HttpFoundation\Request;
|
17 |
-
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
|
18 |
-
use Symfony\Component\HttpKernel\HttpCache\StoreInterface;
|
19 |
-
use Symfony\Component\HttpKernel\HttpClientKernel;
|
20 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
21 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
22 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
23 |
-
use Symfony\Contracts\Service\ResetInterface;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Adds caching on top of an HTTP client.
|
27 |
-
*
|
28 |
-
* The implementation buffers responses in memory and doesn't stream directly from the network.
|
29 |
-
* You can disable/enable this layer by setting option "no_cache" under "extra" to true/false.
|
30 |
-
* By default, caching is enabled unless the "buffer" option is set to false.
|
31 |
-
*
|
32 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
33 |
-
*/
|
34 |
-
class CachingHttpClient implements HttpClientInterface, ResetInterface
|
35 |
-
{
|
36 |
-
use HttpClientTrait;
|
37 |
-
|
38 |
-
private $client;
|
39 |
-
private $cache;
|
40 |
-
private $defaultOptions = self::OPTIONS_DEFAULTS;
|
41 |
-
|
42 |
-
public function __construct(HttpClientInterface $client, StoreInterface $store, array $defaultOptions = [])
|
43 |
-
{
|
44 |
-
if (!class_exists(HttpClientKernel::class)) {
|
45 |
-
throw new \LogicException(sprintf('Using "%s" requires that the HttpKernel component version 4.3 or higher is installed, try running "composer require symfony/http-kernel:^5.4".', __CLASS__));
|
46 |
-
}
|
47 |
-
|
48 |
-
$this->client = $client;
|
49 |
-
$kernel = new HttpClientKernel($client);
|
50 |
-
$this->cache = new HttpCache($kernel, $store, null, $defaultOptions);
|
51 |
-
|
52 |
-
unset($defaultOptions['debug']);
|
53 |
-
unset($defaultOptions['default_ttl']);
|
54 |
-
unset($defaultOptions['private_headers']);
|
55 |
-
unset($defaultOptions['allow_reload']);
|
56 |
-
unset($defaultOptions['allow_revalidate']);
|
57 |
-
unset($defaultOptions['stale_while_revalidate']);
|
58 |
-
unset($defaultOptions['stale_if_error']);
|
59 |
-
unset($defaultOptions['trace_level']);
|
60 |
-
unset($defaultOptions['trace_header']);
|
61 |
-
|
62 |
-
if ($defaultOptions) {
|
63 |
-
[, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions);
|
64 |
-
}
|
65 |
-
}
|
66 |
-
|
67 |
-
/**
|
68 |
-
* {@inheritdoc}
|
69 |
-
*/
|
70 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
71 |
-
{
|
72 |
-
[$url, $options] = $this->prepareRequest($method, $url, $options, $this->defaultOptions, true);
|
73 |
-
$url = implode('', $url);
|
74 |
-
|
75 |
-
if (!empty($options['body']) || !empty($options['extra']['no_cache']) || !\in_array($method, ['GET', 'HEAD', 'OPTIONS'])) {
|
76 |
-
return $this->client->request($method, $url, $options);
|
77 |
-
}
|
78 |
-
|
79 |
-
$request = Request::create($url, $method);
|
80 |
-
$request->attributes->set('http_client_options', $options);
|
81 |
-
|
82 |
-
foreach ($options['normalized_headers'] as $name => $values) {
|
83 |
-
if ('cookie' !== $name) {
|
84 |
-
foreach ($values as $value) {
|
85 |
-
$request->headers->set($name, substr($value, 2 + \strlen($name)), false);
|
86 |
-
}
|
87 |
-
|
88 |
-
continue;
|
89 |
-
}
|
90 |
-
|
91 |
-
foreach ($values as $cookies) {
|
92 |
-
foreach (explode('; ', substr($cookies, \strlen('Cookie: '))) as $cookie) {
|
93 |
-
if ('' !== $cookie) {
|
94 |
-
$cookie = explode('=', $cookie, 2);
|
95 |
-
$request->cookies->set($cookie[0], $cookie[1] ?? '');
|
96 |
-
}
|
97 |
-
}
|
98 |
-
}
|
99 |
-
}
|
100 |
-
|
101 |
-
$response = $this->cache->handle($request);
|
102 |
-
$response = new MockResponse($response->getContent(), [
|
103 |
-
'http_code' => $response->getStatusCode(),
|
104 |
-
'response_headers' => $response->headers->allPreserveCase(),
|
105 |
-
]);
|
106 |
-
|
107 |
-
return MockResponse::fromRequest($method, $url, $options, $response);
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* {@inheritdoc}
|
112 |
-
*/
|
113 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
114 |
-
{
|
115 |
-
if ($responses instanceof ResponseInterface) {
|
116 |
-
$responses = [$responses];
|
117 |
-
} elseif (!is_iterable($responses)) {
|
118 |
-
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of ResponseInterface objects, "%s" given.', __METHOD__, get_debug_type($responses)));
|
119 |
-
}
|
120 |
-
|
121 |
-
$mockResponses = [];
|
122 |
-
$clientResponses = [];
|
123 |
-
|
124 |
-
foreach ($responses as $response) {
|
125 |
-
if ($response instanceof MockResponse) {
|
126 |
-
$mockResponses[] = $response;
|
127 |
-
} else {
|
128 |
-
$clientResponses[] = $response;
|
129 |
-
}
|
130 |
-
}
|
131 |
-
|
132 |
-
if (!$mockResponses) {
|
133 |
-
return $this->client->stream($clientResponses, $timeout);
|
134 |
-
}
|
135 |
-
|
136 |
-
if (!$clientResponses) {
|
137 |
-
return new ResponseStream(MockResponse::stream($mockResponses, $timeout));
|
138 |
-
}
|
139 |
-
|
140 |
-
return new ResponseStream((function () use ($mockResponses, $clientResponses, $timeout) {
|
141 |
-
yield from MockResponse::stream($mockResponses, $timeout);
|
142 |
-
yield $this->client->stream($clientResponses, $timeout);
|
143 |
-
})());
|
144 |
-
}
|
145 |
-
|
146 |
-
public function reset()
|
147 |
-
{
|
148 |
-
if ($this->client instanceof ResetInterface) {
|
149 |
-
$this->client->reset();
|
150 |
-
}
|
151 |
-
}
|
152 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Chunk/DataChunk.php
DELETED
@@ -1,87 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Chunk;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*
|
19 |
-
* @internal
|
20 |
-
*/
|
21 |
-
class DataChunk implements ChunkInterface
|
22 |
-
{
|
23 |
-
private $offset = 0;
|
24 |
-
private $content = '';
|
25 |
-
|
26 |
-
public function __construct(int $offset = 0, string $content = '')
|
27 |
-
{
|
28 |
-
$this->offset = $offset;
|
29 |
-
$this->content = $content;
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* {@inheritdoc}
|
34 |
-
*/
|
35 |
-
public function isTimeout(): bool
|
36 |
-
{
|
37 |
-
return false;
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* {@inheritdoc}
|
42 |
-
*/
|
43 |
-
public function isFirst(): bool
|
44 |
-
{
|
45 |
-
return false;
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* {@inheritdoc}
|
50 |
-
*/
|
51 |
-
public function isLast(): bool
|
52 |
-
{
|
53 |
-
return false;
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* {@inheritdoc}
|
58 |
-
*/
|
59 |
-
public function getInformationalStatus(): ?array
|
60 |
-
{
|
61 |
-
return null;
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* {@inheritdoc}
|
66 |
-
*/
|
67 |
-
public function getContent(): string
|
68 |
-
{
|
69 |
-
return $this->content;
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* {@inheritdoc}
|
74 |
-
*/
|
75 |
-
public function getOffset(): int
|
76 |
-
{
|
77 |
-
return $this->offset;
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* {@inheritdoc}
|
82 |
-
*/
|
83 |
-
public function getError(): ?string
|
84 |
-
{
|
85 |
-
return null;
|
86 |
-
}
|
87 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Chunk/ErrorChunk.php
DELETED
@@ -1,140 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Chunk;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Exception\TimeoutException;
|
15 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
16 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
*
|
21 |
-
* @internal
|
22 |
-
*/
|
23 |
-
class ErrorChunk implements ChunkInterface
|
24 |
-
{
|
25 |
-
private $didThrow = false;
|
26 |
-
private $offset;
|
27 |
-
private $errorMessage;
|
28 |
-
private $error;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* @param \Throwable|string $error
|
32 |
-
*/
|
33 |
-
public function __construct(int $offset, $error)
|
34 |
-
{
|
35 |
-
$this->offset = $offset;
|
36 |
-
|
37 |
-
if (\is_string($error)) {
|
38 |
-
$this->errorMessage = $error;
|
39 |
-
} else {
|
40 |
-
$this->error = $error;
|
41 |
-
$this->errorMessage = $error->getMessage();
|
42 |
-
}
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* {@inheritdoc}
|
47 |
-
*/
|
48 |
-
public function isTimeout(): bool
|
49 |
-
{
|
50 |
-
$this->didThrow = true;
|
51 |
-
|
52 |
-
if (null !== $this->error) {
|
53 |
-
throw new TransportException($this->errorMessage, 0, $this->error);
|
54 |
-
}
|
55 |
-
|
56 |
-
return true;
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* {@inheritdoc}
|
61 |
-
*/
|
62 |
-
public function isFirst(): bool
|
63 |
-
{
|
64 |
-
$this->didThrow = true;
|
65 |
-
throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* {@inheritdoc}
|
70 |
-
*/
|
71 |
-
public function isLast(): bool
|
72 |
-
{
|
73 |
-
$this->didThrow = true;
|
74 |
-
throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* {@inheritdoc}
|
79 |
-
*/
|
80 |
-
public function getInformationalStatus(): ?array
|
81 |
-
{
|
82 |
-
$this->didThrow = true;
|
83 |
-
throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
|
84 |
-
}
|
85 |
-
|
86 |
-
/**
|
87 |
-
* {@inheritdoc}
|
88 |
-
*/
|
89 |
-
public function getContent(): string
|
90 |
-
{
|
91 |
-
$this->didThrow = true;
|
92 |
-
throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* {@inheritdoc}
|
97 |
-
*/
|
98 |
-
public function getOffset(): int
|
99 |
-
{
|
100 |
-
return $this->offset;
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* {@inheritdoc}
|
105 |
-
*/
|
106 |
-
public function getError(): ?string
|
107 |
-
{
|
108 |
-
return $this->errorMessage;
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* @return bool Whether the wrapped error has been thrown or not
|
113 |
-
*/
|
114 |
-
public function didThrow(bool $didThrow = null): bool
|
115 |
-
{
|
116 |
-
if (null !== $didThrow && $this->didThrow !== $didThrow) {
|
117 |
-
return !$this->didThrow = $didThrow;
|
118 |
-
}
|
119 |
-
|
120 |
-
return $this->didThrow;
|
121 |
-
}
|
122 |
-
|
123 |
-
public function __sleep(): array
|
124 |
-
{
|
125 |
-
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
126 |
-
}
|
127 |
-
|
128 |
-
public function __wakeup()
|
129 |
-
{
|
130 |
-
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
131 |
-
}
|
132 |
-
|
133 |
-
public function __destruct()
|
134 |
-
{
|
135 |
-
if (!$this->didThrow) {
|
136 |
-
$this->didThrow = true;
|
137 |
-
throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
|
138 |
-
}
|
139 |
-
}
|
140 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Chunk/FirstChunk.php
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Chunk;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
16 |
-
*
|
17 |
-
* @internal
|
18 |
-
*/
|
19 |
-
class FirstChunk extends DataChunk
|
20 |
-
{
|
21 |
-
/**
|
22 |
-
* {@inheritdoc}
|
23 |
-
*/
|
24 |
-
public function isFirst(): bool
|
25 |
-
{
|
26 |
-
return true;
|
27 |
-
}
|
28 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Chunk/InformationalChunk.php
DELETED
@@ -1,35 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Chunk;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
16 |
-
*
|
17 |
-
* @internal
|
18 |
-
*/
|
19 |
-
class InformationalChunk extends DataChunk
|
20 |
-
{
|
21 |
-
private $status;
|
22 |
-
|
23 |
-
public function __construct(int $statusCode, array $headers)
|
24 |
-
{
|
25 |
-
$this->status = [$statusCode, $headers];
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* {@inheritdoc}
|
30 |
-
*/
|
31 |
-
public function getInformationalStatus(): ?array
|
32 |
-
{
|
33 |
-
return $this->status;
|
34 |
-
}
|
35 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Chunk/LastChunk.php
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Chunk;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
16 |
-
*
|
17 |
-
* @internal
|
18 |
-
*/
|
19 |
-
class LastChunk extends DataChunk
|
20 |
-
{
|
21 |
-
/**
|
22 |
-
* {@inheritdoc}
|
23 |
-
*/
|
24 |
-
public function isLast(): bool
|
25 |
-
{
|
26 |
-
return true;
|
27 |
-
}
|
28 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Chunk/ServerSentEvent.php
DELETED
@@ -1,79 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Chunk;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @author Antoine Bluchet <soyuka@gmail.com>
|
18 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
19 |
-
*/
|
20 |
-
final class ServerSentEvent extends DataChunk implements ChunkInterface
|
21 |
-
{
|
22 |
-
private $data = '';
|
23 |
-
private $id = '';
|
24 |
-
private $type = 'message';
|
25 |
-
private $retry = 0;
|
26 |
-
|
27 |
-
public function __construct(string $content)
|
28 |
-
{
|
29 |
-
parent::__construct(-1, $content);
|
30 |
-
|
31 |
-
// remove BOM
|
32 |
-
if (0 === strpos($content, "\xEF\xBB\xBF")) {
|
33 |
-
$content = substr($content, 3);
|
34 |
-
}
|
35 |
-
|
36 |
-
foreach (preg_split("/(?:\r\n|[\r\n])/", $content) as $line) {
|
37 |
-
if (0 === $i = strpos($line, ':')) {
|
38 |
-
continue;
|
39 |
-
}
|
40 |
-
|
41 |
-
$i = false === $i ? \strlen($line) : $i;
|
42 |
-
$field = substr($line, 0, $i);
|
43 |
-
$i += 1 + (' ' === ($line[1 + $i] ?? ''));
|
44 |
-
|
45 |
-
switch ($field) {
|
46 |
-
case 'id': $this->id = substr($line, $i); break;
|
47 |
-
case 'event': $this->type = substr($line, $i); break;
|
48 |
-
case 'data': $this->data .= ('' === $this->data ? '' : "\n").substr($line, $i); break;
|
49 |
-
case 'retry':
|
50 |
-
$retry = substr($line, $i);
|
51 |
-
|
52 |
-
if ('' !== $retry && \strlen($retry) === strspn($retry, '0123456789')) {
|
53 |
-
$this->retry = $retry / 1000.0;
|
54 |
-
}
|
55 |
-
break;
|
56 |
-
}
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
public function getId(): string
|
61 |
-
{
|
62 |
-
return $this->id;
|
63 |
-
}
|
64 |
-
|
65 |
-
public function getType(): string
|
66 |
-
{
|
67 |
-
return $this->type;
|
68 |
-
}
|
69 |
-
|
70 |
-
public function getData(): string
|
71 |
-
{
|
72 |
-
return $this->data;
|
73 |
-
}
|
74 |
-
|
75 |
-
public function getRetry(): float
|
76 |
-
{
|
77 |
-
return $this->retry;
|
78 |
-
}
|
79 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/CurlHttpClient.php
DELETED
@@ -1,551 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerAwareInterface;
|
15 |
-
use Psr\Log\LoggerInterface;
|
16 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
17 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
18 |
-
use Symfony\Component\HttpClient\Internal\CurlClientState;
|
19 |
-
use Symfony\Component\HttpClient\Internal\PushedResponse;
|
20 |
-
use Symfony\Component\HttpClient\Response\CurlResponse;
|
21 |
-
use Symfony\Component\HttpClient\Response\ResponseStream;
|
22 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
23 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
24 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
25 |
-
use Symfony\Contracts\Service\ResetInterface;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* A performant implementation of the HttpClientInterface contracts based on the curl extension.
|
29 |
-
*
|
30 |
-
* This provides fully concurrent HTTP requests, with transparent
|
31 |
-
* HTTP/2 push when a curl version that supports it is installed.
|
32 |
-
*
|
33 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
34 |
-
*/
|
35 |
-
final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, ResetInterface
|
36 |
-
{
|
37 |
-
use HttpClientTrait;
|
38 |
-
|
39 |
-
private $defaultOptions = self::OPTIONS_DEFAULTS + [
|
40 |
-
'auth_ntlm' => null, // array|string - an array containing the username as first value, and optionally the
|
41 |
-
// password as the second one; or string like username:password - enabling NTLM auth
|
42 |
-
'extra' => [
|
43 |
-
'curl' => [], // A list of extra curl options indexed by their corresponding CURLOPT_*
|
44 |
-
],
|
45 |
-
];
|
46 |
-
private static $emptyDefaults = self::OPTIONS_DEFAULTS + ['auth_ntlm' => null];
|
47 |
-
|
48 |
-
/**
|
49 |
-
* @var LoggerInterface|null
|
50 |
-
*/
|
51 |
-
private $logger;
|
52 |
-
|
53 |
-
/**
|
54 |
-
* An internal object to share state between the client and its responses.
|
55 |
-
*
|
56 |
-
* @var CurlClientState
|
57 |
-
*/
|
58 |
-
private $multi;
|
59 |
-
|
60 |
-
/**
|
61 |
-
* @param array $defaultOptions Default request's options
|
62 |
-
* @param int $maxHostConnections The maximum number of connections to a single host
|
63 |
-
* @param int $maxPendingPushes The maximum number of pushed responses to accept in the queue
|
64 |
-
*
|
65 |
-
* @see HttpClientInterface::OPTIONS_DEFAULTS for available options
|
66 |
-
*/
|
67 |
-
public function __construct(array $defaultOptions = [], int $maxHostConnections = 6, int $maxPendingPushes = 50)
|
68 |
-
{
|
69 |
-
if (!\extension_loaded('curl')) {
|
70 |
-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\CurlHttpClient" as the "curl" extension is not installed.');
|
71 |
-
}
|
72 |
-
|
73 |
-
$this->defaultOptions['buffer'] = $this->defaultOptions['buffer'] ?? \Closure::fromCallable([__CLASS__, 'shouldBuffer']);
|
74 |
-
|
75 |
-
if ($defaultOptions) {
|
76 |
-
[, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions);
|
77 |
-
}
|
78 |
-
|
79 |
-
$this->multi = new CurlClientState($maxHostConnections, $maxPendingPushes);
|
80 |
-
}
|
81 |
-
|
82 |
-
public function setLogger(LoggerInterface $logger): void
|
83 |
-
{
|
84 |
-
$this->logger = $this->multi->logger = $logger;
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* @see HttpClientInterface::OPTIONS_DEFAULTS for available options
|
89 |
-
*
|
90 |
-
* {@inheritdoc}
|
91 |
-
*/
|
92 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
93 |
-
{
|
94 |
-
[$url, $options] = self::prepareRequest($method, $url, $options, $this->defaultOptions);
|
95 |
-
$scheme = $url['scheme'];
|
96 |
-
$authority = $url['authority'];
|
97 |
-
$host = parse_url($authority, \PHP_URL_HOST);
|
98 |
-
$proxy = $options['proxy']
|
99 |
-
?? ('https:' === $url['scheme'] ? $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? null : null)
|
100 |
-
// Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities
|
101 |
-
?? $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null;
|
102 |
-
$url = implode('', $url);
|
103 |
-
|
104 |
-
if (!isset($options['normalized_headers']['user-agent'])) {
|
105 |
-
$options['headers'][] = 'User-Agent: Symfony HttpClient/Curl';
|
106 |
-
}
|
107 |
-
|
108 |
-
$curlopts = [
|
109 |
-
\CURLOPT_URL => $url,
|
110 |
-
\CURLOPT_TCP_NODELAY => true,
|
111 |
-
\CURLOPT_PROTOCOLS => \CURLPROTO_HTTP | \CURLPROTO_HTTPS,
|
112 |
-
\CURLOPT_REDIR_PROTOCOLS => \CURLPROTO_HTTP | \CURLPROTO_HTTPS,
|
113 |
-
\CURLOPT_FOLLOWLOCATION => true,
|
114 |
-
\CURLOPT_MAXREDIRS => 0 < $options['max_redirects'] ? $options['max_redirects'] : 0,
|
115 |
-
\CURLOPT_COOKIEFILE => '', // Keep track of cookies during redirects
|
116 |
-
\CURLOPT_TIMEOUT => 0,
|
117 |
-
\CURLOPT_PROXY => $proxy,
|
118 |
-
\CURLOPT_NOPROXY => $options['no_proxy'] ?? $_SERVER['no_proxy'] ?? $_SERVER['NO_PROXY'] ?? '',
|
119 |
-
\CURLOPT_SSL_VERIFYPEER => $options['verify_peer'],
|
120 |
-
\CURLOPT_SSL_VERIFYHOST => $options['verify_host'] ? 2 : 0,
|
121 |
-
\CURLOPT_CAINFO => $options['cafile'],
|
122 |
-
\CURLOPT_CAPATH => $options['capath'],
|
123 |
-
\CURLOPT_SSL_CIPHER_LIST => $options['ciphers'],
|
124 |
-
\CURLOPT_SSLCERT => $options['local_cert'],
|
125 |
-
\CURLOPT_SSLKEY => $options['local_pk'],
|
126 |
-
\CURLOPT_KEYPASSWD => $options['passphrase'],
|
127 |
-
\CURLOPT_CERTINFO => $options['capture_peer_cert_chain'],
|
128 |
-
];
|
129 |
-
|
130 |
-
if (1.0 === (float) $options['http_version']) {
|
131 |
-
$curlopts[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
|
132 |
-
} elseif (1.1 === (float) $options['http_version']) {
|
133 |
-
$curlopts[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
|
134 |
-
} elseif (\defined('CURL_VERSION_HTTP2') && (\CURL_VERSION_HTTP2 & CurlClientState::$curlVersion['features']) && ('https:' === $scheme || 2.0 === (float) $options['http_version'])) {
|
135 |
-
$curlopts[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
|
136 |
-
}
|
137 |
-
|
138 |
-
if (isset($options['auth_ntlm'])) {
|
139 |
-
$curlopts[\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM;
|
140 |
-
$curlopts[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
|
141 |
-
|
142 |
-
if (\is_array($options['auth_ntlm'])) {
|
143 |
-
$count = \count($options['auth_ntlm']);
|
144 |
-
if ($count <= 0 || $count > 2) {
|
145 |
-
throw new InvalidArgumentException(sprintf('Option "auth_ntlm" must contain 1 or 2 elements, %d given.', $count));
|
146 |
-
}
|
147 |
-
|
148 |
-
$options['auth_ntlm'] = implode(':', $options['auth_ntlm']);
|
149 |
-
}
|
150 |
-
|
151 |
-
if (!\is_string($options['auth_ntlm'])) {
|
152 |
-
throw new InvalidArgumentException(sprintf('Option "auth_ntlm" must be a string or an array, "%s" given.', get_debug_type($options['auth_ntlm'])));
|
153 |
-
}
|
154 |
-
|
155 |
-
$curlopts[\CURLOPT_USERPWD] = $options['auth_ntlm'];
|
156 |
-
}
|
157 |
-
|
158 |
-
if (!\ZEND_THREAD_SAFE) {
|
159 |
-
$curlopts[\CURLOPT_DNS_USE_GLOBAL_CACHE] = false;
|
160 |
-
}
|
161 |
-
|
162 |
-
if (\defined('CURLOPT_HEADEROPT') && \defined('CURLHEADER_SEPARATE')) {
|
163 |
-
$curlopts[\CURLOPT_HEADEROPT] = \CURLHEADER_SEPARATE;
|
164 |
-
}
|
165 |
-
|
166 |
-
// curl's resolve feature varies by host:port but ours varies by host only, let's handle this with our own DNS map
|
167 |
-
if (isset($this->multi->dnsCache->hostnames[$host])) {
|
168 |
-
$options['resolve'] += [$host => $this->multi->dnsCache->hostnames[$host]];
|
169 |
-
}
|
170 |
-
|
171 |
-
if ($options['resolve'] || $this->multi->dnsCache->evictions) {
|
172 |
-
// First reset any old DNS cache entries then add the new ones
|
173 |
-
$resolve = $this->multi->dnsCache->evictions;
|
174 |
-
$this->multi->dnsCache->evictions = [];
|
175 |
-
$port = parse_url($authority, \PHP_URL_PORT) ?: ('http:' === $scheme ? 80 : 443);
|
176 |
-
|
177 |
-
if ($resolve && 0x072A00 > CurlClientState::$curlVersion['version_number']) {
|
178 |
-
// DNS cache removals require curl 7.42 or higher
|
179 |
-
$this->multi->reset();
|
180 |
-
}
|
181 |
-
|
182 |
-
foreach ($options['resolve'] as $host => $ip) {
|
183 |
-
$resolve[] = null === $ip ? "-$host:$port" : "$host:$port:$ip";
|
184 |
-
$this->multi->dnsCache->hostnames[$host] = $ip;
|
185 |
-
$this->multi->dnsCache->removals["-$host:$port"] = "-$host:$port";
|
186 |
-
}
|
187 |
-
|
188 |
-
$curlopts[\CURLOPT_RESOLVE] = $resolve;
|
189 |
-
}
|
190 |
-
|
191 |
-
if ('POST' === $method) {
|
192 |
-
// Use CURLOPT_POST to have browser-like POST-to-GET redirects for 301, 302 and 303
|
193 |
-
$curlopts[\CURLOPT_POST] = true;
|
194 |
-
} elseif ('HEAD' === $method) {
|
195 |
-
$curlopts[\CURLOPT_NOBODY] = true;
|
196 |
-
} else {
|
197 |
-
$curlopts[\CURLOPT_CUSTOMREQUEST] = $method;
|
198 |
-
}
|
199 |
-
|
200 |
-
if ('\\' !== \DIRECTORY_SEPARATOR && $options['timeout'] < 1) {
|
201 |
-
$curlopts[\CURLOPT_NOSIGNAL] = true;
|
202 |
-
}
|
203 |
-
|
204 |
-
if (\extension_loaded('zlib') && !isset($options['normalized_headers']['accept-encoding'])) {
|
205 |
-
$options['headers'][] = 'Accept-Encoding: gzip'; // Expose only one encoding, some servers mess up when more are provided
|
206 |
-
}
|
207 |
-
|
208 |
-
foreach ($options['headers'] as $header) {
|
209 |
-
if (':' === $header[-2] && \strlen($header) - 2 === strpos($header, ': ')) {
|
210 |
-
// curl requires a special syntax to send empty headers
|
211 |
-
$curlopts[\CURLOPT_HTTPHEADER][] = substr_replace($header, ';', -2);
|
212 |
-
} else {
|
213 |
-
$curlopts[\CURLOPT_HTTPHEADER][] = $header;
|
214 |
-
}
|
215 |
-
}
|
216 |
-
|
217 |
-
// Prevent curl from sending its default Accept and Expect headers
|
218 |
-
foreach (['accept', 'expect'] as $header) {
|
219 |
-
if (!isset($options['normalized_headers'][$header][0])) {
|
220 |
-
$curlopts[\CURLOPT_HTTPHEADER][] = $header.':';
|
221 |
-
}
|
222 |
-
}
|
223 |
-
|
224 |
-
if (!\is_string($body = $options['body'])) {
|
225 |
-
if (\is_resource($body)) {
|
226 |
-
$curlopts[\CURLOPT_INFILE] = $body;
|
227 |
-
} else {
|
228 |
-
$eof = false;
|
229 |
-
$buffer = '';
|
230 |
-
$curlopts[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body, &$buffer, &$eof) {
|
231 |
-
return self::readRequestBody($length, $body, $buffer, $eof);
|
232 |
-
};
|
233 |
-
}
|
234 |
-
|
235 |
-
if (isset($options['normalized_headers']['content-length'][0])) {
|
236 |
-
$curlopts[\CURLOPT_INFILESIZE] = substr($options['normalized_headers']['content-length'][0], \strlen('Content-Length: '));
|
237 |
-
} elseif (!isset($options['normalized_headers']['transfer-encoding'])) {
|
238 |
-
$curlopts[\CURLOPT_HTTPHEADER][] = 'Transfer-Encoding: chunked'; // Enable chunked request bodies
|
239 |
-
}
|
240 |
-
|
241 |
-
if ('POST' !== $method) {
|
242 |
-
$curlopts[\CURLOPT_UPLOAD] = true;
|
243 |
-
|
244 |
-
if (!isset($options['normalized_headers']['content-type'])) {
|
245 |
-
$curlopts[\CURLOPT_HTTPHEADER][] = 'Content-Type: application/x-www-form-urlencoded';
|
246 |
-
}
|
247 |
-
}
|
248 |
-
} elseif ('' !== $body || 'POST' === $method) {
|
249 |
-
$curlopts[\CURLOPT_POSTFIELDS] = $body;
|
250 |
-
}
|
251 |
-
|
252 |
-
if ($options['peer_fingerprint']) {
|
253 |
-
if (!isset($options['peer_fingerprint']['pin-sha256'])) {
|
254 |
-
throw new TransportException(__CLASS__.' supports only "pin-sha256" fingerprints.');
|
255 |
-
}
|
256 |
-
|
257 |
-
$curlopts[\CURLOPT_PINNEDPUBLICKEY] = 'sha256//'.implode(';sha256//', $options['peer_fingerprint']['pin-sha256']);
|
258 |
-
}
|
259 |
-
|
260 |
-
if ($options['bindto']) {
|
261 |
-
if (file_exists($options['bindto'])) {
|
262 |
-
$curlopts[\CURLOPT_UNIX_SOCKET_PATH] = $options['bindto'];
|
263 |
-
} elseif (!str_starts_with($options['bindto'], 'if!') && preg_match('/^(.*):(\d+)$/', $options['bindto'], $matches)) {
|
264 |
-
$curlopts[\CURLOPT_INTERFACE] = $matches[1];
|
265 |
-
$curlopts[\CURLOPT_LOCALPORT] = $matches[2];
|
266 |
-
} else {
|
267 |
-
$curlopts[\CURLOPT_INTERFACE] = $options['bindto'];
|
268 |
-
}
|
269 |
-
}
|
270 |
-
|
271 |
-
if (0 < $options['max_duration']) {
|
272 |
-
$curlopts[\CURLOPT_TIMEOUT_MS] = 1000 * $options['max_duration'];
|
273 |
-
}
|
274 |
-
|
275 |
-
if (!empty($options['extra']['curl']) && \is_array($options['extra']['curl'])) {
|
276 |
-
$this->validateExtraCurlOptions($options['extra']['curl']);
|
277 |
-
$curlopts += $options['extra']['curl'];
|
278 |
-
}
|
279 |
-
|
280 |
-
if ($pushedResponse = $this->multi->pushedResponses[$url] ?? null) {
|
281 |
-
unset($this->multi->pushedResponses[$url]);
|
282 |
-
|
283 |
-
if (self::acceptPushForRequest($method, $options, $pushedResponse)) {
|
284 |
-
$this->logger && $this->logger->debug(sprintf('Accepting pushed response: "%s %s"', $method, $url));
|
285 |
-
|
286 |
-
// Reinitialize the pushed response with request's options
|
287 |
-
$ch = $pushedResponse->handle;
|
288 |
-
$pushedResponse = $pushedResponse->response;
|
289 |
-
$pushedResponse->__construct($this->multi, $url, $options, $this->logger);
|
290 |
-
} else {
|
291 |
-
$this->logger && $this->logger->debug(sprintf('Rejecting pushed response: "%s"', $url));
|
292 |
-
$pushedResponse = null;
|
293 |
-
}
|
294 |
-
}
|
295 |
-
|
296 |
-
if (!$pushedResponse) {
|
297 |
-
$ch = curl_init();
|
298 |
-
$this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, $url));
|
299 |
-
$curlopts += [\CURLOPT_SHARE => $this->multi->share];
|
300 |
-
}
|
301 |
-
|
302 |
-
foreach ($curlopts as $opt => $value) {
|
303 |
-
if (null !== $value && !curl_setopt($ch, $opt, $value) && \CURLOPT_CERTINFO !== $opt && (!\defined('CURLOPT_HEADEROPT') || \CURLOPT_HEADEROPT !== $opt)) {
|
304 |
-
$constantName = $this->findConstantName($opt);
|
305 |
-
throw new TransportException(sprintf('Curl option "%s" is not supported.', $constantName ?? $opt));
|
306 |
-
}
|
307 |
-
}
|
308 |
-
|
309 |
-
return $pushedResponse ?? new CurlResponse($this->multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host), CurlClientState::$curlVersion['version_number']);
|
310 |
-
}
|
311 |
-
|
312 |
-
/**
|
313 |
-
* {@inheritdoc}
|
314 |
-
*/
|
315 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
316 |
-
{
|
317 |
-
if ($responses instanceof CurlResponse) {
|
318 |
-
$responses = [$responses];
|
319 |
-
} elseif (!is_iterable($responses)) {
|
320 |
-
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of CurlResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
|
321 |
-
}
|
322 |
-
|
323 |
-
if (\is_resource($this->multi->handle) || $this->multi->handle instanceof \CurlMultiHandle) {
|
324 |
-
$active = 0;
|
325 |
-
while (\CURLM_CALL_MULTI_PERFORM === curl_multi_exec($this->multi->handle, $active)) {
|
326 |
-
}
|
327 |
-
}
|
328 |
-
|
329 |
-
return new ResponseStream(CurlResponse::stream($responses, $timeout));
|
330 |
-
}
|
331 |
-
|
332 |
-
public function reset()
|
333 |
-
{
|
334 |
-
$this->multi->reset();
|
335 |
-
}
|
336 |
-
|
337 |
-
/**
|
338 |
-
* Accepts pushed responses only if their headers related to authentication match the request.
|
339 |
-
*/
|
340 |
-
private static function acceptPushForRequest(string $method, array $options, PushedResponse $pushedResponse): bool
|
341 |
-
{
|
342 |
-
if ('' !== $options['body'] || $method !== $pushedResponse->requestHeaders[':method'][0]) {
|
343 |
-
return false;
|
344 |
-
}
|
345 |
-
|
346 |
-
foreach (['proxy', 'no_proxy', 'bindto', 'local_cert', 'local_pk'] as $k) {
|
347 |
-
if ($options[$k] !== $pushedResponse->parentOptions[$k]) {
|
348 |
-
return false;
|
349 |
-
}
|
350 |
-
}
|
351 |
-
|
352 |
-
foreach (['authorization', 'cookie', 'range', 'proxy-authorization'] as $k) {
|
353 |
-
$normalizedHeaders = $options['normalized_headers'][$k] ?? [];
|
354 |
-
foreach ($normalizedHeaders as $i => $v) {
|
355 |
-
$normalizedHeaders[$i] = substr($v, \strlen($k) + 2);
|
356 |
-
}
|
357 |
-
|
358 |
-
if (($pushedResponse->requestHeaders[$k] ?? []) !== $normalizedHeaders) {
|
359 |
-
return false;
|
360 |
-
}
|
361 |
-
}
|
362 |
-
|
363 |
-
return true;
|
364 |
-
}
|
365 |
-
|
366 |
-
/**
|
367 |
-
* Wraps the request's body callback to allow it to return strings longer than curl requested.
|
368 |
-
*/
|
369 |
-
private static function readRequestBody(int $length, \Closure $body, string &$buffer, bool &$eof): string
|
370 |
-
{
|
371 |
-
if (!$eof && \strlen($buffer) < $length) {
|
372 |
-
if (!\is_string($data = $body($length))) {
|
373 |
-
throw new TransportException(sprintf('The return value of the "body" option callback must be a string, "%s" returned.', get_debug_type($data)));
|
374 |
-
}
|
375 |
-
|
376 |
-
$buffer .= $data;
|
377 |
-
$eof = '' === $data;
|
378 |
-
}
|
379 |
-
|
380 |
-
$data = substr($buffer, 0, $length);
|
381 |
-
$buffer = substr($buffer, $length);
|
382 |
-
|
383 |
-
return $data;
|
384 |
-
}
|
385 |
-
|
386 |
-
/**
|
387 |
-
* Resolves relative URLs on redirects and deals with authentication headers.
|
388 |
-
*
|
389 |
-
* Work around CVE-2018-1000007: Authorization and Cookie headers should not follow redirects - fixed in Curl 7.64
|
390 |
-
*/
|
391 |
-
private static function createRedirectResolver(array $options, string $host): \Closure
|
392 |
-
{
|
393 |
-
$redirectHeaders = [];
|
394 |
-
if (0 < $options['max_redirects']) {
|
395 |
-
$redirectHeaders['host'] = $host;
|
396 |
-
$redirectHeaders['with_auth'] = $redirectHeaders['no_auth'] = array_filter($options['headers'], static function ($h) {
|
397 |
-
return 0 !== stripos($h, 'Host:');
|
398 |
-
});
|
399 |
-
|
400 |
-
if (isset($options['normalized_headers']['authorization'][0]) || isset($options['normalized_headers']['cookie'][0])) {
|
401 |
-
$redirectHeaders['no_auth'] = array_filter($options['headers'], static function ($h) {
|
402 |
-
return 0 !== stripos($h, 'Authorization:') && 0 !== stripos($h, 'Cookie:');
|
403 |
-
});
|
404 |
-
}
|
405 |
-
}
|
406 |
-
|
407 |
-
return static function ($ch, string $location, bool $noContent) use (&$redirectHeaders) {
|
408 |
-
try {
|
409 |
-
$location = self::parseUrl($location);
|
410 |
-
} catch (InvalidArgumentException $e) {
|
411 |
-
return null;
|
412 |
-
}
|
413 |
-
|
414 |
-
if ($noContent && $redirectHeaders) {
|
415 |
-
$filterContentHeaders = static function ($h) {
|
416 |
-
return 0 !== stripos($h, 'Content-Length:') && 0 !== stripos($h, 'Content-Type:') && 0 !== stripos($h, 'Transfer-Encoding:');
|
417 |
-
};
|
418 |
-
$redirectHeaders['no_auth'] = array_filter($redirectHeaders['no_auth'], $filterContentHeaders);
|
419 |
-
$redirectHeaders['with_auth'] = array_filter($redirectHeaders['with_auth'], $filterContentHeaders);
|
420 |
-
}
|
421 |
-
|
422 |
-
if ($redirectHeaders && $host = parse_url('http:'.$location['authority'], \PHP_URL_HOST)) {
|
423 |
-
$requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth'];
|
424 |
-
curl_setopt($ch, \CURLOPT_HTTPHEADER, $requestHeaders);
|
425 |
-
} elseif ($noContent && $redirectHeaders) {
|
426 |
-
curl_setopt($ch, \CURLOPT_HTTPHEADER, $redirectHeaders['with_auth']);
|
427 |
-
}
|
428 |
-
|
429 |
-
$url = self::parseUrl(curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL));
|
430 |
-
$url = self::resolveUrl($location, $url);
|
431 |
-
|
432 |
-
curl_setopt($ch, \CURLOPT_PROXY, $options['proxy']
|
433 |
-
?? ('https:' === $url['scheme'] ? $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? null : null)
|
434 |
-
// Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities
|
435 |
-
?? $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null
|
436 |
-
);
|
437 |
-
|
438 |
-
return implode('', $url);
|
439 |
-
};
|
440 |
-
}
|
441 |
-
|
442 |
-
private function findConstantName(int $opt): ?string
|
443 |
-
{
|
444 |
-
$constants = array_filter(get_defined_constants(), static function ($v, $k) use ($opt) {
|
445 |
-
return $v === $opt && 'C' === $k[0] && (str_starts_with($k, 'CURLOPT_') || str_starts_with($k, 'CURLINFO_'));
|
446 |
-
}, \ARRAY_FILTER_USE_BOTH);
|
447 |
-
|
448 |
-
return key($constants);
|
449 |
-
}
|
450 |
-
|
451 |
-
/**
|
452 |
-
* Prevents overriding options that are set internally throughout the request.
|
453 |
-
*/
|
454 |
-
private function validateExtraCurlOptions(array $options): void
|
455 |
-
{
|
456 |
-
$curloptsToConfig = [
|
457 |
-
//options used in CurlHttpClient
|
458 |
-
\CURLOPT_HTTPAUTH => 'auth_ntlm',
|
459 |
-
\CURLOPT_USERPWD => 'auth_ntlm',
|
460 |
-
\CURLOPT_RESOLVE => 'resolve',
|
461 |
-
\CURLOPT_NOSIGNAL => 'timeout',
|
462 |
-
\CURLOPT_HTTPHEADER => 'headers',
|
463 |
-
\CURLOPT_INFILE => 'body',
|
464 |
-
\CURLOPT_READFUNCTION => 'body',
|
465 |
-
\CURLOPT_INFILESIZE => 'body',
|
466 |
-
\CURLOPT_POSTFIELDS => 'body',
|
467 |
-
\CURLOPT_UPLOAD => 'body',
|
468 |
-
\CURLOPT_INTERFACE => 'bindto',
|
469 |
-
\CURLOPT_TIMEOUT_MS => 'max_duration',
|
470 |
-
\CURLOPT_TIMEOUT => 'max_duration',
|
471 |
-
\CURLOPT_MAXREDIRS => 'max_redirects',
|
472 |
-
\CURLOPT_PROXY => 'proxy',
|
473 |
-
\CURLOPT_NOPROXY => 'no_proxy',
|
474 |
-
\CURLOPT_SSL_VERIFYPEER => 'verify_peer',
|
475 |
-
\CURLOPT_SSL_VERIFYHOST => 'verify_host',
|
476 |
-
\CURLOPT_CAINFO => 'cafile',
|
477 |
-
\CURLOPT_CAPATH => 'capath',
|
478 |
-
\CURLOPT_SSL_CIPHER_LIST => 'ciphers',
|
479 |
-
\CURLOPT_SSLCERT => 'local_cert',
|
480 |
-
\CURLOPT_SSLKEY => 'local_pk',
|
481 |
-
\CURLOPT_KEYPASSWD => 'passphrase',
|
482 |
-
\CURLOPT_CERTINFO => 'capture_peer_cert_chain',
|
483 |
-
\CURLOPT_USERAGENT => 'normalized_headers',
|
484 |
-
\CURLOPT_REFERER => 'headers',
|
485 |
-
//options used in CurlResponse
|
486 |
-
\CURLOPT_NOPROGRESS => 'on_progress',
|
487 |
-
\CURLOPT_PROGRESSFUNCTION => 'on_progress',
|
488 |
-
];
|
489 |
-
|
490 |
-
if (\defined('CURLOPT_UNIX_SOCKET_PATH')) {
|
491 |
-
$curloptsToConfig[\CURLOPT_UNIX_SOCKET_PATH] = 'bindto';
|
492 |
-
}
|
493 |
-
|
494 |
-
if (\defined('CURLOPT_PINNEDPUBLICKEY')) {
|
495 |
-
$curloptsToConfig[\CURLOPT_PINNEDPUBLICKEY] = 'peer_fingerprint';
|
496 |
-
}
|
497 |
-
|
498 |
-
$curloptsToCheck = [
|
499 |
-
\CURLOPT_PRIVATE,
|
500 |
-
\CURLOPT_HEADERFUNCTION,
|
501 |
-
\CURLOPT_WRITEFUNCTION,
|
502 |
-
\CURLOPT_VERBOSE,
|
503 |
-
\CURLOPT_STDERR,
|
504 |
-
\CURLOPT_RETURNTRANSFER,
|
505 |
-
\CURLOPT_URL,
|
506 |
-
\CURLOPT_FOLLOWLOCATION,
|
507 |
-
\CURLOPT_HEADER,
|
508 |
-
\CURLOPT_CONNECTTIMEOUT,
|
509 |
-
\CURLOPT_CONNECTTIMEOUT_MS,
|
510 |
-
\CURLOPT_HTTP_VERSION,
|
511 |
-
\CURLOPT_PORT,
|
512 |
-
\CURLOPT_DNS_USE_GLOBAL_CACHE,
|
513 |
-
\CURLOPT_PROTOCOLS,
|
514 |
-
\CURLOPT_REDIR_PROTOCOLS,
|
515 |
-
\CURLOPT_COOKIEFILE,
|
516 |
-
\CURLINFO_REDIRECT_COUNT,
|
517 |
-
];
|
518 |
-
|
519 |
-
if (\defined('CURLOPT_HTTP09_ALLOWED')) {
|
520 |
-
$curloptsToCheck[] = \CURLOPT_HTTP09_ALLOWED;
|
521 |
-
}
|
522 |
-
|
523 |
-
if (\defined('CURLOPT_HEADEROPT')) {
|
524 |
-
$curloptsToCheck[] = \CURLOPT_HEADEROPT;
|
525 |
-
}
|
526 |
-
|
527 |
-
$methodOpts = [
|
528 |
-
\CURLOPT_POST,
|
529 |
-
\CURLOPT_PUT,
|
530 |
-
\CURLOPT_CUSTOMREQUEST,
|
531 |
-
\CURLOPT_HTTPGET,
|
532 |
-
\CURLOPT_NOBODY,
|
533 |
-
];
|
534 |
-
|
535 |
-
foreach ($options as $opt => $optValue) {
|
536 |
-
if (isset($curloptsToConfig[$opt])) {
|
537 |
-
$constName = $this->findConstantName($opt) ?? $opt;
|
538 |
-
throw new InvalidArgumentException(sprintf('Cannot set "%s" with "extra.curl", use option "%s" instead.', $constName, $curloptsToConfig[$opt]));
|
539 |
-
}
|
540 |
-
|
541 |
-
if (\in_array($opt, $methodOpts)) {
|
542 |
-
throw new InvalidArgumentException('The HTTP method cannot be overridden using "extra.curl".');
|
543 |
-
}
|
544 |
-
|
545 |
-
if (\in_array($opt, $curloptsToCheck)) {
|
546 |
-
$constName = $this->findConstantName($opt) ?? $opt;
|
547 |
-
throw new InvalidArgumentException(sprintf('Cannot set "%s" with "extra.curl".', $constName));
|
548 |
-
}
|
549 |
-
}
|
550 |
-
}
|
551 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/DataCollector/HttpClientDataCollector.php
DELETED
@@ -1,170 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\DataCollector;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\TraceableHttpClient;
|
15 |
-
use Symfony\Component\HttpFoundation\Request;
|
16 |
-
use Symfony\Component\HttpFoundation\Response;
|
17 |
-
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
18 |
-
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
|
19 |
-
use Symfony\Component\VarDumper\Caster\ImgStub;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @author Jérémy Romey <jeremy@free-agent.fr>
|
23 |
-
*/
|
24 |
-
final class HttpClientDataCollector extends DataCollector implements LateDataCollectorInterface
|
25 |
-
{
|
26 |
-
/**
|
27 |
-
* @var TraceableHttpClient[]
|
28 |
-
*/
|
29 |
-
private $clients = [];
|
30 |
-
|
31 |
-
public function registerClient(string $name, TraceableHttpClient $client)
|
32 |
-
{
|
33 |
-
$this->clients[$name] = $client;
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* {@inheritdoc}
|
38 |
-
*/
|
39 |
-
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
40 |
-
{
|
41 |
-
$this->reset();
|
42 |
-
|
43 |
-
foreach ($this->clients as $name => $client) {
|
44 |
-
[$errorCount, $traces] = $this->collectOnClient($client);
|
45 |
-
|
46 |
-
$this->data['clients'][$name] = [
|
47 |
-
'traces' => $traces,
|
48 |
-
'error_count' => $errorCount,
|
49 |
-
];
|
50 |
-
|
51 |
-
$this->data['request_count'] += \count($traces);
|
52 |
-
$this->data['error_count'] += $errorCount;
|
53 |
-
}
|
54 |
-
}
|
55 |
-
|
56 |
-
public function lateCollect()
|
57 |
-
{
|
58 |
-
foreach ($this->clients as $client) {
|
59 |
-
$client->reset();
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
public function getClients(): array
|
64 |
-
{
|
65 |
-
return $this->data['clients'] ?? [];
|
66 |
-
}
|
67 |
-
|
68 |
-
public function getRequestCount(): int
|
69 |
-
{
|
70 |
-
return $this->data['request_count'] ?? 0;
|
71 |
-
}
|
72 |
-
|
73 |
-
public function getErrorCount(): int
|
74 |
-
{
|
75 |
-
return $this->data['error_count'] ?? 0;
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* {@inheritdoc}
|
80 |
-
*/
|
81 |
-
public function getName(): string
|
82 |
-
{
|
83 |
-
return 'http_client';
|
84 |
-
}
|
85 |
-
|
86 |
-
public function reset()
|
87 |
-
{
|
88 |
-
$this->data = [
|
89 |
-
'clients' => [],
|
90 |
-
'request_count' => 0,
|
91 |
-
'error_count' => 0,
|
92 |
-
];
|
93 |
-
}
|
94 |
-
|
95 |
-
private function collectOnClient(TraceableHttpClient $client): array
|
96 |
-
{
|
97 |
-
$traces = $client->getTracedRequests();
|
98 |
-
$errorCount = 0;
|
99 |
-
$baseInfo = [
|
100 |
-
'response_headers' => 1,
|
101 |
-
'retry_count' => 1,
|
102 |
-
'redirect_count' => 1,
|
103 |
-
'redirect_url' => 1,
|
104 |
-
'user_data' => 1,
|
105 |
-
'error' => 1,
|
106 |
-
'url' => 1,
|
107 |
-
];
|
108 |
-
|
109 |
-
foreach ($traces as $i => $trace) {
|
110 |
-
if (400 <= ($trace['info']['http_code'] ?? 0)) {
|
111 |
-
++$errorCount;
|
112 |
-
}
|
113 |
-
|
114 |
-
$info = $trace['info'];
|
115 |
-
$traces[$i]['http_code'] = $info['http_code'] ?? 0;
|
116 |
-
|
117 |
-
unset($info['filetime'], $info['http_code'], $info['ssl_verify_result'], $info['content_type']);
|
118 |
-
|
119 |
-
if (($info['http_method'] ?? null) === $trace['method']) {
|
120 |
-
unset($info['http_method']);
|
121 |
-
}
|
122 |
-
|
123 |
-
if (($info['url'] ?? null) === $trace['url']) {
|
124 |
-
unset($info['url']);
|
125 |
-
}
|
126 |
-
|
127 |
-
foreach ($info as $k => $v) {
|
128 |
-
if (!$v || (is_numeric($v) && 0 > $v)) {
|
129 |
-
unset($info[$k]);
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
133 |
-
if (\is_string($content = $trace['content'])) {
|
134 |
-
$contentType = 'application/octet-stream';
|
135 |
-
|
136 |
-
foreach ($info['response_headers'] ?? [] as $h) {
|
137 |
-
if (0 === stripos($h, 'content-type: ')) {
|
138 |
-
$contentType = substr($h, \strlen('content-type: '));
|
139 |
-
break;
|
140 |
-
}
|
141 |
-
}
|
142 |
-
|
143 |
-
if (0 === strpos($contentType, 'image/') && class_exists(ImgStub::class)) {
|
144 |
-
$content = new ImgStub($content, $contentType, '');
|
145 |
-
} else {
|
146 |
-
$content = [$content];
|
147 |
-
}
|
148 |
-
|
149 |
-
$content = ['response_content' => $content];
|
150 |
-
} elseif (\is_array($content)) {
|
151 |
-
$content = ['response_json' => $content];
|
152 |
-
} else {
|
153 |
-
$content = [];
|
154 |
-
}
|
155 |
-
|
156 |
-
if (isset($info['retry_count'])) {
|
157 |
-
$content['retries'] = $info['previous_info'];
|
158 |
-
unset($info['previous_info']);
|
159 |
-
}
|
160 |
-
|
161 |
-
$debugInfo = array_diff_key($info, $baseInfo);
|
162 |
-
$info = ['info' => $debugInfo] + array_diff_key($info, $debugInfo) + $content;
|
163 |
-
unset($traces[$i]['info']); // break PHP reference used by TraceableHttpClient
|
164 |
-
$traces[$i]['info'] = $this->cloneVar($info);
|
165 |
-
$traces[$i]['options'] = $this->cloneVar($trace['options']);
|
166 |
-
}
|
167 |
-
|
168 |
-
return [$errorCount, $traces];
|
169 |
-
}
|
170 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/DecoratorTrait.php
DELETED
@@ -1,66 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
15 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
16 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
17 |
-
use Symfony\Contracts\Service\ResetInterface;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Eases with writing decorators.
|
21 |
-
*
|
22 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
23 |
-
*/
|
24 |
-
trait DecoratorTrait
|
25 |
-
{
|
26 |
-
private $client;
|
27 |
-
|
28 |
-
public function __construct(HttpClientInterface $client = null)
|
29 |
-
{
|
30 |
-
$this->client = $client ?? HttpClient::create();
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* {@inheritdoc}
|
35 |
-
*/
|
36 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
37 |
-
{
|
38 |
-
return $this->client->request($method, $url, $options);
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* {@inheritdoc}
|
43 |
-
*/
|
44 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
45 |
-
{
|
46 |
-
return $this->client->stream($responses, $timeout);
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* {@inheritdoc}
|
51 |
-
*/
|
52 |
-
public function withOptions(array $options): self
|
53 |
-
{
|
54 |
-
$clone = clone $this;
|
55 |
-
$clone->client = $this->client->withOptions($options);
|
56 |
-
|
57 |
-
return $clone;
|
58 |
-
}
|
59 |
-
|
60 |
-
public function reset()
|
61 |
-
{
|
62 |
-
if ($this->client instanceof ResetInterface) {
|
63 |
-
$this->client->reset();
|
64 |
-
}
|
65 |
-
}
|
66 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/DependencyInjection/HttpClientPass.php
DELETED
@@ -1,51 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\DependencyInjection;
|
13 |
-
|
14 |
-
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
15 |
-
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
16 |
-
use Symfony\Component\DependencyInjection\ContainerInterface;
|
17 |
-
use Symfony\Component\DependencyInjection\Reference;
|
18 |
-
use Symfony\Component\HttpClient\TraceableHttpClient;
|
19 |
-
|
20 |
-
final class HttpClientPass implements CompilerPassInterface
|
21 |
-
{
|
22 |
-
private $clientTag;
|
23 |
-
|
24 |
-
public function __construct(string $clientTag = 'http_client.client')
|
25 |
-
{
|
26 |
-
if (0 < \func_num_args()) {
|
27 |
-
trigger_deprecation('symfony/http-client', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
|
28 |
-
}
|
29 |
-
|
30 |
-
$this->clientTag = $clientTag;
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* {@inheritdoc}
|
35 |
-
*/
|
36 |
-
public function process(ContainerBuilder $container)
|
37 |
-
{
|
38 |
-
if (!$container->hasDefinition('data_collector.http_client')) {
|
39 |
-
return;
|
40 |
-
}
|
41 |
-
|
42 |
-
foreach ($container->findTaggedServiceIds($this->clientTag) as $id => $tags) {
|
43 |
-
$container->register('.debug.'.$id, TraceableHttpClient::class)
|
44 |
-
->setArguments([new Reference('.debug.'.$id.'.inner'), new Reference('debug.stopwatch', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)])
|
45 |
-
->addTag('kernel.reset', ['method' => 'reset'])
|
46 |
-
->setDecoratedService($id);
|
47 |
-
$container->getDefinition('data_collector.http_client')
|
48 |
-
->addMethodCall('registerClient', [$id, new Reference('.debug.'.$id)]);
|
49 |
-
}
|
50 |
-
}
|
51 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/EventSourceHttpClient.php
DELETED
@@ -1,159 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Chunk\ServerSentEvent;
|
15 |
-
use Symfony\Component\HttpClient\Exception\EventSourceException;
|
16 |
-
use Symfony\Component\HttpClient\Response\AsyncContext;
|
17 |
-
use Symfony\Component\HttpClient\Response\AsyncResponse;
|
18 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
19 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
20 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
21 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
22 |
-
use Symfony\Contracts\Service\ResetInterface;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @author Antoine Bluchet <soyuka@gmail.com>
|
26 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
27 |
-
*/
|
28 |
-
final class EventSourceHttpClient implements HttpClientInterface, ResetInterface
|
29 |
-
{
|
30 |
-
use AsyncDecoratorTrait, HttpClientTrait {
|
31 |
-
AsyncDecoratorTrait::withOptions insteadof HttpClientTrait;
|
32 |
-
}
|
33 |
-
|
34 |
-
private $reconnectionTime;
|
35 |
-
|
36 |
-
public function __construct(HttpClientInterface $client = null, float $reconnectionTime = 10.0)
|
37 |
-
{
|
38 |
-
$this->client = $client ?? HttpClient::create();
|
39 |
-
$this->reconnectionTime = $reconnectionTime;
|
40 |
-
}
|
41 |
-
|
42 |
-
public function connect(string $url, array $options = []): ResponseInterface
|
43 |
-
{
|
44 |
-
return $this->request('GET', $url, self::mergeDefaultOptions($options, [
|
45 |
-
'buffer' => false,
|
46 |
-
'headers' => [
|
47 |
-
'Accept' => 'text/event-stream',
|
48 |
-
'Cache-Control' => 'no-cache',
|
49 |
-
],
|
50 |
-
], true));
|
51 |
-
}
|
52 |
-
|
53 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
54 |
-
{
|
55 |
-
$state = new class() {
|
56 |
-
public $buffer = null;
|
57 |
-
public $lastEventId = null;
|
58 |
-
public $reconnectionTime;
|
59 |
-
public $lastError = null;
|
60 |
-
};
|
61 |
-
$state->reconnectionTime = $this->reconnectionTime;
|
62 |
-
|
63 |
-
if ($accept = self::normalizeHeaders($options['headers'] ?? [])['accept'] ?? []) {
|
64 |
-
$state->buffer = \in_array($accept, [['Accept: text/event-stream'], ['accept: text/event-stream']], true) ? '' : null;
|
65 |
-
|
66 |
-
if (null !== $state->buffer) {
|
67 |
-
$options['extra']['trace_content'] = false;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
-
return new AsyncResponse($this->client, $method, $url, $options, static function (ChunkInterface $chunk, AsyncContext $context) use ($state, $method, $url, $options) {
|
72 |
-
if (null !== $state->buffer) {
|
73 |
-
$context->setInfo('reconnection_time', $state->reconnectionTime);
|
74 |
-
$isTimeout = false;
|
75 |
-
}
|
76 |
-
$lastError = $state->lastError;
|
77 |
-
$state->lastError = null;
|
78 |
-
|
79 |
-
try {
|
80 |
-
$isTimeout = $chunk->isTimeout();
|
81 |
-
|
82 |
-
if (null !== $chunk->getInformationalStatus() || $context->getInfo('canceled')) {
|
83 |
-
yield $chunk;
|
84 |
-
|
85 |
-
return;
|
86 |
-
}
|
87 |
-
} catch (TransportExceptionInterface $e) {
|
88 |
-
$state->lastError = $lastError ?? microtime(true);
|
89 |
-
|
90 |
-
if (null === $state->buffer || ($isTimeout && microtime(true) - $state->lastError < $state->reconnectionTime)) {
|
91 |
-
yield $chunk;
|
92 |
-
} else {
|
93 |
-
$options['headers']['Last-Event-ID'] = $state->lastEventId;
|
94 |
-
$state->buffer = '';
|
95 |
-
$state->lastError = microtime(true);
|
96 |
-
$context->getResponse()->cancel();
|
97 |
-
$context->replaceRequest($method, $url, $options);
|
98 |
-
if ($isTimeout) {
|
99 |
-
yield $chunk;
|
100 |
-
} else {
|
101 |
-
$context->pause($state->reconnectionTime);
|
102 |
-
}
|
103 |
-
}
|
104 |
-
|
105 |
-
return;
|
106 |
-
}
|
107 |
-
|
108 |
-
if ($chunk->isFirst()) {
|
109 |
-
if (preg_match('/^text\/event-stream(;|$)/i', $context->getHeaders()['content-type'][0] ?? '')) {
|
110 |
-
$state->buffer = '';
|
111 |
-
} elseif (null !== $lastError || (null !== $state->buffer && 200 === $context->getStatusCode())) {
|
112 |
-
throw new EventSourceException(sprintf('Response content-type is "%s" while "text/event-stream" was expected for "%s".', $context->getHeaders()['content-type'][0] ?? '', $context->getInfo('url')));
|
113 |
-
} else {
|
114 |
-
$context->passthru();
|
115 |
-
}
|
116 |
-
|
117 |
-
if (null === $lastError) {
|
118 |
-
yield $chunk;
|
119 |
-
}
|
120 |
-
|
121 |
-
return;
|
122 |
-
}
|
123 |
-
|
124 |
-
$rx = '/((?:\r\n|[\r\n]){2,})/';
|
125 |
-
$content = $state->buffer.$chunk->getContent();
|
126 |
-
|
127 |
-
if ($chunk->isLast()) {
|
128 |
-
$rx = substr_replace($rx, '|$', -2, 0);
|
129 |
-
}
|
130 |
-
$events = preg_split($rx, $content, -1, \PREG_SPLIT_DELIM_CAPTURE);
|
131 |
-
$state->buffer = array_pop($events);
|
132 |
-
|
133 |
-
for ($i = 0; isset($events[$i]); $i += 2) {
|
134 |
-
$event = new ServerSentEvent($events[$i].$events[1 + $i]);
|
135 |
-
|
136 |
-
if ('' !== $event->getId()) {
|
137 |
-
$context->setInfo('last_event_id', $state->lastEventId = $event->getId());
|
138 |
-
}
|
139 |
-
|
140 |
-
if ($event->getRetry()) {
|
141 |
-
$context->setInfo('reconnection_time', $state->reconnectionTime = $event->getRetry());
|
142 |
-
}
|
143 |
-
|
144 |
-
yield $event;
|
145 |
-
}
|
146 |
-
|
147 |
-
if (preg_match('/^(?::[^\r\n]*+(?:\r\n|[\r\n]))+$/m', $state->buffer)) {
|
148 |
-
$content = $state->buffer;
|
149 |
-
$state->buffer = '';
|
150 |
-
|
151 |
-
yield $context->createChunk($content);
|
152 |
-
}
|
153 |
-
|
154 |
-
if ($chunk->isLast()) {
|
155 |
-
yield $chunk;
|
156 |
-
}
|
157 |
-
});
|
158 |
-
}
|
159 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/ClientException.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Represents a 4xx response.
|
18 |
-
*
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
*/
|
21 |
-
final class ClientException extends \RuntimeException implements ClientExceptionInterface
|
22 |
-
{
|
23 |
-
use HttpExceptionTrait;
|
24 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/EventSourceException.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
final class EventSourceException extends \RuntimeException implements DecodingExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/HttpExceptionTrait.php
DELETED
@@ -1,78 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*
|
19 |
-
* @internal
|
20 |
-
*/
|
21 |
-
trait HttpExceptionTrait
|
22 |
-
{
|
23 |
-
private $response;
|
24 |
-
|
25 |
-
public function __construct(ResponseInterface $response)
|
26 |
-
{
|
27 |
-
$this->response = $response;
|
28 |
-
$code = $response->getInfo('http_code');
|
29 |
-
$url = $response->getInfo('url');
|
30 |
-
$message = sprintf('HTTP %d returned for "%s".', $code, $url);
|
31 |
-
|
32 |
-
$httpCodeFound = false;
|
33 |
-
$isJson = false;
|
34 |
-
foreach (array_reverse($response->getInfo('response_headers')) as $h) {
|
35 |
-
if (str_starts_with($h, 'HTTP/')) {
|
36 |
-
if ($httpCodeFound) {
|
37 |
-
break;
|
38 |
-
}
|
39 |
-
|
40 |
-
$message = sprintf('%s returned for "%s".', $h, $url);
|
41 |
-
$httpCodeFound = true;
|
42 |
-
}
|
43 |
-
|
44 |
-
if (0 === stripos($h, 'content-type:')) {
|
45 |
-
if (preg_match('/\bjson\b/i', $h)) {
|
46 |
-
$isJson = true;
|
47 |
-
}
|
48 |
-
|
49 |
-
if ($httpCodeFound) {
|
50 |
-
break;
|
51 |
-
}
|
52 |
-
}
|
53 |
-
}
|
54 |
-
|
55 |
-
// Try to guess a better error message using common API error formats
|
56 |
-
// The MIME type isn't explicitly checked because some formats inherit from others
|
57 |
-
// Ex: JSON:API follows RFC 7807 semantics, Hydra can be used in any JSON-LD-compatible format
|
58 |
-
if ($isJson && $body = json_decode($response->getContent(false), true)) {
|
59 |
-
if (isset($body['hydra:title']) || isset($body['hydra:description'])) {
|
60 |
-
// see http://www.hydra-cg.com/spec/latest/core/#description-of-http-status-codes-and-errors
|
61 |
-
$separator = isset($body['hydra:title'], $body['hydra:description']) ? "\n\n" : '';
|
62 |
-
$message = ($body['hydra:title'] ?? '').$separator.($body['hydra:description'] ?? '');
|
63 |
-
} elseif ((isset($body['title']) || isset($body['detail']))
|
64 |
-
&& (is_scalar($body['title'] ?? '') && is_scalar($body['detail'] ?? ''))) {
|
65 |
-
// see RFC 7807 and https://jsonapi.org/format/#error-objects
|
66 |
-
$separator = isset($body['title'], $body['detail']) ? "\n\n" : '';
|
67 |
-
$message = ($body['title'] ?? '').$separator.($body['detail'] ?? '');
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
-
parent::__construct($message, $code);
|
72 |
-
}
|
73 |
-
|
74 |
-
public function getResponse(): ResponseInterface
|
75 |
-
{
|
76 |
-
return $this->response;
|
77 |
-
}
|
78 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/InvalidArgumentException.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
final class InvalidArgumentException extends \InvalidArgumentException implements TransportExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/JsonException.php
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Thrown by responses' toArray() method when their content cannot be JSON-decoded.
|
18 |
-
*
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
*/
|
21 |
-
final class JsonException extends \JsonException implements DecodingExceptionInterface
|
22 |
-
{
|
23 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/RedirectionException.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Represents a 3xx response.
|
18 |
-
*
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
*/
|
21 |
-
final class RedirectionException extends \RuntimeException implements RedirectionExceptionInterface
|
22 |
-
{
|
23 |
-
use HttpExceptionTrait;
|
24 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/ServerException.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Represents a 5xx response.
|
18 |
-
*
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
*/
|
21 |
-
final class ServerException extends \RuntimeException implements ServerExceptionInterface
|
22 |
-
{
|
23 |
-
use HttpExceptionTrait;
|
24 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/TimeoutException.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\TimeoutExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
final class TimeoutException extends TransportException implements TimeoutExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Exception/TransportException.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Exception;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
18 |
-
*/
|
19 |
-
class TransportException extends \RuntimeException implements TransportExceptionInterface
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/HttpClient.php
DELETED
@@ -1,78 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Amp\Http\Client\Connection\ConnectionLimitingPool;
|
15 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* A factory to instantiate the best possible HTTP client for the runtime.
|
19 |
-
*
|
20 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
21 |
-
*/
|
22 |
-
final class HttpClient
|
23 |
-
{
|
24 |
-
/**
|
25 |
-
* @param array $defaultOptions Default request's options
|
26 |
-
* @param int $maxHostConnections The maximum number of connections to a single host
|
27 |
-
* @param int $maxPendingPushes The maximum number of pushed responses to accept in the queue
|
28 |
-
*
|
29 |
-
* @see HttpClientInterface::OPTIONS_DEFAULTS for available options
|
30 |
-
*/
|
31 |
-
public static function create(array $defaultOptions = [], int $maxHostConnections = 6, int $maxPendingPushes = 50): HttpClientInterface
|
32 |
-
{
|
33 |
-
if ($amp = class_exists(ConnectionLimitingPool::class)) {
|
34 |
-
if (!\extension_loaded('curl')) {
|
35 |
-
return new AmpHttpClient($defaultOptions, null, $maxHostConnections, $maxPendingPushes);
|
36 |
-
}
|
37 |
-
|
38 |
-
// Skip curl when HTTP/2 push is unsupported or buggy, see https://bugs.php.net/77535
|
39 |
-
if (\PHP_VERSION_ID < 70217 || (\PHP_VERSION_ID >= 70300 && \PHP_VERSION_ID < 70304) || !\defined('CURLMOPT_PUSHFUNCTION')) {
|
40 |
-
return new AmpHttpClient($defaultOptions, null, $maxHostConnections, $maxPendingPushes);
|
41 |
-
}
|
42 |
-
|
43 |
-
static $curlVersion = null;
|
44 |
-
$curlVersion = $curlVersion ?? curl_version();
|
45 |
-
|
46 |
-
// HTTP/2 push crashes before curl 7.61
|
47 |
-
if (0x073D00 > $curlVersion['version_number'] || !(\CURL_VERSION_HTTP2 & $curlVersion['features'])) {
|
48 |
-
return new AmpHttpClient($defaultOptions, null, $maxHostConnections, $maxPendingPushes);
|
49 |
-
}
|
50 |
-
}
|
51 |
-
|
52 |
-
if (\extension_loaded('curl')) {
|
53 |
-
if ('\\' !== \DIRECTORY_SEPARATOR || isset($defaultOptions['cafile']) || isset($defaultOptions['capath']) || ini_get('curl.cainfo') || ini_get('openssl.cafile') || ini_get('openssl.capath')) {
|
54 |
-
return new CurlHttpClient($defaultOptions, $maxHostConnections, $maxPendingPushes);
|
55 |
-
}
|
56 |
-
|
57 |
-
@trigger_error('Configure the "curl.cainfo", "openssl.cafile" or "openssl.capath" php.ini setting to enable the CurlHttpClient', \E_USER_WARNING);
|
58 |
-
}
|
59 |
-
|
60 |
-
if ($amp) {
|
61 |
-
return new AmpHttpClient($defaultOptions, null, $maxHostConnections, $maxPendingPushes);
|
62 |
-
}
|
63 |
-
|
64 |
-
@trigger_error((\extension_loaded('curl') ? 'Upgrade' : 'Install').' the curl extension or run "composer require amphp/http-client" to perform async HTTP operations, including full HTTP/2 support', \E_USER_NOTICE);
|
65 |
-
|
66 |
-
return new NativeHttpClient($defaultOptions, $maxHostConnections);
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Creates a client that adds options (e.g. authentication headers) only when the request URL matches the provided base URI.
|
71 |
-
*/
|
72 |
-
public static function createForBaseUri(string $baseUri, array $defaultOptions = [], int $maxHostConnections = 6, int $maxPendingPushes = 50): HttpClientInterface
|
73 |
-
{
|
74 |
-
$client = self::create([], $maxHostConnections, $maxPendingPushes);
|
75 |
-
|
76 |
-
return ScopingHttpClient::forBaseUri($client, $baseUri, $defaultOptions);
|
77 |
-
}
|
78 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/HttpClientTrait.php
DELETED
@@ -1,684 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
15 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Provides the common logic from writing HttpClientInterface implementations.
|
19 |
-
*
|
20 |
-
* All private methods are static to prevent implementers from creating memory leaks via circular references.
|
21 |
-
*
|
22 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
23 |
-
*/
|
24 |
-
trait HttpClientTrait
|
25 |
-
{
|
26 |
-
private static $CHUNK_SIZE = 16372;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* {@inheritdoc}
|
30 |
-
*/
|
31 |
-
public function withOptions(array $options): self
|
32 |
-
{
|
33 |
-
$clone = clone $this;
|
34 |
-
$clone->defaultOptions = self::mergeDefaultOptions($options, $this->defaultOptions);
|
35 |
-
|
36 |
-
return $clone;
|
37 |
-
}
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Validates and normalizes method, URL and options, and merges them with defaults.
|
41 |
-
*
|
42 |
-
* @throws InvalidArgumentException When a not-supported option is found
|
43 |
-
*/
|
44 |
-
private static function prepareRequest(?string $method, ?string $url, array $options, array $defaultOptions = [], bool $allowExtraOptions = false): array
|
45 |
-
{
|
46 |
-
if (null !== $method) {
|
47 |
-
if (\strlen($method) !== strspn($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')) {
|
48 |
-
throw new InvalidArgumentException(sprintf('Invalid HTTP method "%s", only uppercase letters are accepted.', $method));
|
49 |
-
}
|
50 |
-
if (!$method) {
|
51 |
-
throw new InvalidArgumentException('The HTTP method cannot be empty.');
|
52 |
-
}
|
53 |
-
}
|
54 |
-
|
55 |
-
$options = self::mergeDefaultOptions($options, $defaultOptions, $allowExtraOptions);
|
56 |
-
|
57 |
-
$buffer = $options['buffer'] ?? true;
|
58 |
-
|
59 |
-
if ($buffer instanceof \Closure) {
|
60 |
-
$options['buffer'] = static function (array $headers) use ($buffer) {
|
61 |
-
if (!\is_bool($buffer = $buffer($headers))) {
|
62 |
-
if (!\is_array($bufferInfo = @stream_get_meta_data($buffer))) {
|
63 |
-
throw new \LogicException(sprintf('The closure passed as option "buffer" must return bool or stream resource, got "%s".', get_debug_type($buffer)));
|
64 |
-
}
|
65 |
-
|
66 |
-
if (false === strpbrk($bufferInfo['mode'], 'acew+')) {
|
67 |
-
throw new \LogicException(sprintf('The stream returned by the closure passed as option "buffer" must be writeable, got mode "%s".', $bufferInfo['mode']));
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
-
return $buffer;
|
72 |
-
};
|
73 |
-
} elseif (!\is_bool($buffer)) {
|
74 |
-
if (!\is_array($bufferInfo = @stream_get_meta_data($buffer))) {
|
75 |
-
throw new InvalidArgumentException(sprintf('Option "buffer" must be bool, stream resource or Closure, "%s" given.', get_debug_type($buffer)));
|
76 |
-
}
|
77 |
-
|
78 |
-
if (false === strpbrk($bufferInfo['mode'], 'acew+')) {
|
79 |
-
throw new InvalidArgumentException(sprintf('The stream in option "buffer" must be writeable, mode "%s" given.', $bufferInfo['mode']));
|
80 |
-
}
|
81 |
-
}
|
82 |
-
|
83 |
-
if (isset($options['json'])) {
|
84 |
-
if (isset($options['body']) && '' !== $options['body']) {
|
85 |
-
throw new InvalidArgumentException('Define either the "json" or the "body" option, setting both is not supported.');
|
86 |
-
}
|
87 |
-
$options['body'] = self::jsonEncode($options['json']);
|
88 |
-
unset($options['json']);
|
89 |
-
|
90 |
-
if (!isset($options['normalized_headers']['content-type'])) {
|
91 |
-
$options['normalized_headers']['content-type'] = ['Content-Type: application/json'];
|
92 |
-
}
|
93 |
-
}
|
94 |
-
|
95 |
-
if (!isset($options['normalized_headers']['accept'])) {
|
96 |
-
$options['normalized_headers']['accept'] = ['Accept: */*'];
|
97 |
-
}
|
98 |
-
|
99 |
-
if (isset($options['body'])) {
|
100 |
-
$options['body'] = self::normalizeBody($options['body']);
|
101 |
-
|
102 |
-
if (\is_string($options['body'])
|
103 |
-
&& (string) \strlen($options['body']) !== substr($h = $options['normalized_headers']['content-length'][0] ?? '', 16)
|
104 |
-
&& ('' !== $h || '' !== $options['body'])
|
105 |
-
) {
|
106 |
-
if ('chunked' === substr($options['normalized_headers']['transfer-encoding'][0] ?? '', \strlen('Transfer-Encoding: '))) {
|
107 |
-
unset($options['normalized_headers']['transfer-encoding']);
|
108 |
-
$options['body'] = self::dechunk($options['body']);
|
109 |
-
}
|
110 |
-
|
111 |
-
$options['normalized_headers']['content-length'] = [substr_replace($h ?: 'Content-Length: ', \strlen($options['body']), 16)];
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
-
if (isset($options['peer_fingerprint'])) {
|
116 |
-
$options['peer_fingerprint'] = self::normalizePeerFingerprint($options['peer_fingerprint']);
|
117 |
-
}
|
118 |
-
|
119 |
-
// Validate on_progress
|
120 |
-
if (!\is_callable($onProgress = $options['on_progress'] ?? 'var_dump')) {
|
121 |
-
throw new InvalidArgumentException(sprintf('Option "on_progress" must be callable, "%s" given.', get_debug_type($onProgress)));
|
122 |
-
}
|
123 |
-
|
124 |
-
if (\is_array($options['auth_basic'] ?? null)) {
|
125 |
-
$count = \count($options['auth_basic']);
|
126 |
-
if ($count <= 0 || $count > 2) {
|
127 |
-
throw new InvalidArgumentException(sprintf('Option "auth_basic" must contain 1 or 2 elements, "%s" given.', $count));
|
128 |
-
}
|
129 |
-
|
130 |
-
$options['auth_basic'] = implode(':', $options['auth_basic']);
|
131 |
-
}
|
132 |
-
|
133 |
-
if (!\is_string($options['auth_basic'] ?? '')) {
|
134 |
-
throw new InvalidArgumentException(sprintf('Option "auth_basic" must be string or an array, "%s" given.', get_debug_type($options['auth_basic'])));
|
135 |
-
}
|
136 |
-
|
137 |
-
if (isset($options['auth_bearer'])) {
|
138 |
-
if (!\is_string($options['auth_bearer'])) {
|
139 |
-
throw new InvalidArgumentException(sprintf('Option "auth_bearer" must be a string, "%s" given.', get_debug_type($options['auth_bearer'])));
|
140 |
-
}
|
141 |
-
if (preg_match('{[^\x21-\x7E]}', $options['auth_bearer'])) {
|
142 |
-
throw new InvalidArgumentException('Invalid character found in option "auth_bearer": '.json_encode($options['auth_bearer']).'.');
|
143 |
-
}
|
144 |
-
}
|
145 |
-
|
146 |
-
if (isset($options['auth_basic'], $options['auth_bearer'])) {
|
147 |
-
throw new InvalidArgumentException('Define either the "auth_basic" or the "auth_bearer" option, setting both is not supported.');
|
148 |
-
}
|
149 |
-
|
150 |
-
if (null !== $url) {
|
151 |
-
// Merge auth with headers
|
152 |
-
if (($options['auth_basic'] ?? false) && !($options['normalized_headers']['authorization'] ?? false)) {
|
153 |
-
$options['normalized_headers']['authorization'] = ['Authorization: Basic '.base64_encode($options['auth_basic'])];
|
154 |
-
}
|
155 |
-
// Merge bearer with headers
|
156 |
-
if (($options['auth_bearer'] ?? false) && !($options['normalized_headers']['authorization'] ?? false)) {
|
157 |
-
$options['normalized_headers']['authorization'] = ['Authorization: Bearer '.$options['auth_bearer']];
|
158 |
-
}
|
159 |
-
|
160 |
-
unset($options['auth_basic'], $options['auth_bearer']);
|
161 |
-
|
162 |
-
// Parse base URI
|
163 |
-
if (\is_string($options['base_uri'])) {
|
164 |
-
$options['base_uri'] = self::parseUrl($options['base_uri']);
|
165 |
-
}
|
166 |
-
|
167 |
-
// Validate and resolve URL
|
168 |
-
$url = self::parseUrl($url, $options['query']);
|
169 |
-
$url = self::resolveUrl($url, $options['base_uri'], $defaultOptions['query'] ?? []);
|
170 |
-
}
|
171 |
-
|
172 |
-
// Finalize normalization of options
|
173 |
-
$options['http_version'] = (string) ($options['http_version'] ?? '') ?: null;
|
174 |
-
if (0 > $options['timeout'] = (float) ($options['timeout'] ?? ini_get('default_socket_timeout'))) {
|
175 |
-
$options['timeout'] = 172800.0; // 2 days
|
176 |
-
}
|
177 |
-
|
178 |
-
$options['max_duration'] = isset($options['max_duration']) ? (float) $options['max_duration'] : 0;
|
179 |
-
$options['headers'] = array_merge(...array_values($options['normalized_headers']));
|
180 |
-
|
181 |
-
return [$url, $options];
|
182 |
-
}
|
183 |
-
|
184 |
-
/**
|
185 |
-
* @throws InvalidArgumentException When an invalid option is found
|
186 |
-
*/
|
187 |
-
private static function mergeDefaultOptions(array $options, array $defaultOptions, bool $allowExtraOptions = false): array
|
188 |
-
{
|
189 |
-
$options['normalized_headers'] = self::normalizeHeaders($options['headers'] ?? []);
|
190 |
-
|
191 |
-
if ($defaultOptions['headers'] ?? false) {
|
192 |
-
$options['normalized_headers'] += self::normalizeHeaders($defaultOptions['headers']);
|
193 |
-
}
|
194 |
-
|
195 |
-
$options['headers'] = array_merge(...array_values($options['normalized_headers']) ?: [[]]);
|
196 |
-
|
197 |
-
if ($resolve = $options['resolve'] ?? false) {
|
198 |
-
$options['resolve'] = [];
|
199 |
-
foreach ($resolve as $k => $v) {
|
200 |
-
$options['resolve'][substr(self::parseUrl('http://'.$k)['authority'], 2)] = (string) $v;
|
201 |
-
}
|
202 |
-
}
|
203 |
-
|
204 |
-
// Option "query" is never inherited from defaults
|
205 |
-
$options['query'] = $options['query'] ?? [];
|
206 |
-
|
207 |
-
$options += $defaultOptions;
|
208 |
-
|
209 |
-
foreach (self::$emptyDefaults ?? [] as $k => $v) {
|
210 |
-
if (!isset($options[$k])) {
|
211 |
-
$options[$k] = $v;
|
212 |
-
}
|
213 |
-
}
|
214 |
-
|
215 |
-
if (isset($defaultOptions['extra'])) {
|
216 |
-
$options['extra'] += $defaultOptions['extra'];
|
217 |
-
}
|
218 |
-
|
219 |
-
if ($resolve = $defaultOptions['resolve'] ?? false) {
|
220 |
-
foreach ($resolve as $k => $v) {
|
221 |
-
$options['resolve'] += [substr(self::parseUrl('http://'.$k)['authority'], 2) => (string) $v];
|
222 |
-
}
|
223 |
-
}
|
224 |
-
|
225 |
-
if ($allowExtraOptions || !$defaultOptions) {
|
226 |
-
return $options;
|
227 |
-
}
|
228 |
-
|
229 |
-
// Look for unsupported options
|
230 |
-
foreach ($options as $name => $v) {
|
231 |
-
if (\array_key_exists($name, $defaultOptions) || 'normalized_headers' === $name) {
|
232 |
-
continue;
|
233 |
-
}
|
234 |
-
|
235 |
-
if ('auth_ntlm' === $name) {
|
236 |
-
if (!\extension_loaded('curl')) {
|
237 |
-
$msg = 'try installing the "curl" extension to use "%s" instead.';
|
238 |
-
} else {
|
239 |
-
$msg = 'try using "%s" instead.';
|
240 |
-
}
|
241 |
-
|
242 |
-
throw new InvalidArgumentException(sprintf('Option "auth_ntlm" is not supported by "%s", '.$msg, __CLASS__, CurlHttpClient::class));
|
243 |
-
}
|
244 |
-
|
245 |
-
$alternatives = [];
|
246 |
-
|
247 |
-
foreach ($defaultOptions as $k => $v) {
|
248 |
-
if (levenshtein($name, $k) <= \strlen($name) / 3 || str_contains($k, $name)) {
|
249 |
-
$alternatives[] = $k;
|
250 |
-
}
|
251 |
-
}
|
252 |
-
|
253 |
-
throw new InvalidArgumentException(sprintf('Unsupported option "%s" passed to "%s", did you mean "%s"?', $name, __CLASS__, implode('", "', $alternatives ?: array_keys($defaultOptions))));
|
254 |
-
}
|
255 |
-
|
256 |
-
return $options;
|
257 |
-
}
|
258 |
-
|
259 |
-
/**
|
260 |
-
* @return string[][]
|
261 |
-
*
|
262 |
-
* @throws InvalidArgumentException When an invalid header is found
|
263 |
-
*/
|
264 |
-
private static function normalizeHeaders(array $headers): array
|
265 |
-
{
|
266 |
-
$normalizedHeaders = [];
|
267 |
-
|
268 |
-
foreach ($headers as $name => $values) {
|
269 |
-
if (\is_object($values) && method_exists($values, '__toString')) {
|
270 |
-
$values = (string) $values;
|
271 |
-
}
|
272 |
-
|
273 |
-
if (\is_int($name)) {
|
274 |
-
if (!\is_string($values)) {
|
275 |
-
throw new InvalidArgumentException(sprintf('Invalid value for header "%s": expected string, "%s" given.', $name, get_debug_type($values)));
|
276 |
-
}
|
277 |
-
[$name, $values] = explode(':', $values, 2);
|
278 |
-
$values = [ltrim($values)];
|
279 |
-
} elseif (!is_iterable($values)) {
|
280 |
-
if (\is_object($values)) {
|
281 |
-
throw new InvalidArgumentException(sprintf('Invalid value for header "%s": expected string, "%s" given.', $name, get_debug_type($values)));
|
282 |
-
}
|
283 |
-
|
284 |
-
$values = (array) $values;
|
285 |
-
}
|
286 |
-
|
287 |
-
$lcName = strtolower($name);
|
288 |
-
$normalizedHeaders[$lcName] = [];
|
289 |
-
|
290 |
-
foreach ($values as $value) {
|
291 |
-
$normalizedHeaders[$lcName][] = $value = $name.': '.$value;
|
292 |
-
|
293 |
-
if (\strlen($value) !== strcspn($value, "\r\n\0")) {
|
294 |
-
throw new InvalidArgumentException(sprintf('Invalid header: CR/LF/NUL found in "%s".', $value));
|
295 |
-
}
|
296 |
-
}
|
297 |
-
}
|
298 |
-
|
299 |
-
return $normalizedHeaders;
|
300 |
-
}
|
301 |
-
|
302 |
-
/**
|
303 |
-
* @param array|string|resource|\Traversable|\Closure $body
|
304 |
-
*
|
305 |
-
* @return string|resource|\Closure
|
306 |
-
*
|
307 |
-
* @throws InvalidArgumentException When an invalid body is passed
|
308 |
-
*/
|
309 |
-
private static function normalizeBody($body)
|
310 |
-
{
|
311 |
-
if (\is_array($body)) {
|
312 |
-
array_walk_recursive($body, $caster = static function (&$v) use (&$caster) {
|
313 |
-
if (\is_object($v)) {
|
314 |
-
if ($vars = get_object_vars($v)) {
|
315 |
-
array_walk_recursive($vars, $caster);
|
316 |
-
$v = $vars;
|
317 |
-
} elseif (method_exists($v, '__toString')) {
|
318 |
-
$v = (string) $v;
|
319 |
-
}
|
320 |
-
}
|
321 |
-
});
|
322 |
-
|
323 |
-
return http_build_query($body, '', '&');
|
324 |
-
}
|
325 |
-
|
326 |
-
if (\is_string($body)) {
|
327 |
-
return $body;
|
328 |
-
}
|
329 |
-
|
330 |
-
$generatorToCallable = static function (\Generator $body): \Closure {
|
331 |
-
return static function () use ($body) {
|
332 |
-
while ($body->valid()) {
|
333 |
-
$chunk = $body->current();
|
334 |
-
$body->next();
|
335 |
-
|
336 |
-
if ('' !== $chunk) {
|
337 |
-
return $chunk;
|
338 |
-
}
|
339 |
-
}
|
340 |
-
|
341 |
-
return '';
|
342 |
-
};
|
343 |
-
};
|
344 |
-
|
345 |
-
if ($body instanceof \Generator) {
|
346 |
-
return $generatorToCallable($body);
|
347 |
-
}
|
348 |
-
|
349 |
-
if ($body instanceof \Traversable) {
|
350 |
-
return $generatorToCallable((static function ($body) { yield from $body; })($body));
|
351 |
-
}
|
352 |
-
|
353 |
-
if ($body instanceof \Closure) {
|
354 |
-
$r = new \ReflectionFunction($body);
|
355 |
-
$body = $r->getClosure();
|
356 |
-
|
357 |
-
if ($r->isGenerator()) {
|
358 |
-
$body = $body(self::$CHUNK_SIZE);
|
359 |
-
|
360 |
-
return $generatorToCallable($body);
|
361 |
-
}
|
362 |
-
|
363 |
-
return $body;
|
364 |
-
}
|
365 |
-
|
366 |
-
if (!\is_array(@stream_get_meta_data($body))) {
|
367 |
-
throw new InvalidArgumentException(sprintf('Option "body" must be string, stream resource, iterable or callable, "%s" given.', get_debug_type($body)));
|
368 |
-
}
|
369 |
-
|
370 |
-
return $body;
|
371 |
-
}
|
372 |
-
|
373 |
-
private static function dechunk(string $body): string
|
374 |
-
{
|
375 |
-
$h = fopen('php://temp', 'w+');
|
376 |
-
stream_filter_append($h, 'dechunk', \STREAM_FILTER_WRITE);
|
377 |
-
fwrite($h, $body);
|
378 |
-
$body = stream_get_contents($h, -1, 0);
|
379 |
-
rewind($h);
|
380 |
-
ftruncate($h, 0);
|
381 |
-
|
382 |
-
if (fwrite($h, '-') && '' !== stream_get_contents($h, -1, 0)) {
|
383 |
-
throw new TransportException('Request body has broken chunked encoding.');
|
384 |
-
}
|
385 |
-
|
386 |
-
return $body;
|
387 |
-
}
|
388 |
-
|
389 |
-
/**
|
390 |
-
* @param string|string[] $fingerprint
|
391 |
-
*
|
392 |
-
* @throws InvalidArgumentException When an invalid fingerprint is passed
|
393 |
-
*/
|
394 |
-
private static function normalizePeerFingerprint($fingerprint): array
|
395 |
-
{
|
396 |
-
if (\is_string($fingerprint)) {
|
397 |
-
switch (\strlen($fingerprint = str_replace(':', '', $fingerprint))) {
|
398 |
-
case 32: $fingerprint = ['md5' => $fingerprint]; break;
|
399 |
-
case 40: $fingerprint = ['sha1' => $fingerprint]; break;
|
400 |
-
case 44: $fingerprint = ['pin-sha256' => [$fingerprint]]; break;
|
401 |
-
case 64: $fingerprint = ['sha256' => $fingerprint]; break;
|
402 |
-
default: throw new InvalidArgumentException(sprintf('Cannot auto-detect fingerprint algorithm for "%s".', $fingerprint));
|
403 |
-
}
|
404 |
-
} elseif (\is_array($fingerprint)) {
|
405 |
-
foreach ($fingerprint as $algo => $hash) {
|
406 |
-
$fingerprint[$algo] = 'pin-sha256' === $algo ? (array) $hash : str_replace(':', '', $hash);
|
407 |
-
}
|
408 |
-
} else {
|
409 |
-
throw new InvalidArgumentException(sprintf('Option "peer_fingerprint" must be string or array, "%s" given.', get_debug_type($fingerprint)));
|
410 |
-
}
|
411 |
-
|
412 |
-
return $fingerprint;
|
413 |
-
}
|
414 |
-
|
415 |
-
/**
|
416 |
-
* @param mixed $value
|
417 |
-
*
|
418 |
-
* @throws InvalidArgumentException When the value cannot be json-encoded
|
419 |
-
*/
|
420 |
-
private static function jsonEncode($value, int $flags = null, int $maxDepth = 512): string
|
421 |
-
{
|
422 |
-
$flags = $flags ?? (\JSON_HEX_TAG | \JSON_HEX_APOS | \JSON_HEX_AMP | \JSON_HEX_QUOT | \JSON_PRESERVE_ZERO_FRACTION);
|
423 |
-
|
424 |
-
try {
|
425 |
-
$value = json_encode($value, $flags | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0), $maxDepth);
|
426 |
-
} catch (\JsonException $e) {
|
427 |
-
throw new InvalidArgumentException('Invalid value for "json" option: '.$e->getMessage());
|
428 |
-
}
|
429 |
-
|
430 |
-
if (\PHP_VERSION_ID < 70300 && \JSON_ERROR_NONE !== json_last_error() && (false === $value || !($flags & \JSON_PARTIAL_OUTPUT_ON_ERROR))) {
|
431 |
-
throw new InvalidArgumentException('Invalid value for "json" option: '.json_last_error_msg());
|
432 |
-
}
|
433 |
-
|
434 |
-
return $value;
|
435 |
-
}
|
436 |
-
|
437 |
-
/**
|
438 |
-
* Resolves a URL against a base URI.
|
439 |
-
*
|
440 |
-
* @see https://tools.ietf.org/html/rfc3986#section-5.2.2
|
441 |
-
*
|
442 |
-
* @throws InvalidArgumentException When an invalid URL is passed
|
443 |
-
*/
|
444 |
-
private static function resolveUrl(array $url, ?array $base, array $queryDefaults = []): array
|
445 |
-
{
|
446 |
-
if (null !== $base && '' === ($base['scheme'] ?? '').($base['authority'] ?? '')) {
|
447 |
-
throw new InvalidArgumentException(sprintf('Invalid "base_uri" option: host or scheme is missing in "%s".', implode('', $base)));
|
448 |
-
}
|
449 |
-
|
450 |
-
if (null === $url['scheme'] && (null === $base || null === $base['scheme'])) {
|
451 |
-
throw new InvalidArgumentException(sprintf('Invalid URL: scheme is missing in "%s". Did you forget to add "http(s)://"?', implode('', $base ?? $url)));
|
452 |
-
}
|
453 |
-
|
454 |
-
if (null === $base && '' === $url['scheme'].$url['authority']) {
|
455 |
-
throw new InvalidArgumentException(sprintf('Invalid URL: no "base_uri" option was provided and host or scheme is missing in "%s".', implode('', $url)));
|
456 |
-
}
|
457 |
-
|
458 |
-
if (null !== $url['scheme']) {
|
459 |
-
$url['path'] = self::removeDotSegments($url['path'] ?? '');
|
460 |
-
} else {
|
461 |
-
if (null !== $url['authority']) {
|
462 |
-
$url['path'] = self::removeDotSegments($url['path'] ?? '');
|
463 |
-
} else {
|
464 |
-
if (null === $url['path']) {
|
465 |
-
$url['path'] = $base['path'];
|
466 |
-
$url['query'] = $url['query'] ?? $base['query'];
|
467 |
-
} else {
|
468 |
-
if ('/' !== $url['path'][0]) {
|
469 |
-
if (null === $base['path']) {
|
470 |
-
$url['path'] = '/'.$url['path'];
|
471 |
-
} else {
|
472 |
-
$segments = explode('/', $base['path']);
|
473 |
-
array_splice($segments, -1, 1, [$url['path']]);
|
474 |
-
$url['path'] = implode('/', $segments);
|
475 |
-
}
|
476 |
-
}
|
477 |
-
|
478 |
-
$url['path'] = self::removeDotSegments($url['path']);
|
479 |
-
}
|
480 |
-
|
481 |
-
$url['authority'] = $base['authority'];
|
482 |
-
|
483 |
-
if ($queryDefaults) {
|
484 |
-
$url['query'] = '?'.self::mergeQueryString(substr($url['query'] ?? '', 1), $queryDefaults, false);
|
485 |
-
}
|
486 |
-
}
|
487 |
-
|
488 |
-
$url['scheme'] = $base['scheme'];
|
489 |
-
}
|
490 |
-
|
491 |
-
if ('' === ($url['path'] ?? '')) {
|
492 |
-
$url['path'] = '/';
|
493 |
-
}
|
494 |
-
|
495 |
-
if ('?' === ($url['query'] ?? '')) {
|
496 |
-
$url['query'] = null;
|
497 |
-
}
|
498 |
-
|
499 |
-
return $url;
|
500 |
-
}
|
501 |
-
|
502 |
-
/**
|
503 |
-
* Parses a URL and fixes its encoding if needed.
|
504 |
-
*
|
505 |
-
* @throws InvalidArgumentException When an invalid URL is passed
|
506 |
-
*/
|
507 |
-
private static function parseUrl(string $url, array $query = [], array $allowedSchemes = ['http' => 80, 'https' => 443]): array
|
508 |
-
{
|
509 |
-
if (false === $parts = parse_url($url)) {
|
510 |
-
throw new InvalidArgumentException(sprintf('Malformed URL "%s".', $url));
|
511 |
-
}
|
512 |
-
|
513 |
-
if ($query) {
|
514 |
-
$parts['query'] = self::mergeQueryString($parts['query'] ?? null, $query, true);
|
515 |
-
}
|
516 |
-
|
517 |
-
$port = $parts['port'] ?? 0;
|
518 |
-
|
519 |
-
if (null !== $scheme = $parts['scheme'] ?? null) {
|
520 |
-
if (!isset($allowedSchemes[$scheme = strtolower($scheme)])) {
|
521 |
-
throw new InvalidArgumentException(sprintf('Unsupported scheme in "%s".', $url));
|
522 |
-
}
|
523 |
-
|
524 |
-
$port = $allowedSchemes[$scheme] === $port ? 0 : $port;
|
525 |
-
$scheme .= ':';
|
526 |
-
}
|
527 |
-
|
528 |
-
if (null !== $host = $parts['host'] ?? null) {
|
529 |
-
if (!\defined('INTL_IDNA_VARIANT_UTS46') && preg_match('/[\x80-\xFF]/', $host)) {
|
530 |
-
throw new InvalidArgumentException(sprintf('Unsupported IDN "%s", try enabling the "intl" PHP extension or running "composer require symfony/polyfill-intl-idn".', $host));
|
531 |
-
}
|
532 |
-
|
533 |
-
$host = \defined('INTL_IDNA_VARIANT_UTS46') ? idn_to_ascii($host, \IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI | \IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII, \INTL_IDNA_VARIANT_UTS46) ?: strtolower($host) : strtolower($host);
|
534 |
-
$host .= $port ? ':'.$port : '';
|
535 |
-
}
|
536 |
-
|
537 |
-
foreach (['user', 'pass', 'path', 'query', 'fragment'] as $part) {
|
538 |
-
if (!isset($parts[$part])) {
|
539 |
-
continue;
|
540 |
-
}
|
541 |
-
|
542 |
-
if (str_contains($parts[$part], '%')) {
|
543 |
-
// https://tools.ietf.org/html/rfc3986#section-2.3
|
544 |
-
$parts[$part] = preg_replace_callback('/%(?:2[DE]|3[0-9]|[46][1-9A-F]|5F|[57][0-9A]|7E)++/i', function ($m) { return rawurldecode($m[0]); }, $parts[$part]);
|
545 |
-
}
|
546 |
-
|
547 |
-
// https://tools.ietf.org/html/rfc3986#section-3.3
|
548 |
-
$parts[$part] = preg_replace_callback("#[^-A-Za-z0-9._~!$&/'()*+,;=:@%]++#", function ($m) { return rawurlencode($m[0]); }, $parts[$part]);
|
549 |
-
}
|
550 |
-
|
551 |
-
return [
|
552 |
-
'scheme' => $scheme,
|
553 |
-
'authority' => null !== $host ? '//'.(isset($parts['user']) ? $parts['user'].(isset($parts['pass']) ? ':'.$parts['pass'] : '').'@' : '').$host : null,
|
554 |
-
'path' => isset($parts['path'][0]) ? $parts['path'] : null,
|
555 |
-
'query' => isset($parts['query']) ? '?'.$parts['query'] : null,
|
556 |
-
'fragment' => isset($parts['fragment']) ? '#'.$parts['fragment'] : null,
|
557 |
-
];
|
558 |
-
}
|
559 |
-
|
560 |
-
/**
|
561 |
-
* Removes dot-segments from a path.
|
562 |
-
*
|
563 |
-
* @see https://tools.ietf.org/html/rfc3986#section-5.2.4
|
564 |
-
*/
|
565 |
-
private static function removeDotSegments(string $path)
|
566 |
-
{
|
567 |
-
$result = '';
|
568 |
-
|
569 |
-
while (!\in_array($path, ['', '.', '..'], true)) {
|
570 |
-
if ('.' === $path[0] && (str_starts_with($path, $p = '../') || str_starts_with($path, $p = './'))) {
|
571 |
-
$path = substr($path, \strlen($p));
|
572 |
-
} elseif ('/.' === $path || str_starts_with($path, '/./')) {
|
573 |
-
$path = substr_replace($path, '/', 0, 3);
|
574 |
-
} elseif ('/..' === $path || str_starts_with($path, '/../')) {
|
575 |
-
$i = strrpos($result, '/');
|
576 |
-
$result = $i ? substr($result, 0, $i) : '';
|
577 |
-
$path = substr_replace($path, '/', 0, 4);
|
578 |
-
} else {
|
579 |
-
$i = strpos($path, '/', 1) ?: \strlen($path);
|
580 |
-
$result .= substr($path, 0, $i);
|
581 |
-
$path = substr($path, $i);
|
582 |
-
}
|
583 |
-
}
|
584 |
-
|
585 |
-
return $result;
|
586 |
-
}
|
587 |
-
|
588 |
-
/**
|
589 |
-
* Merges and encodes a query array with a query string.
|
590 |
-
*
|
591 |
-
* @throws InvalidArgumentException When an invalid query-string value is passed
|
592 |
-
*/
|
593 |
-
private static function mergeQueryString(?string $queryString, array $queryArray, bool $replace): ?string
|
594 |
-
{
|
595 |
-
if (!$queryArray) {
|
596 |
-
return $queryString;
|
597 |
-
}
|
598 |
-
|
599 |
-
$query = [];
|
600 |
-
|
601 |
-
if (null !== $queryString) {
|
602 |
-
foreach (explode('&', $queryString) as $v) {
|
603 |
-
if ('' !== $v) {
|
604 |
-
$k = urldecode(explode('=', $v, 2)[0]);
|
605 |
-
$query[$k] = (isset($query[$k]) ? $query[$k].'&' : '').$v;
|
606 |
-
}
|
607 |
-
}
|
608 |
-
}
|
609 |
-
|
610 |
-
if ($replace) {
|
611 |
-
foreach ($queryArray as $k => $v) {
|
612 |
-
if (null === $v) {
|
613 |
-
unset($query[$k]);
|
614 |
-
}
|
615 |
-
}
|
616 |
-
}
|
617 |
-
|
618 |
-
$queryString = http_build_query($queryArray, '', '&', \PHP_QUERY_RFC3986);
|
619 |
-
$queryArray = [];
|
620 |
-
|
621 |
-
if ($queryString) {
|
622 |
-
foreach (explode('&', $queryString) as $v) {
|
623 |
-
$queryArray[rawurldecode(explode('=', $v, 2)[0])] = $v;
|
624 |
-
}
|
625 |
-
}
|
626 |
-
|
627 |
-
return implode('&', $replace ? array_replace($query, $queryArray) : ($query + $queryArray));
|
628 |
-
}
|
629 |
-
|
630 |
-
/**
|
631 |
-
* Loads proxy configuration from the same environment variables as curl when no proxy is explicitly set.
|
632 |
-
*/
|
633 |
-
private static function getProxy(?string $proxy, array $url, ?string $noProxy): ?array
|
634 |
-
{
|
635 |
-
if (null === $proxy) {
|
636 |
-
// Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities
|
637 |
-
$proxy = $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null;
|
638 |
-
|
639 |
-
if ('https:' === $url['scheme']) {
|
640 |
-
$proxy = $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? $proxy;
|
641 |
-
}
|
642 |
-
}
|
643 |
-
|
644 |
-
if (null === $proxy) {
|
645 |
-
return null;
|
646 |
-
}
|
647 |
-
|
648 |
-
$proxy = (parse_url($proxy) ?: []) + ['scheme' => 'http'];
|
649 |
-
|
650 |
-
if (!isset($proxy['host'])) {
|
651 |
-
throw new TransportException('Invalid HTTP proxy: host is missing.');
|
652 |
-
}
|
653 |
-
|
654 |
-
if ('http' === $proxy['scheme']) {
|
655 |
-
$proxyUrl = 'tcp://'.$proxy['host'].':'.($proxy['port'] ?? '80');
|
656 |
-
} elseif ('https' === $proxy['scheme']) {
|
657 |
-
$proxyUrl = 'ssl://'.$proxy['host'].':'.($proxy['port'] ?? '443');
|
658 |
-
} else {
|
659 |
-
throw new TransportException(sprintf('Unsupported proxy scheme "%s": "http" or "https" expected.', $proxy['scheme']));
|
660 |
-
}
|
661 |
-
|
662 |
-
$noProxy = $noProxy ?? $_SERVER['no_proxy'] ?? $_SERVER['NO_PROXY'] ?? '';
|
663 |
-
$noProxy = $noProxy ? preg_split('/[\s,]+/', $noProxy) : [];
|
664 |
-
|
665 |
-
return [
|
666 |
-
'url' => $proxyUrl,
|
667 |
-
'auth' => isset($proxy['user']) ? 'Basic '.base64_encode(rawurldecode($proxy['user']).':'.rawurldecode($proxy['pass'] ?? '')) : null,
|
668 |
-
'no_proxy' => $noProxy,
|
669 |
-
];
|
670 |
-
}
|
671 |
-
|
672 |
-
private static function shouldBuffer(array $headers): bool
|
673 |
-
{
|
674 |
-
if (null === $contentType = $headers['content-type'][0] ?? null) {
|
675 |
-
return false;
|
676 |
-
}
|
677 |
-
|
678 |
-
if (false !== $i = strpos($contentType, ';')) {
|
679 |
-
$contentType = substr($contentType, 0, $i);
|
680 |
-
}
|
681 |
-
|
682 |
-
return $contentType && preg_match('#^(?:text/|application/(?:.+\+)?(?:json|xml)$)#i', $contentType);
|
683 |
-
}
|
684 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/HttpOptions.php
DELETED
@@ -1,331 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* A helper providing autocompletion for available options.
|
18 |
-
*
|
19 |
-
* @see HttpClientInterface for a description of each options.
|
20 |
-
*
|
21 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
22 |
-
*/
|
23 |
-
class HttpOptions
|
24 |
-
{
|
25 |
-
private $options = [];
|
26 |
-
|
27 |
-
public function toArray(): array
|
28 |
-
{
|
29 |
-
return $this->options;
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* @return $this
|
34 |
-
*/
|
35 |
-
public function setAuthBasic(string $user, string $password = '')
|
36 |
-
{
|
37 |
-
$this->options['auth_basic'] = $user;
|
38 |
-
|
39 |
-
if ('' !== $password) {
|
40 |
-
$this->options['auth_basic'] .= ':'.$password;
|
41 |
-
}
|
42 |
-
|
43 |
-
return $this;
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* @return $this
|
48 |
-
*/
|
49 |
-
public function setAuthBearer(string $token)
|
50 |
-
{
|
51 |
-
$this->options['auth_bearer'] = $token;
|
52 |
-
|
53 |
-
return $this;
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* @return $this
|
58 |
-
*/
|
59 |
-
public function setQuery(array $query)
|
60 |
-
{
|
61 |
-
$this->options['query'] = $query;
|
62 |
-
|
63 |
-
return $this;
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* @return $this
|
68 |
-
*/
|
69 |
-
public function setHeaders(iterable $headers)
|
70 |
-
{
|
71 |
-
$this->options['headers'] = $headers;
|
72 |
-
|
73 |
-
return $this;
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* @param array|string|resource|\Traversable|\Closure $body
|
78 |
-
*
|
79 |
-
* @return $this
|
80 |
-
*/
|
81 |
-
public function setBody($body)
|
82 |
-
{
|
83 |
-
$this->options['body'] = $body;
|
84 |
-
|
85 |
-
return $this;
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* @param mixed $json
|
90 |
-
*
|
91 |
-
* @return $this
|
92 |
-
*/
|
93 |
-
public function setJson($json)
|
94 |
-
{
|
95 |
-
$this->options['json'] = $json;
|
96 |
-
|
97 |
-
return $this;
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* @return $this
|
102 |
-
*/
|
103 |
-
public function setUserData($data)
|
104 |
-
{
|
105 |
-
$this->options['user_data'] = $data;
|
106 |
-
|
107 |
-
return $this;
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* @return $this
|
112 |
-
*/
|
113 |
-
public function setMaxRedirects(int $max)
|
114 |
-
{
|
115 |
-
$this->options['max_redirects'] = $max;
|
116 |
-
|
117 |
-
return $this;
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* @return $this
|
122 |
-
*/
|
123 |
-
public function setHttpVersion(string $version)
|
124 |
-
{
|
125 |
-
$this->options['http_version'] = $version;
|
126 |
-
|
127 |
-
return $this;
|
128 |
-
}
|
129 |
-
|
130 |
-
/**
|
131 |
-
* @return $this
|
132 |
-
*/
|
133 |
-
public function setBaseUri(string $uri)
|
134 |
-
{
|
135 |
-
$this->options['base_uri'] = $uri;
|
136 |
-
|
137 |
-
return $this;
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* @return $this
|
142 |
-
*/
|
143 |
-
public function buffer(bool $buffer)
|
144 |
-
{
|
145 |
-
$this->options['buffer'] = $buffer;
|
146 |
-
|
147 |
-
return $this;
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* @return $this
|
152 |
-
*/
|
153 |
-
public function setOnProgress(callable $callback)
|
154 |
-
{
|
155 |
-
$this->options['on_progress'] = $callback;
|
156 |
-
|
157 |
-
return $this;
|
158 |
-
}
|
159 |
-
|
160 |
-
/**
|
161 |
-
* @return $this
|
162 |
-
*/
|
163 |
-
public function resolve(array $hostIps)
|
164 |
-
{
|
165 |
-
$this->options['resolve'] = $hostIps;
|
166 |
-
|
167 |
-
return $this;
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* @return $this
|
172 |
-
*/
|
173 |
-
public function setProxy(string $proxy)
|
174 |
-
{
|
175 |
-
$this->options['proxy'] = $proxy;
|
176 |
-
|
177 |
-
return $this;
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* @return $this
|
182 |
-
*/
|
183 |
-
public function setNoProxy(string $noProxy)
|
184 |
-
{
|
185 |
-
$this->options['no_proxy'] = $noProxy;
|
186 |
-
|
187 |
-
return $this;
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* @return $this
|
192 |
-
*/
|
193 |
-
public function setTimeout(float $timeout)
|
194 |
-
{
|
195 |
-
$this->options['timeout'] = $timeout;
|
196 |
-
|
197 |
-
return $this;
|
198 |
-
}
|
199 |
-
|
200 |
-
/**
|
201 |
-
* @return $this
|
202 |
-
*/
|
203 |
-
public function setMaxDuration(float $maxDuration)
|
204 |
-
{
|
205 |
-
$this->options['max_duration'] = $maxDuration;
|
206 |
-
|
207 |
-
return $this;
|
208 |
-
}
|
209 |
-
|
210 |
-
/**
|
211 |
-
* @return $this
|
212 |
-
*/
|
213 |
-
public function bindTo(string $bindto)
|
214 |
-
{
|
215 |
-
$this->options['bindto'] = $bindto;
|
216 |
-
|
217 |
-
return $this;
|
218 |
-
}
|
219 |
-
|
220 |
-
/**
|
221 |
-
* @return $this
|
222 |
-
*/
|
223 |
-
public function verifyPeer(bool $verify)
|
224 |
-
{
|
225 |
-
$this->options['verify_peer'] = $verify;
|
226 |
-
|
227 |
-
return $this;
|
228 |
-
}
|
229 |
-
|
230 |
-
/**
|
231 |
-
* @return $this
|
232 |
-
*/
|
233 |
-
public function verifyHost(bool $verify)
|
234 |
-
{
|
235 |
-
$this->options['verify_host'] = $verify;
|
236 |
-
|
237 |
-
return $this;
|
238 |
-
}
|
239 |
-
|
240 |
-
/**
|
241 |
-
* @return $this
|
242 |
-
*/
|
243 |
-
public function setCaFile(string $cafile)
|
244 |
-
{
|
245 |
-
$this->options['cafile'] = $cafile;
|
246 |
-
|
247 |
-
return $this;
|
248 |
-
}
|
249 |
-
|
250 |
-
/**
|
251 |
-
* @return $this
|
252 |
-
*/
|
253 |
-
public function setCaPath(string $capath)
|
254 |
-
{
|
255 |
-
$this->options['capath'] = $capath;
|
256 |
-
|
257 |
-
return $this;
|
258 |
-
}
|
259 |
-
|
260 |
-
/**
|
261 |
-
* @return $this
|
262 |
-
*/
|
263 |
-
public function setLocalCert(string $cert)
|
264 |
-
{
|
265 |
-
$this->options['local_cert'] = $cert;
|
266 |
-
|
267 |
-
return $this;
|
268 |
-
}
|
269 |
-
|
270 |
-
/**
|
271 |
-
* @return $this
|
272 |
-
*/
|
273 |
-
public function setLocalPk(string $pk)
|
274 |
-
{
|
275 |
-
$this->options['local_pk'] = $pk;
|
276 |
-
|
277 |
-
return $this;
|
278 |
-
}
|
279 |
-
|
280 |
-
/**
|
281 |
-
* @return $this
|
282 |
-
*/
|
283 |
-
public function setPassphrase(string $passphrase)
|
284 |
-
{
|
285 |
-
$this->options['passphrase'] = $passphrase;
|
286 |
-
|
287 |
-
return $this;
|
288 |
-
}
|
289 |
-
|
290 |
-
/**
|
291 |
-
* @return $this
|
292 |
-
*/
|
293 |
-
public function setCiphers(string $ciphers)
|
294 |
-
{
|
295 |
-
$this->options['ciphers'] = $ciphers;
|
296 |
-
|
297 |
-
return $this;
|
298 |
-
}
|
299 |
-
|
300 |
-
/**
|
301 |
-
* @param string|array $fingerprint
|
302 |
-
*
|
303 |
-
* @return $this
|
304 |
-
*/
|
305 |
-
public function setPeerFingerprint($fingerprint)
|
306 |
-
{
|
307 |
-
$this->options['peer_fingerprint'] = $fingerprint;
|
308 |
-
|
309 |
-
return $this;
|
310 |
-
}
|
311 |
-
|
312 |
-
/**
|
313 |
-
* @return $this
|
314 |
-
*/
|
315 |
-
public function capturePeerCertChain(bool $capture)
|
316 |
-
{
|
317 |
-
$this->options['capture_peer_cert_chain'] = $capture;
|
318 |
-
|
319 |
-
return $this;
|
320 |
-
}
|
321 |
-
|
322 |
-
/**
|
323 |
-
* @return $this
|
324 |
-
*/
|
325 |
-
public function setExtra(string $name, $value)
|
326 |
-
{
|
327 |
-
$this->options['extra'][$name] = $value;
|
328 |
-
|
329 |
-
return $this;
|
330 |
-
}
|
331 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/HttplugClient.php
DELETED
@@ -1,271 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use GuzzleHttp\Promise\Promise as GuzzlePromise;
|
15 |
-
use GuzzleHttp\Promise\RejectedPromise;
|
16 |
-
use GuzzleHttp\Promise\Utils;
|
17 |
-
use Http\Client\Exception\NetworkException;
|
18 |
-
use Http\Client\Exception\RequestException;
|
19 |
-
use Http\Client\HttpAsyncClient;
|
20 |
-
use Http\Client\HttpClient as HttplugInterface;
|
21 |
-
use Http\Discovery\Exception\NotFoundException;
|
22 |
-
use Http\Discovery\Psr17FactoryDiscovery;
|
23 |
-
use Http\Message\RequestFactory;
|
24 |
-
use Http\Message\StreamFactory;
|
25 |
-
use Http\Message\UriFactory;
|
26 |
-
use Http\Promise\Promise;
|
27 |
-
use Nyholm\Psr7\Factory\Psr17Factory;
|
28 |
-
use Nyholm\Psr7\Request;
|
29 |
-
use Nyholm\Psr7\Uri;
|
30 |
-
use Psr\Http\Message\RequestFactoryInterface;
|
31 |
-
use Psr\Http\Message\RequestInterface;
|
32 |
-
use Psr\Http\Message\ResponseFactoryInterface;
|
33 |
-
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
|
34 |
-
use Psr\Http\Message\StreamFactoryInterface;
|
35 |
-
use Psr\Http\Message\StreamInterface;
|
36 |
-
use Psr\Http\Message\UriFactoryInterface;
|
37 |
-
use Psr\Http\Message\UriInterface;
|
38 |
-
use Symfony\Component\HttpClient\Internal\HttplugWaitLoop;
|
39 |
-
use Symfony\Component\HttpClient\Response\HttplugPromise;
|
40 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
41 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
42 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
43 |
-
use Symfony\Contracts\Service\ResetInterface;
|
44 |
-
|
45 |
-
if (!interface_exists(HttplugInterface::class)) {
|
46 |
-
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/httplug" package is not installed. Try running "composer require php-http/httplug".');
|
47 |
-
}
|
48 |
-
|
49 |
-
if (!interface_exists(RequestFactory::class)) {
|
50 |
-
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/message-factory" package is not installed. Try running "composer require nyholm/psr7".');
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* An adapter to turn a Symfony HttpClientInterface into an Httplug client.
|
55 |
-
*
|
56 |
-
* Run "composer require nyholm/psr7" to install an efficient implementation of response
|
57 |
-
* and stream factories with flex-provided autowiring aliases.
|
58 |
-
*
|
59 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
60 |
-
*/
|
61 |
-
final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestFactory, StreamFactory, UriFactory, ResetInterface
|
62 |
-
{
|
63 |
-
private $client;
|
64 |
-
private $responseFactory;
|
65 |
-
private $streamFactory;
|
66 |
-
|
67 |
-
/**
|
68 |
-
* @var \SplObjectStorage<ResponseInterface, array{RequestInterface, Promise}>|null
|
69 |
-
*/
|
70 |
-
private $promisePool;
|
71 |
-
|
72 |
-
private $waitLoop;
|
73 |
-
|
74 |
-
public function __construct(HttpClientInterface $client = null, ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null)
|
75 |
-
{
|
76 |
-
$this->client = $client ?? HttpClient::create();
|
77 |
-
$this->responseFactory = $responseFactory;
|
78 |
-
$this->streamFactory = $streamFactory ?? ($responseFactory instanceof StreamFactoryInterface ? $responseFactory : null);
|
79 |
-
$this->promisePool = class_exists(Utils::class) ? new \SplObjectStorage() : null;
|
80 |
-
|
81 |
-
if (null === $this->responseFactory || null === $this->streamFactory) {
|
82 |
-
if (!class_exists(Psr17Factory::class) && !class_exists(Psr17FactoryDiscovery::class)) {
|
83 |
-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
|
84 |
-
}
|
85 |
-
|
86 |
-
try {
|
87 |
-
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
|
88 |
-
$this->responseFactory = $this->responseFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
|
89 |
-
$this->streamFactory = $this->streamFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
|
90 |
-
} catch (NotFoundException $e) {
|
91 |
-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been found. Try running "composer require nyholm/psr7".', 0, $e);
|
92 |
-
}
|
93 |
-
}
|
94 |
-
|
95 |
-
$this->waitLoop = new HttplugWaitLoop($this->client, $this->promisePool, $this->responseFactory, $this->streamFactory);
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* {@inheritdoc}
|
100 |
-
*/
|
101 |
-
public function sendRequest(RequestInterface $request): Psr7ResponseInterface
|
102 |
-
{
|
103 |
-
try {
|
104 |
-
return $this->waitLoop->createPsr7Response($this->sendPsr7Request($request));
|
105 |
-
} catch (TransportExceptionInterface $e) {
|
106 |
-
throw new NetworkException($e->getMessage(), $request, $e);
|
107 |
-
}
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* {@inheritdoc}
|
112 |
-
*
|
113 |
-
* @return HttplugPromise
|
114 |
-
*/
|
115 |
-
public function sendAsyncRequest(RequestInterface $request): Promise
|
116 |
-
{
|
117 |
-
if (!$promisePool = $this->promisePool) {
|
118 |
-
throw new \LogicException(sprintf('You cannot use "%s()" as the "guzzlehttp/promises" package is not installed. Try running "composer require guzzlehttp/promises".', __METHOD__));
|
119 |
-
}
|
120 |
-
|
121 |
-
try {
|
122 |
-
$response = $this->sendPsr7Request($request, true);
|
123 |
-
} catch (NetworkException $e) {
|
124 |
-
return new HttplugPromise(new RejectedPromise($e));
|
125 |
-
}
|
126 |
-
|
127 |
-
$waitLoop = $this->waitLoop;
|
128 |
-
|
129 |
-
$promise = new GuzzlePromise(static function () use ($response, $waitLoop) {
|
130 |
-
$waitLoop->wait($response);
|
131 |
-
}, static function () use ($response, $promisePool) {
|
132 |
-
$response->cancel();
|
133 |
-
unset($promisePool[$response]);
|
134 |
-
});
|
135 |
-
|
136 |
-
$promisePool[$response] = [$request, $promise];
|
137 |
-
|
138 |
-
return new HttplugPromise($promise);
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Resolves pending promises that complete before the timeouts are reached.
|
143 |
-
*
|
144 |
-
* When $maxDuration is null and $idleTimeout is reached, promises are rejected.
|
145 |
-
*
|
146 |
-
* @return int The number of remaining pending promises
|
147 |
-
*/
|
148 |
-
public function wait(float $maxDuration = null, float $idleTimeout = null): int
|
149 |
-
{
|
150 |
-
return $this->waitLoop->wait(null, $maxDuration, $idleTimeout);
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* {@inheritdoc}
|
155 |
-
*/
|
156 |
-
public function createRequest($method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1'): RequestInterface
|
157 |
-
{
|
158 |
-
if ($this->responseFactory instanceof RequestFactoryInterface) {
|
159 |
-
$request = $this->responseFactory->createRequest($method, $uri);
|
160 |
-
} elseif (class_exists(Request::class)) {
|
161 |
-
$request = new Request($method, $uri);
|
162 |
-
} elseif (class_exists(Psr17FactoryDiscovery::class)) {
|
163 |
-
$request = Psr17FactoryDiscovery::findRequestFactory()->createRequest($method, $uri);
|
164 |
-
} else {
|
165 |
-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
|
166 |
-
}
|
167 |
-
|
168 |
-
$request = $request
|
169 |
-
->withProtocolVersion($protocolVersion)
|
170 |
-
->withBody($this->createStream($body))
|
171 |
-
;
|
172 |
-
|
173 |
-
foreach ($headers as $name => $value) {
|
174 |
-
$request = $request->withAddedHeader($name, $value);
|
175 |
-
}
|
176 |
-
|
177 |
-
return $request;
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* {@inheritdoc}
|
182 |
-
*/
|
183 |
-
public function createStream($body = null): StreamInterface
|
184 |
-
{
|
185 |
-
if ($body instanceof StreamInterface) {
|
186 |
-
return $body;
|
187 |
-
}
|
188 |
-
|
189 |
-
if (\is_string($body ?? '')) {
|
190 |
-
$stream = $this->streamFactory->createStream($body ?? '');
|
191 |
-
} elseif (\is_resource($body)) {
|
192 |
-
$stream = $this->streamFactory->createStreamFromResource($body);
|
193 |
-
} else {
|
194 |
-
throw new \InvalidArgumentException(sprintf('"%s()" expects string, resource or StreamInterface, "%s" given.', __METHOD__, get_debug_type($body)));
|
195 |
-
}
|
196 |
-
|
197 |
-
if ($stream->isSeekable()) {
|
198 |
-
$stream->seek(0);
|
199 |
-
}
|
200 |
-
|
201 |
-
return $stream;
|
202 |
-
}
|
203 |
-
|
204 |
-
/**
|
205 |
-
* {@inheritdoc}
|
206 |
-
*/
|
207 |
-
public function createUri($uri): UriInterface
|
208 |
-
{
|
209 |
-
if ($uri instanceof UriInterface) {
|
210 |
-
return $uri;
|
211 |
-
}
|
212 |
-
|
213 |
-
if ($this->responseFactory instanceof UriFactoryInterface) {
|
214 |
-
return $this->responseFactory->createUri($uri);
|
215 |
-
}
|
216 |
-
|
217 |
-
if (class_exists(Uri::class)) {
|
218 |
-
return new Uri($uri);
|
219 |
-
}
|
220 |
-
|
221 |
-
if (class_exists(Psr17FactoryDiscovery::class)) {
|
222 |
-
return Psr17FactoryDiscovery::findUrlFactory()->createUri($uri);
|
223 |
-
}
|
224 |
-
|
225 |
-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
|
226 |
-
}
|
227 |
-
|
228 |
-
public function __sleep(): array
|
229 |
-
{
|
230 |
-
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
231 |
-
}
|
232 |
-
|
233 |
-
public function __wakeup()
|
234 |
-
{
|
235 |
-
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
236 |
-
}
|
237 |
-
|
238 |
-
public function __destruct()
|
239 |
-
{
|
240 |
-
$this->wait();
|
241 |
-
}
|
242 |
-
|
243 |
-
public function reset()
|
244 |
-
{
|
245 |
-
if ($this->client instanceof ResetInterface) {
|
246 |
-
$this->client->reset();
|
247 |
-
}
|
248 |
-
}
|
249 |
-
|
250 |
-
private function sendPsr7Request(RequestInterface $request, bool $buffer = null): ResponseInterface
|
251 |
-
{
|
252 |
-
try {
|
253 |
-
$body = $request->getBody();
|
254 |
-
|
255 |
-
if ($body->isSeekable()) {
|
256 |
-
$body->seek(0);
|
257 |
-
}
|
258 |
-
|
259 |
-
return $this->client->request($request->getMethod(), (string) $request->getUri(), [
|
260 |
-
'headers' => $request->getHeaders(),
|
261 |
-
'body' => $body->getContents(),
|
262 |
-
'http_version' => '1.0' === $request->getProtocolVersion() ? '1.0' : null,
|
263 |
-
'buffer' => $buffer,
|
264 |
-
]);
|
265 |
-
} catch (\InvalidArgumentException $e) {
|
266 |
-
throw new RequestException($e->getMessage(), $request, $e);
|
267 |
-
} catch (TransportExceptionInterface $e) {
|
268 |
-
throw new NetworkException($e->getMessage(), $request, $e);
|
269 |
-
}
|
270 |
-
}
|
271 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/AmpBody.php
DELETED
@@ -1,142 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
use Amp\ByteStream\InputStream;
|
15 |
-
use Amp\ByteStream\ResourceInputStream;
|
16 |
-
use Amp\Http\Client\RequestBody;
|
17 |
-
use Amp\Promise;
|
18 |
-
use Amp\Success;
|
19 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
23 |
-
*
|
24 |
-
* @internal
|
25 |
-
*/
|
26 |
-
class AmpBody implements RequestBody, InputStream
|
27 |
-
{
|
28 |
-
private $body;
|
29 |
-
private $info;
|
30 |
-
private $onProgress;
|
31 |
-
private $offset = 0;
|
32 |
-
private $length = -1;
|
33 |
-
private $uploaded;
|
34 |
-
|
35 |
-
public function __construct($body, &$info, \Closure $onProgress)
|
36 |
-
{
|
37 |
-
$this->body = $body;
|
38 |
-
$this->info = &$info;
|
39 |
-
$this->onProgress = $onProgress;
|
40 |
-
|
41 |
-
if (\is_resource($body)) {
|
42 |
-
$this->offset = ftell($body);
|
43 |
-
$this->length = fstat($body)['size'];
|
44 |
-
$this->body = new ResourceInputStream($body);
|
45 |
-
} elseif (\is_string($body)) {
|
46 |
-
$this->length = \strlen($body);
|
47 |
-
}
|
48 |
-
}
|
49 |
-
|
50 |
-
public function createBodyStream(): InputStream
|
51 |
-
{
|
52 |
-
if (null !== $this->uploaded) {
|
53 |
-
$this->uploaded = null;
|
54 |
-
|
55 |
-
if (\is_string($this->body)) {
|
56 |
-
$this->offset = 0;
|
57 |
-
} elseif ($this->body instanceof ResourceInputStream) {
|
58 |
-
fseek($this->body->getResource(), $this->offset);
|
59 |
-
}
|
60 |
-
}
|
61 |
-
|
62 |
-
return $this;
|
63 |
-
}
|
64 |
-
|
65 |
-
public function getHeaders(): Promise
|
66 |
-
{
|
67 |
-
return new Success([]);
|
68 |
-
}
|
69 |
-
|
70 |
-
public function getBodyLength(): Promise
|
71 |
-
{
|
72 |
-
return new Success($this->length - $this->offset);
|
73 |
-
}
|
74 |
-
|
75 |
-
public function read(): Promise
|
76 |
-
{
|
77 |
-
$this->info['size_upload'] += $this->uploaded;
|
78 |
-
$this->uploaded = 0;
|
79 |
-
($this->onProgress)();
|
80 |
-
|
81 |
-
$chunk = $this->doRead();
|
82 |
-
$chunk->onResolve(function ($e, $data) {
|
83 |
-
if (null !== $data) {
|
84 |
-
$this->uploaded = \strlen($data);
|
85 |
-
} else {
|
86 |
-
$this->info['upload_content_length'] = $this->info['size_upload'];
|
87 |
-
}
|
88 |
-
});
|
89 |
-
|
90 |
-
return $chunk;
|
91 |
-
}
|
92 |
-
|
93 |
-
public static function rewind(RequestBody $body): RequestBody
|
94 |
-
{
|
95 |
-
if (!$body instanceof self) {
|
96 |
-
return $body;
|
97 |
-
}
|
98 |
-
|
99 |
-
$body->uploaded = null;
|
100 |
-
|
101 |
-
if ($body->body instanceof ResourceInputStream) {
|
102 |
-
fseek($body->body->getResource(), $body->offset);
|
103 |
-
|
104 |
-
return new $body($body->body, $body->info, $body->onProgress);
|
105 |
-
}
|
106 |
-
|
107 |
-
if (\is_string($body->body)) {
|
108 |
-
$body->offset = 0;
|
109 |
-
}
|
110 |
-
|
111 |
-
return $body;
|
112 |
-
}
|
113 |
-
|
114 |
-
private function doRead(): Promise
|
115 |
-
{
|
116 |
-
if ($this->body instanceof ResourceInputStream) {
|
117 |
-
return $this->body->read();
|
118 |
-
}
|
119 |
-
|
120 |
-
if (null === $this->offset || !$this->length) {
|
121 |
-
return new Success();
|
122 |
-
}
|
123 |
-
|
124 |
-
if (\is_string($this->body)) {
|
125 |
-
$this->offset = null;
|
126 |
-
|
127 |
-
return new Success($this->body);
|
128 |
-
}
|
129 |
-
|
130 |
-
if ('' === $data = ($this->body)(16372)) {
|
131 |
-
$this->offset = null;
|
132 |
-
|
133 |
-
return new Success();
|
134 |
-
}
|
135 |
-
|
136 |
-
if (!\is_string($data)) {
|
137 |
-
throw new TransportException(sprintf('Return value of the "body" option callback must be string, "%s" returned.', get_debug_type($data)));
|
138 |
-
}
|
139 |
-
|
140 |
-
return new Success($data);
|
141 |
-
}
|
142 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/AmpClientState.php
DELETED
@@ -1,217 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
use Amp\CancellationToken;
|
15 |
-
use Amp\Deferred;
|
16 |
-
use Amp\Http\Client\Connection\ConnectionLimitingPool;
|
17 |
-
use Amp\Http\Client\Connection\DefaultConnectionFactory;
|
18 |
-
use Amp\Http\Client\InterceptedHttpClient;
|
19 |
-
use Amp\Http\Client\Interceptor\RetryRequests;
|
20 |
-
use Amp\Http\Client\PooledHttpClient;
|
21 |
-
use Amp\Http\Client\Request;
|
22 |
-
use Amp\Http\Client\Response;
|
23 |
-
use Amp\Http\Tunnel\Http1TunnelConnector;
|
24 |
-
use Amp\Http\Tunnel\Https1TunnelConnector;
|
25 |
-
use Amp\Promise;
|
26 |
-
use Amp\Socket\Certificate;
|
27 |
-
use Amp\Socket\ClientTlsContext;
|
28 |
-
use Amp\Socket\ConnectContext;
|
29 |
-
use Amp\Socket\Connector;
|
30 |
-
use Amp\Socket\DnsConnector;
|
31 |
-
use Amp\Socket\SocketAddress;
|
32 |
-
use Amp\Success;
|
33 |
-
use Psr\Log\LoggerInterface;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Internal representation of the Amp client's state.
|
37 |
-
*
|
38 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
39 |
-
*
|
40 |
-
* @internal
|
41 |
-
*/
|
42 |
-
final class AmpClientState extends ClientState
|
43 |
-
{
|
44 |
-
public $dnsCache = [];
|
45 |
-
public $responseCount = 0;
|
46 |
-
public $pushedResponses = [];
|
47 |
-
|
48 |
-
private $clients = [];
|
49 |
-
private $clientConfigurator;
|
50 |
-
private $maxHostConnections;
|
51 |
-
private $maxPendingPushes;
|
52 |
-
private $logger;
|
53 |
-
|
54 |
-
public function __construct(?callable $clientConfigurator, int $maxHostConnections, int $maxPendingPushes, ?LoggerInterface &$logger)
|
55 |
-
{
|
56 |
-
$this->clientConfigurator = $clientConfigurator ?? static function (PooledHttpClient $client) {
|
57 |
-
return new InterceptedHttpClient($client, new RetryRequests(2));
|
58 |
-
};
|
59 |
-
$this->maxHostConnections = $maxHostConnections;
|
60 |
-
$this->maxPendingPushes = $maxPendingPushes;
|
61 |
-
$this->logger = &$logger;
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* @return Promise<Response>
|
66 |
-
*/
|
67 |
-
public function request(array $options, Request $request, CancellationToken $cancellation, array &$info, \Closure $onProgress, &$handle): Promise
|
68 |
-
{
|
69 |
-
if ($options['proxy']) {
|
70 |
-
if ($request->hasHeader('proxy-authorization')) {
|
71 |
-
$options['proxy']['auth'] = $request->getHeader('proxy-authorization');
|
72 |
-
}
|
73 |
-
|
74 |
-
// Matching "no_proxy" should follow the behavior of curl
|
75 |
-
$host = $request->getUri()->getHost();
|
76 |
-
foreach ($options['proxy']['no_proxy'] as $rule) {
|
77 |
-
$dotRule = '.'.ltrim($rule, '.');
|
78 |
-
|
79 |
-
if ('*' === $rule || $host === $rule || substr($host, -\strlen($dotRule)) === $dotRule) {
|
80 |
-
$options['proxy'] = null;
|
81 |
-
break;
|
82 |
-
}
|
83 |
-
}
|
84 |
-
}
|
85 |
-
|
86 |
-
$request = clone $request;
|
87 |
-
|
88 |
-
if ($request->hasHeader('proxy-authorization')) {
|
89 |
-
$request->removeHeader('proxy-authorization');
|
90 |
-
}
|
91 |
-
|
92 |
-
if ($options['capture_peer_cert_chain']) {
|
93 |
-
$info['peer_certificate_chain'] = [];
|
94 |
-
}
|
95 |
-
|
96 |
-
$request->addEventListener(new AmpListener($info, $options['peer_fingerprint']['pin-sha256'] ?? [], $onProgress, $handle));
|
97 |
-
$request->setPushHandler(function ($request, $response) use ($options): Promise {
|
98 |
-
return $this->handlePush($request, $response, $options);
|
99 |
-
});
|
100 |
-
|
101 |
-
($request->hasHeader('content-length') ? new Success((int) $request->getHeader('content-length')) : $request->getBody()->getBodyLength())
|
102 |
-
->onResolve(static function ($e, $bodySize) use (&$info) {
|
103 |
-
if (null !== $bodySize && 0 <= $bodySize) {
|
104 |
-
$info['upload_content_length'] = ((1 + $info['upload_content_length']) ?? 1) - 1 + $bodySize;
|
105 |
-
}
|
106 |
-
});
|
107 |
-
|
108 |
-
[$client, $connector] = $this->getClient($options);
|
109 |
-
$response = $client->request($request, $cancellation);
|
110 |
-
$response->onResolve(static function ($e) use ($connector, &$handle) {
|
111 |
-
if (null === $e) {
|
112 |
-
$handle = $connector->handle;
|
113 |
-
}
|
114 |
-
});
|
115 |
-
|
116 |
-
return $response;
|
117 |
-
}
|
118 |
-
|
119 |
-
private function getClient(array $options): array
|
120 |
-
{
|
121 |
-
$options = [
|
122 |
-
'bindto' => $options['bindto'] ?: '0',
|
123 |
-
'verify_peer' => $options['verify_peer'],
|
124 |
-
'capath' => $options['capath'],
|
125 |
-
'cafile' => $options['cafile'],
|
126 |
-
'local_cert' => $options['local_cert'],
|
127 |
-
'local_pk' => $options['local_pk'],
|
128 |
-
'ciphers' => $options['ciphers'],
|
129 |
-
'capture_peer_cert_chain' => $options['capture_peer_cert_chain'] || $options['peer_fingerprint'],
|
130 |
-
'proxy' => $options['proxy'],
|
131 |
-
];
|
132 |
-
|
133 |
-
$key = md5(serialize($options));
|
134 |
-
|
135 |
-
if (isset($this->clients[$key])) {
|
136 |
-
return $this->clients[$key];
|
137 |
-
}
|
138 |
-
|
139 |
-
$context = new ClientTlsContext('');
|
140 |
-
$options['verify_peer'] || $context = $context->withoutPeerVerification();
|
141 |
-
$options['cafile'] && $context = $context->withCaFile($options['cafile']);
|
142 |
-
$options['capath'] && $context = $context->withCaPath($options['capath']);
|
143 |
-
$options['local_cert'] && $context = $context->withCertificate(new Certificate($options['local_cert'], $options['local_pk']));
|
144 |
-
$options['ciphers'] && $context = $context->withCiphers($options['ciphers']);
|
145 |
-
$options['capture_peer_cert_chain'] && $context = $context->withPeerCapturing();
|
146 |
-
|
147 |
-
$connector = $handleConnector = new class() implements Connector {
|
148 |
-
public $connector;
|
149 |
-
public $uri;
|
150 |
-
public $handle;
|
151 |
-
|
152 |
-
public function connect(string $uri, ConnectContext $context = null, CancellationToken $token = null): Promise
|
153 |
-
{
|
154 |
-
$result = $this->connector->connect($this->uri ?? $uri, $context, $token);
|
155 |
-
$result->onResolve(function ($e, $socket) {
|
156 |
-
$this->handle = null !== $socket ? $socket->getResource() : false;
|
157 |
-
});
|
158 |
-
|
159 |
-
return $result;
|
160 |
-
}
|
161 |
-
};
|
162 |
-
$connector->connector = new DnsConnector(new AmpResolver($this->dnsCache));
|
163 |
-
|
164 |
-
$context = (new ConnectContext())
|
165 |
-
->withTcpNoDelay()
|
166 |
-
->withTlsContext($context);
|
167 |
-
|
168 |
-
if ($options['bindto']) {
|
169 |
-
if (file_exists($options['bindto'])) {
|
170 |
-
$connector->uri = 'unix://'.$options['bindto'];
|
171 |
-
} else {
|
172 |
-
$context = $context->withBindTo($options['bindto']);
|
173 |
-
}
|
174 |
-
}
|
175 |
-
|
176 |
-
if ($options['proxy']) {
|
177 |
-
$proxyUrl = parse_url($options['proxy']['url']);
|
178 |
-
$proxySocket = new SocketAddress($proxyUrl['host'], $proxyUrl['port']);
|
179 |
-
$proxyHeaders = $options['proxy']['auth'] ? ['Proxy-Authorization' => $options['proxy']['auth']] : [];
|
180 |
-
|
181 |
-
if ('ssl' === $proxyUrl['scheme']) {
|
182 |
-
$connector = new Https1TunnelConnector($proxySocket, $context->getTlsContext(), $proxyHeaders, $connector);
|
183 |
-
} else {
|
184 |
-
$connector = new Http1TunnelConnector($proxySocket, $proxyHeaders, $connector);
|
185 |
-
}
|
186 |
-
}
|
187 |
-
|
188 |
-
$maxHostConnections = 0 < $this->maxHostConnections ? $this->maxHostConnections : \PHP_INT_MAX;
|
189 |
-
$pool = new DefaultConnectionFactory($connector, $context);
|
190 |
-
$pool = ConnectionLimitingPool::byAuthority($maxHostConnections, $pool);
|
191 |
-
|
192 |
-
return $this->clients[$key] = [($this->clientConfigurator)(new PooledHttpClient($pool)), $handleConnector];
|
193 |
-
}
|
194 |
-
|
195 |
-
private function handlePush(Request $request, Promise $response, array $options): Promise
|
196 |
-
{
|
197 |
-
$deferred = new Deferred();
|
198 |
-
$authority = $request->getUri()->getAuthority();
|
199 |
-
|
200 |
-
if ($this->maxPendingPushes <= \count($this->pushedResponses[$authority] ?? [])) {
|
201 |
-
$fifoUrl = key($this->pushedResponses[$authority]);
|
202 |
-
unset($this->pushedResponses[$authority][$fifoUrl]);
|
203 |
-
$this->logger && $this->logger->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl));
|
204 |
-
}
|
205 |
-
|
206 |
-
$url = (string) $request->getUri();
|
207 |
-
$this->logger && $this->logger->debug(sprintf('Queueing pushed response: "%s"', $url));
|
208 |
-
$this->pushedResponses[$authority][] = [$url, $deferred, $request, $response, [
|
209 |
-
'proxy' => $options['proxy'],
|
210 |
-
'bindto' => $options['bindto'],
|
211 |
-
'local_cert' => $options['local_cert'],
|
212 |
-
'local_pk' => $options['local_pk'],
|
213 |
-
]];
|
214 |
-
|
215 |
-
return $deferred->promise();
|
216 |
-
}
|
217 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/AmpListener.php
DELETED
@@ -1,183 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
use Amp\Http\Client\Connection\Stream;
|
15 |
-
use Amp\Http\Client\EventListener;
|
16 |
-
use Amp\Http\Client\Request;
|
17 |
-
use Amp\Promise;
|
18 |
-
use Amp\Success;
|
19 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
23 |
-
*
|
24 |
-
* @internal
|
25 |
-
*/
|
26 |
-
class AmpListener implements EventListener
|
27 |
-
{
|
28 |
-
private $info;
|
29 |
-
private $pinSha256;
|
30 |
-
private $onProgress;
|
31 |
-
private $handle;
|
32 |
-
|
33 |
-
public function __construct(array &$info, array $pinSha256, \Closure $onProgress, &$handle)
|
34 |
-
{
|
35 |
-
$info += [
|
36 |
-
'connect_time' => 0.0,
|
37 |
-
'pretransfer_time' => 0.0,
|
38 |
-
'starttransfer_time' => 0.0,
|
39 |
-
'total_time' => 0.0,
|
40 |
-
'namelookup_time' => 0.0,
|
41 |
-
'primary_ip' => '',
|
42 |
-
'primary_port' => 0,
|
43 |
-
];
|
44 |
-
|
45 |
-
$this->info = &$info;
|
46 |
-
$this->pinSha256 = $pinSha256;
|
47 |
-
$this->onProgress = $onProgress;
|
48 |
-
$this->handle = &$handle;
|
49 |
-
}
|
50 |
-
|
51 |
-
public function startRequest(Request $request): Promise
|
52 |
-
{
|
53 |
-
$this->info['start_time'] = $this->info['start_time'] ?? microtime(true);
|
54 |
-
($this->onProgress)();
|
55 |
-
|
56 |
-
return new Success();
|
57 |
-
}
|
58 |
-
|
59 |
-
public function startDnsResolution(Request $request): Promise
|
60 |
-
{
|
61 |
-
($this->onProgress)();
|
62 |
-
|
63 |
-
return new Success();
|
64 |
-
}
|
65 |
-
|
66 |
-
public function startConnectionCreation(Request $request): Promise
|
67 |
-
{
|
68 |
-
($this->onProgress)();
|
69 |
-
|
70 |
-
return new Success();
|
71 |
-
}
|
72 |
-
|
73 |
-
public function startTlsNegotiation(Request $request): Promise
|
74 |
-
{
|
75 |
-
($this->onProgress)();
|
76 |
-
|
77 |
-
return new Success();
|
78 |
-
}
|
79 |
-
|
80 |
-
public function startSendingRequest(Request $request, Stream $stream): Promise
|
81 |
-
{
|
82 |
-
$host = $stream->getRemoteAddress()->getHost();
|
83 |
-
|
84 |
-
if (false !== strpos($host, ':')) {
|
85 |
-
$host = '['.$host.']';
|
86 |
-
}
|
87 |
-
|
88 |
-
$this->info['primary_ip'] = $host;
|
89 |
-
$this->info['primary_port'] = $stream->getRemoteAddress()->getPort();
|
90 |
-
$this->info['pretransfer_time'] = microtime(true) - $this->info['start_time'];
|
91 |
-
$this->info['debug'] .= sprintf("* Connected to %s (%s) port %d\n", $request->getUri()->getHost(), $host, $this->info['primary_port']);
|
92 |
-
|
93 |
-
if ((isset($this->info['peer_certificate_chain']) || $this->pinSha256) && null !== $tlsInfo = $stream->getTlsInfo()) {
|
94 |
-
foreach ($tlsInfo->getPeerCertificates() as $cert) {
|
95 |
-
$this->info['peer_certificate_chain'][] = openssl_x509_read($cert->toPem());
|
96 |
-
}
|
97 |
-
|
98 |
-
if ($this->pinSha256) {
|
99 |
-
$pin = openssl_pkey_get_public($this->info['peer_certificate_chain'][0]);
|
100 |
-
$pin = openssl_pkey_get_details($pin)['key'];
|
101 |
-
$pin = \array_slice(explode("\n", $pin), 1, -2);
|
102 |
-
$pin = base64_decode(implode('', $pin));
|
103 |
-
$pin = base64_encode(hash('sha256', $pin, true));
|
104 |
-
|
105 |
-
if (!\in_array($pin, $this->pinSha256, true)) {
|
106 |
-
throw new TransportException(sprintf('SSL public key does not match pinned public key for "%s".', $this->info['url']));
|
107 |
-
}
|
108 |
-
}
|
109 |
-
}
|
110 |
-
($this->onProgress)();
|
111 |
-
|
112 |
-
$uri = $request->getUri();
|
113 |
-
$requestUri = $uri->getPath() ?: '/';
|
114 |
-
|
115 |
-
if ('' !== $query = $uri->getQuery()) {
|
116 |
-
$requestUri .= '?'.$query;
|
117 |
-
}
|
118 |
-
|
119 |
-
if ('CONNECT' === $method = $request->getMethod()) {
|
120 |
-
$requestUri = $uri->getHost().': '.($uri->getPort() ?? ('https' === $uri->getScheme() ? 443 : 80));
|
121 |
-
}
|
122 |
-
|
123 |
-
$this->info['debug'] .= sprintf("> %s %s HTTP/%s \r\n", $method, $requestUri, $request->getProtocolVersions()[0]);
|
124 |
-
|
125 |
-
foreach ($request->getRawHeaders() as [$name, $value]) {
|
126 |
-
$this->info['debug'] .= $name.': '.$value."\r\n";
|
127 |
-
}
|
128 |
-
$this->info['debug'] .= "\r\n";
|
129 |
-
|
130 |
-
return new Success();
|
131 |
-
}
|
132 |
-
|
133 |
-
public function completeSendingRequest(Request $request, Stream $stream): Promise
|
134 |
-
{
|
135 |
-
($this->onProgress)();
|
136 |
-
|
137 |
-
return new Success();
|
138 |
-
}
|
139 |
-
|
140 |
-
public function startReceivingResponse(Request $request, Stream $stream): Promise
|
141 |
-
{
|
142 |
-
$this->info['starttransfer_time'] = microtime(true) - $this->info['start_time'];
|
143 |
-
($this->onProgress)();
|
144 |
-
|
145 |
-
return new Success();
|
146 |
-
}
|
147 |
-
|
148 |
-
public function completeReceivingResponse(Request $request, Stream $stream): Promise
|
149 |
-
{
|
150 |
-
$this->handle = null;
|
151 |
-
($this->onProgress)();
|
152 |
-
|
153 |
-
return new Success();
|
154 |
-
}
|
155 |
-
|
156 |
-
public function completeDnsResolution(Request $request): Promise
|
157 |
-
{
|
158 |
-
$this->info['namelookup_time'] = microtime(true) - $this->info['start_time'];
|
159 |
-
($this->onProgress)();
|
160 |
-
|
161 |
-
return new Success();
|
162 |
-
}
|
163 |
-
|
164 |
-
public function completeConnectionCreation(Request $request): Promise
|
165 |
-
{
|
166 |
-
$this->info['connect_time'] = microtime(true) - $this->info['start_time'];
|
167 |
-
($this->onProgress)();
|
168 |
-
|
169 |
-
return new Success();
|
170 |
-
}
|
171 |
-
|
172 |
-
public function completeTlsNegotiation(Request $request): Promise
|
173 |
-
{
|
174 |
-
($this->onProgress)();
|
175 |
-
|
176 |
-
return new Success();
|
177 |
-
}
|
178 |
-
|
179 |
-
public function abort(Request $request, \Throwable $cause): Promise
|
180 |
-
{
|
181 |
-
return new Success();
|
182 |
-
}
|
183 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/AmpResolver.php
DELETED
@@ -1,52 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
use Amp\Dns;
|
15 |
-
use Amp\Dns\Record;
|
16 |
-
use Amp\Promise;
|
17 |
-
use Amp\Success;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Handles local overrides for the DNS resolver.
|
21 |
-
*
|
22 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
23 |
-
*
|
24 |
-
* @internal
|
25 |
-
*/
|
26 |
-
class AmpResolver implements Dns\Resolver
|
27 |
-
{
|
28 |
-
private $dnsMap;
|
29 |
-
|
30 |
-
public function __construct(array &$dnsMap)
|
31 |
-
{
|
32 |
-
$this->dnsMap = &$dnsMap;
|
33 |
-
}
|
34 |
-
|
35 |
-
public function resolve(string $name, int $typeRestriction = null): Promise
|
36 |
-
{
|
37 |
-
if (!isset($this->dnsMap[$name]) || !\in_array($typeRestriction, [Record::A, null], true)) {
|
38 |
-
return Dns\resolver()->resolve($name, $typeRestriction);
|
39 |
-
}
|
40 |
-
|
41 |
-
return new Success([new Record($this->dnsMap[$name], Record::A, null)]);
|
42 |
-
}
|
43 |
-
|
44 |
-
public function query(string $name, int $type): Promise
|
45 |
-
{
|
46 |
-
if (!isset($this->dnsMap[$name]) || Record::A !== $type) {
|
47 |
-
return Dns\resolver()->query($name, $type);
|
48 |
-
}
|
49 |
-
|
50 |
-
return new Success([new Record($this->dnsMap[$name], Record::A, null)]);
|
51 |
-
}
|
52 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/Canary.php
DELETED
@@ -1,40 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
16 |
-
*
|
17 |
-
* @internal
|
18 |
-
*/
|
19 |
-
final class Canary
|
20 |
-
{
|
21 |
-
private $canceller;
|
22 |
-
|
23 |
-
public function __construct(\Closure $canceller)
|
24 |
-
{
|
25 |
-
$this->canceller = $canceller;
|
26 |
-
}
|
27 |
-
|
28 |
-
public function cancel()
|
29 |
-
{
|
30 |
-
if (($canceller = $this->canceller) instanceof \Closure) {
|
31 |
-
$this->canceller = null;
|
32 |
-
$canceller();
|
33 |
-
}
|
34 |
-
}
|
35 |
-
|
36 |
-
public function __destruct()
|
37 |
-
{
|
38 |
-
$this->cancel();
|
39 |
-
}
|
40 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/ClientState.php
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Internal representation of the client state.
|
16 |
-
*
|
17 |
-
* @author Alexander M. Turek <me@derrabus.de>
|
18 |
-
*
|
19 |
-
* @internal
|
20 |
-
*/
|
21 |
-
class ClientState
|
22 |
-
{
|
23 |
-
public $handlesActivity = [];
|
24 |
-
public $openHandles = [];
|
25 |
-
public $lastTimeout;
|
26 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/CurlClientState.php
DELETED
@@ -1,148 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerInterface;
|
15 |
-
use Symfony\Component\HttpClient\Response\CurlResponse;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Internal representation of the cURL client's state.
|
19 |
-
*
|
20 |
-
* @author Alexander M. Turek <me@derrabus.de>
|
21 |
-
*
|
22 |
-
* @internal
|
23 |
-
*/
|
24 |
-
final class CurlClientState extends ClientState
|
25 |
-
{
|
26 |
-
/** @var \CurlMultiHandle|resource|null */
|
27 |
-
public $handle;
|
28 |
-
/** @var \CurlShareHandle|resource|null */
|
29 |
-
public $share;
|
30 |
-
/** @var PushedResponse[] */
|
31 |
-
public $pushedResponses = [];
|
32 |
-
/** @var DnsCache */
|
33 |
-
public $dnsCache;
|
34 |
-
/** @var float[] */
|
35 |
-
public $pauseExpiries = [];
|
36 |
-
public $execCounter = \PHP_INT_MIN;
|
37 |
-
/** @var LoggerInterface|null */
|
38 |
-
public $logger;
|
39 |
-
|
40 |
-
public static $curlVersion;
|
41 |
-
|
42 |
-
public function __construct(int $maxHostConnections, int $maxPendingPushes)
|
43 |
-
{
|
44 |
-
self::$curlVersion = self::$curlVersion ?? curl_version();
|
45 |
-
|
46 |
-
$this->handle = curl_multi_init();
|
47 |
-
$this->dnsCache = new DnsCache();
|
48 |
-
$this->reset();
|
49 |
-
|
50 |
-
// Don't enable HTTP/1.1 pipelining: it forces responses to be sent in order
|
51 |
-
if (\defined('CURLPIPE_MULTIPLEX')) {
|
52 |
-
curl_multi_setopt($this->handle, \CURLMOPT_PIPELINING, \CURLPIPE_MULTIPLEX);
|
53 |
-
}
|
54 |
-
if (\defined('CURLMOPT_MAX_HOST_CONNECTIONS')) {
|
55 |
-
$maxHostConnections = curl_multi_setopt($this->handle, \CURLMOPT_MAX_HOST_CONNECTIONS, 0 < $maxHostConnections ? $maxHostConnections : \PHP_INT_MAX) ? 0 : $maxHostConnections;
|
56 |
-
}
|
57 |
-
if (\defined('CURLMOPT_MAXCONNECTS') && 0 < $maxHostConnections) {
|
58 |
-
curl_multi_setopt($this->handle, \CURLMOPT_MAXCONNECTS, $maxHostConnections);
|
59 |
-
}
|
60 |
-
|
61 |
-
// Skip configuring HTTP/2 push when it's unsupported or buggy, see https://bugs.php.net/77535
|
62 |
-
if (0 >= $maxPendingPushes || \PHP_VERSION_ID < 70217 || (\PHP_VERSION_ID >= 70300 && \PHP_VERSION_ID < 70304)) {
|
63 |
-
return;
|
64 |
-
}
|
65 |
-
|
66 |
-
// HTTP/2 push crashes before curl 7.61
|
67 |
-
if (!\defined('CURLMOPT_PUSHFUNCTION') || 0x073D00 > self::$curlVersion['version_number'] || !(\CURL_VERSION_HTTP2 & self::$curlVersion['features'])) {
|
68 |
-
return;
|
69 |
-
}
|
70 |
-
|
71 |
-
// Clone to prevent a circular reference
|
72 |
-
$multi = clone $this;
|
73 |
-
$multi->handle = null;
|
74 |
-
$multi->share = null;
|
75 |
-
$multi->pushedResponses = &$this->pushedResponses;
|
76 |
-
$multi->logger = &$this->logger;
|
77 |
-
$multi->handlesActivity = &$this->handlesActivity;
|
78 |
-
$multi->openHandles = &$this->openHandles;
|
79 |
-
|
80 |
-
curl_multi_setopt($this->handle, \CURLMOPT_PUSHFUNCTION, static function ($parent, $pushed, array $requestHeaders) use ($multi, $maxPendingPushes) {
|
81 |
-
return $multi->handlePush($parent, $pushed, $requestHeaders, $maxPendingPushes);
|
82 |
-
});
|
83 |
-
}
|
84 |
-
|
85 |
-
public function reset()
|
86 |
-
{
|
87 |
-
foreach ($this->pushedResponses as $url => $response) {
|
88 |
-
$this->logger && $this->logger->debug(sprintf('Unused pushed response: "%s"', $url));
|
89 |
-
curl_multi_remove_handle($this->handle, $response->handle);
|
90 |
-
curl_close($response->handle);
|
91 |
-
}
|
92 |
-
|
93 |
-
$this->pushedResponses = [];
|
94 |
-
$this->dnsCache->evictions = $this->dnsCache->evictions ?: $this->dnsCache->removals;
|
95 |
-
$this->dnsCache->removals = $this->dnsCache->hostnames = [];
|
96 |
-
|
97 |
-
$this->share = curl_share_init();
|
98 |
-
|
99 |
-
curl_share_setopt($this->share, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_DNS);
|
100 |
-
curl_share_setopt($this->share, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_SSL_SESSION);
|
101 |
-
|
102 |
-
if (\defined('CURL_LOCK_DATA_CONNECT')) {
|
103 |
-
curl_share_setopt($this->share, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_CONNECT);
|
104 |
-
}
|
105 |
-
}
|
106 |
-
|
107 |
-
private function handlePush($parent, $pushed, array $requestHeaders, int $maxPendingPushes): int
|
108 |
-
{
|
109 |
-
$headers = [];
|
110 |
-
$origin = curl_getinfo($parent, \CURLINFO_EFFECTIVE_URL);
|
111 |
-
|
112 |
-
foreach ($requestHeaders as $h) {
|
113 |
-
if (false !== $i = strpos($h, ':', 1)) {
|
114 |
-
$headers[substr($h, 0, $i)][] = substr($h, 1 + $i);
|
115 |
-
}
|
116 |
-
}
|
117 |
-
|
118 |
-
if (!isset($headers[':method']) || !isset($headers[':scheme']) || !isset($headers[':authority']) || !isset($headers[':path'])) {
|
119 |
-
$this->logger && $this->logger->debug(sprintf('Rejecting pushed response from "%s": pushed headers are invalid', $origin));
|
120 |
-
|
121 |
-
return \CURL_PUSH_DENY;
|
122 |
-
}
|
123 |
-
|
124 |
-
$url = $headers[':scheme'][0].'://'.$headers[':authority'][0];
|
125 |
-
|
126 |
-
// curl before 7.65 doesn't validate the pushed ":authority" header,
|
127 |
-
// but this is a MUST in the HTTP/2 RFC; let's restrict pushes to the original host,
|
128 |
-
// ignoring domains mentioned as alt-name in the certificate for now (same as curl).
|
129 |
-
if (!str_starts_with($origin, $url.'/')) {
|
130 |
-
$this->logger && $this->logger->debug(sprintf('Rejecting pushed response from "%s": server is not authoritative for "%s"', $origin, $url));
|
131 |
-
|
132 |
-
return \CURL_PUSH_DENY;
|
133 |
-
}
|
134 |
-
|
135 |
-
if ($maxPendingPushes <= \count($this->pushedResponses)) {
|
136 |
-
$fifoUrl = key($this->pushedResponses);
|
137 |
-
unset($this->pushedResponses[$fifoUrl]);
|
138 |
-
$this->logger && $this->logger->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl));
|
139 |
-
}
|
140 |
-
|
141 |
-
$url .= $headers[':path'][0];
|
142 |
-
$this->logger && $this->logger->debug(sprintf('Queueing pushed response: "%s"', $url));
|
143 |
-
|
144 |
-
$this->pushedResponses[$url] = new PushedResponse(new CurlResponse($this, $pushed), $headers, $this->openHandles[(int) $parent][1] ?? [], $pushed);
|
145 |
-
|
146 |
-
return \CURL_PUSH_OK;
|
147 |
-
}
|
148 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/DnsCache.php
DELETED
@@ -1,39 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Cache for resolved DNS queries.
|
16 |
-
*
|
17 |
-
* @author Alexander M. Turek <me@derrabus.de>
|
18 |
-
*
|
19 |
-
* @internal
|
20 |
-
*/
|
21 |
-
final class DnsCache
|
22 |
-
{
|
23 |
-
/**
|
24 |
-
* Resolved hostnames (hostname => IP address).
|
25 |
-
*
|
26 |
-
* @var string[]
|
27 |
-
*/
|
28 |
-
public $hostnames = [];
|
29 |
-
|
30 |
-
/**
|
31 |
-
* @var string[]
|
32 |
-
*/
|
33 |
-
public $removals = [];
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @var string[]
|
37 |
-
*/
|
38 |
-
public $evictions = [];
|
39 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/HttplugWaitLoop.php
DELETED
@@ -1,141 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
use Http\Client\Exception\NetworkException;
|
15 |
-
use Http\Promise\Promise;
|
16 |
-
use Psr\Http\Message\RequestInterface as Psr7RequestInterface;
|
17 |
-
use Psr\Http\Message\ResponseFactoryInterface;
|
18 |
-
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
|
19 |
-
use Psr\Http\Message\StreamFactoryInterface;
|
20 |
-
use Symfony\Component\HttpClient\Response\StreamableInterface;
|
21 |
-
use Symfony\Component\HttpClient\Response\StreamWrapper;
|
22 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
23 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
24 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
28 |
-
*
|
29 |
-
* @internal
|
30 |
-
*/
|
31 |
-
final class HttplugWaitLoop
|
32 |
-
{
|
33 |
-
private $client;
|
34 |
-
private $promisePool;
|
35 |
-
private $responseFactory;
|
36 |
-
private $streamFactory;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* @param \SplObjectStorage<ResponseInterface, array{Psr7RequestInterface, Promise}>|null $promisePool
|
40 |
-
*/
|
41 |
-
public function __construct(HttpClientInterface $client, ?\SplObjectStorage $promisePool, ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory)
|
42 |
-
{
|
43 |
-
$this->client = $client;
|
44 |
-
$this->promisePool = $promisePool;
|
45 |
-
$this->responseFactory = $responseFactory;
|
46 |
-
$this->streamFactory = $streamFactory;
|
47 |
-
}
|
48 |
-
|
49 |
-
public function wait(?ResponseInterface $pendingResponse, float $maxDuration = null, float $idleTimeout = null): int
|
50 |
-
{
|
51 |
-
if (!$this->promisePool) {
|
52 |
-
return 0;
|
53 |
-
}
|
54 |
-
|
55 |
-
$guzzleQueue = \GuzzleHttp\Promise\Utils::queue();
|
56 |
-
|
57 |
-
if (0.0 === $remainingDuration = $maxDuration) {
|
58 |
-
$idleTimeout = 0.0;
|
59 |
-
} elseif (null !== $maxDuration) {
|
60 |
-
$startTime = microtime(true);
|
61 |
-
$idleTimeout = max(0.0, min($maxDuration / 5, $idleTimeout ?? $maxDuration));
|
62 |
-
}
|
63 |
-
|
64 |
-
do {
|
65 |
-
foreach ($this->client->stream($this->promisePool, $idleTimeout) as $response => $chunk) {
|
66 |
-
try {
|
67 |
-
if (null !== $maxDuration && $chunk->isTimeout()) {
|
68 |
-
goto check_duration;
|
69 |
-
}
|
70 |
-
|
71 |
-
if ($chunk->isFirst()) {
|
72 |
-
// Deactivate throwing on 3/4/5xx
|
73 |
-
$response->getStatusCode();
|
74 |
-
}
|
75 |
-
|
76 |
-
if (!$chunk->isLast()) {
|
77 |
-
goto check_duration;
|
78 |
-
}
|
79 |
-
|
80 |
-
if ([, $promise] = $this->promisePool[$response] ?? null) {
|
81 |
-
unset($this->promisePool[$response]);
|
82 |
-
$promise->resolve($this->createPsr7Response($response, true));
|
83 |
-
}
|
84 |
-
} catch (\Exception $e) {
|
85 |
-
if ([$request, $promise] = $this->promisePool[$response] ?? null) {
|
86 |
-
unset($this->promisePool[$response]);
|
87 |
-
|
88 |
-
if ($e instanceof TransportExceptionInterface) {
|
89 |
-
$e = new NetworkException($e->getMessage(), $request, $e);
|
90 |
-
}
|
91 |
-
|
92 |
-
$promise->reject($e);
|
93 |
-
}
|
94 |
-
}
|
95 |
-
|
96 |
-
$guzzleQueue->run();
|
97 |
-
|
98 |
-
if ($pendingResponse === $response) {
|
99 |
-
return $this->promisePool->count();
|
100 |
-
}
|
101 |
-
|
102 |
-
check_duration:
|
103 |
-
if (null !== $maxDuration && $idleTimeout && $idleTimeout > $remainingDuration = max(0.0, $maxDuration - microtime(true) + $startTime)) {
|
104 |
-
$idleTimeout = $remainingDuration / 5;
|
105 |
-
break;
|
106 |
-
}
|
107 |
-
}
|
108 |
-
|
109 |
-
if (!$count = $this->promisePool->count()) {
|
110 |
-
return 0;
|
111 |
-
}
|
112 |
-
} while (null === $maxDuration || 0 < $remainingDuration);
|
113 |
-
|
114 |
-
return $count;
|
115 |
-
}
|
116 |
-
|
117 |
-
public function createPsr7Response(ResponseInterface $response, bool $buffer = false): Psr7ResponseInterface
|
118 |
-
{
|
119 |
-
$psrResponse = $this->responseFactory->createResponse($response->getStatusCode());
|
120 |
-
|
121 |
-
foreach ($response->getHeaders(false) as $name => $values) {
|
122 |
-
foreach ($values as $value) {
|
123 |
-
$psrResponse = $psrResponse->withAddedHeader($name, $value);
|
124 |
-
}
|
125 |
-
}
|
126 |
-
|
127 |
-
if ($response instanceof StreamableInterface) {
|
128 |
-
$body = $this->streamFactory->createStreamFromResource($response->toStream(false));
|
129 |
-
} elseif (!$buffer) {
|
130 |
-
$body = $this->streamFactory->createStreamFromResource(StreamWrapper::createResource($response, $this->client));
|
131 |
-
} else {
|
132 |
-
$body = $this->streamFactory->createStream($response->getContent(false));
|
133 |
-
}
|
134 |
-
|
135 |
-
if ($body->isSeekable()) {
|
136 |
-
$body->seek(0);
|
137 |
-
}
|
138 |
-
|
139 |
-
return $psrResponse->withBody($body);
|
140 |
-
}
|
141 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/NativeClientState.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Internal representation of the native client's state.
|
16 |
-
*
|
17 |
-
* @author Alexander M. Turek <me@derrabus.de>
|
18 |
-
*
|
19 |
-
* @internal
|
20 |
-
*/
|
21 |
-
final class NativeClientState extends ClientState
|
22 |
-
{
|
23 |
-
/** @var int */
|
24 |
-
public $id;
|
25 |
-
/** @var int */
|
26 |
-
public $maxHostConnections = \PHP_INT_MAX;
|
27 |
-
/** @var int */
|
28 |
-
public $responseCount = 0;
|
29 |
-
/** @var string[] */
|
30 |
-
public $dnsCache = [];
|
31 |
-
/** @var bool */
|
32 |
-
public $sleep = false;
|
33 |
-
/** @var int[] */
|
34 |
-
public $hosts = [];
|
35 |
-
|
36 |
-
public function __construct()
|
37 |
-
{
|
38 |
-
$this->id = random_int(\PHP_INT_MIN, \PHP_INT_MAX);
|
39 |
-
}
|
40 |
-
|
41 |
-
public function reset()
|
42 |
-
{
|
43 |
-
$this->responseCount = 0;
|
44 |
-
$this->dnsCache = [];
|
45 |
-
$this->hosts = [];
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Internal/PushedResponse.php
DELETED
@@ -1,41 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Internal;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Response\CurlResponse;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* A pushed response with its request headers.
|
18 |
-
*
|
19 |
-
* @author Alexander M. Turek <me@derrabus.de>
|
20 |
-
*
|
21 |
-
* @internal
|
22 |
-
*/
|
23 |
-
final class PushedResponse
|
24 |
-
{
|
25 |
-
public $response;
|
26 |
-
|
27 |
-
/** @var string[] */
|
28 |
-
public $requestHeaders;
|
29 |
-
|
30 |
-
public $parentOptions = [];
|
31 |
-
|
32 |
-
public $handle;
|
33 |
-
|
34 |
-
public function __construct(CurlResponse $response, array $requestHeaders, array $parentOptions, $handle)
|
35 |
-
{
|
36 |
-
$this->response = $response;
|
37 |
-
$this->requestHeaders = $requestHeaders;
|
38 |
-
$this->parentOptions = $parentOptions;
|
39 |
-
$this->handle = $handle;
|
40 |
-
}
|
41 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/LICENSE
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
Copyright (c) 2018-2022 Fabien Potencier
|
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 furnished
|
8 |
-
to do so, subject to the following conditions:
|
9 |
-
|
10 |
-
The above copyright notice and this permission notice shall be included in all
|
11 |
-
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/MockHttpClient.php
DELETED
@@ -1,124 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
15 |
-
use Symfony\Component\HttpClient\Response\MockResponse;
|
16 |
-
use Symfony\Component\HttpClient\Response\ResponseStream;
|
17 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
18 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
19 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
20 |
-
use Symfony\Contracts\Service\ResetInterface;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* A test-friendly HttpClient that doesn't make actual HTTP requests.
|
24 |
-
*
|
25 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
26 |
-
*/
|
27 |
-
class MockHttpClient implements HttpClientInterface, ResetInterface
|
28 |
-
{
|
29 |
-
use HttpClientTrait;
|
30 |
-
|
31 |
-
private $responseFactory;
|
32 |
-
private $requestsCount = 0;
|
33 |
-
private $defaultOptions = [];
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @param callable|callable[]|ResponseInterface|ResponseInterface[]|iterable|null $responseFactory
|
37 |
-
*/
|
38 |
-
public function __construct($responseFactory = null, ?string $baseUri = 'https://example.com')
|
39 |
-
{
|
40 |
-
$this->setResponseFactory($responseFactory);
|
41 |
-
$this->defaultOptions['base_uri'] = $baseUri;
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* @param callable|callable[]|ResponseInterface|ResponseInterface[]|iterable|null $responseFactory
|
46 |
-
*/
|
47 |
-
public function setResponseFactory($responseFactory): void
|
48 |
-
{
|
49 |
-
if ($responseFactory instanceof ResponseInterface) {
|
50 |
-
$responseFactory = [$responseFactory];
|
51 |
-
}
|
52 |
-
|
53 |
-
if (!$responseFactory instanceof \Iterator && null !== $responseFactory && !\is_callable($responseFactory)) {
|
54 |
-
$responseFactory = (static function () use ($responseFactory) {
|
55 |
-
yield from $responseFactory;
|
56 |
-
})();
|
57 |
-
}
|
58 |
-
|
59 |
-
$this->responseFactory = $responseFactory;
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* {@inheritdoc}
|
64 |
-
*/
|
65 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
66 |
-
{
|
67 |
-
[$url, $options] = $this->prepareRequest($method, $url, $options, $this->defaultOptions, true);
|
68 |
-
$url = implode('', $url);
|
69 |
-
|
70 |
-
if (null === $this->responseFactory) {
|
71 |
-
$response = new MockResponse();
|
72 |
-
} elseif (\is_callable($this->responseFactory)) {
|
73 |
-
$response = ($this->responseFactory)($method, $url, $options);
|
74 |
-
} elseif (!$this->responseFactory->valid()) {
|
75 |
-
throw new TransportException('The response factory iterator passed to MockHttpClient is empty.');
|
76 |
-
} else {
|
77 |
-
$responseFactory = $this->responseFactory->current();
|
78 |
-
$response = \is_callable($responseFactory) ? $responseFactory($method, $url, $options) : $responseFactory;
|
79 |
-
$this->responseFactory->next();
|
80 |
-
}
|
81 |
-
++$this->requestsCount;
|
82 |
-
|
83 |
-
if (!$response instanceof ResponseInterface) {
|
84 |
-
throw new TransportException(sprintf('The response factory passed to MockHttpClient must return/yield an instance of ResponseInterface, "%s" given.', \is_object($response) ? \get_class($response) : \gettype($response)));
|
85 |
-
}
|
86 |
-
|
87 |
-
return MockResponse::fromRequest($method, $url, $options, $response);
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* {@inheritdoc}
|
92 |
-
*/
|
93 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
94 |
-
{
|
95 |
-
if ($responses instanceof ResponseInterface) {
|
96 |
-
$responses = [$responses];
|
97 |
-
} elseif (!is_iterable($responses)) {
|
98 |
-
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of MockResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
|
99 |
-
}
|
100 |
-
|
101 |
-
return new ResponseStream(MockResponse::stream($responses, $timeout));
|
102 |
-
}
|
103 |
-
|
104 |
-
public function getRequestsCount(): int
|
105 |
-
{
|
106 |
-
return $this->requestsCount;
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* {@inheritdoc}
|
111 |
-
*/
|
112 |
-
public function withOptions(array $options): self
|
113 |
-
{
|
114 |
-
$clone = clone $this;
|
115 |
-
$clone->defaultOptions = self::mergeDefaultOptions($options, $this->defaultOptions, true);
|
116 |
-
|
117 |
-
return $clone;
|
118 |
-
}
|
119 |
-
|
120 |
-
public function reset()
|
121 |
-
{
|
122 |
-
$this->requestsCount = 0;
|
123 |
-
}
|
124 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/NativeHttpClient.php
DELETED
@@ -1,468 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerAwareInterface;
|
15 |
-
use Psr\Log\LoggerAwareTrait;
|
16 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
17 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
18 |
-
use Symfony\Component\HttpClient\Internal\NativeClientState;
|
19 |
-
use Symfony\Component\HttpClient\Response\NativeResponse;
|
20 |
-
use Symfony\Component\HttpClient\Response\ResponseStream;
|
21 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
22 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
23 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
24 |
-
use Symfony\Contracts\Service\ResetInterface;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* A portable implementation of the HttpClientInterface contracts based on PHP stream wrappers.
|
28 |
-
*
|
29 |
-
* PHP stream wrappers are able to fetch response bodies concurrently,
|
30 |
-
* but each request is opened synchronously.
|
31 |
-
*
|
32 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
33 |
-
*/
|
34 |
-
final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterface, ResetInterface
|
35 |
-
{
|
36 |
-
use HttpClientTrait;
|
37 |
-
use LoggerAwareTrait;
|
38 |
-
|
39 |
-
private $defaultOptions = self::OPTIONS_DEFAULTS;
|
40 |
-
private static $emptyDefaults = self::OPTIONS_DEFAULTS;
|
41 |
-
|
42 |
-
/** @var NativeClientState */
|
43 |
-
private $multi;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @param array $defaultOptions Default request's options
|
47 |
-
* @param int $maxHostConnections The maximum number of connections to open
|
48 |
-
*
|
49 |
-
* @see HttpClientInterface::OPTIONS_DEFAULTS for available options
|
50 |
-
*/
|
51 |
-
public function __construct(array $defaultOptions = [], int $maxHostConnections = 6)
|
52 |
-
{
|
53 |
-
$this->defaultOptions['buffer'] = $this->defaultOptions['buffer'] ?? \Closure::fromCallable([__CLASS__, 'shouldBuffer']);
|
54 |
-
|
55 |
-
if ($defaultOptions) {
|
56 |
-
[, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions);
|
57 |
-
}
|
58 |
-
|
59 |
-
$this->multi = new NativeClientState();
|
60 |
-
$this->multi->maxHostConnections = 0 < $maxHostConnections ? $maxHostConnections : \PHP_INT_MAX;
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* @see HttpClientInterface::OPTIONS_DEFAULTS for available options
|
65 |
-
*
|
66 |
-
* {@inheritdoc}
|
67 |
-
*/
|
68 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
69 |
-
{
|
70 |
-
[$url, $options] = self::prepareRequest($method, $url, $options, $this->defaultOptions);
|
71 |
-
|
72 |
-
if ($options['bindto']) {
|
73 |
-
if (file_exists($options['bindto'])) {
|
74 |
-
throw new TransportException(__CLASS__.' cannot bind to local Unix sockets, use e.g. CurlHttpClient instead.');
|
75 |
-
}
|
76 |
-
if (str_starts_with($options['bindto'], 'if!')) {
|
77 |
-
throw new TransportException(__CLASS__.' cannot bind to network interfaces, use e.g. CurlHttpClient instead.');
|
78 |
-
}
|
79 |
-
if (str_starts_with($options['bindto'], 'host!')) {
|
80 |
-
$options['bindto'] = substr($options['bindto'], 5);
|
81 |
-
}
|
82 |
-
}
|
83 |
-
|
84 |
-
$hasContentLength = isset($options['normalized_headers']['content-length']);
|
85 |
-
$hasBody = '' !== $options['body'] || 'POST' === $method || $hasContentLength;
|
86 |
-
|
87 |
-
$options['body'] = self::getBodyAsString($options['body']);
|
88 |
-
|
89 |
-
if ('chunked' === substr($options['normalized_headers']['transfer-encoding'][0] ?? '', \strlen('Transfer-Encoding: '))) {
|
90 |
-
unset($options['normalized_headers']['transfer-encoding']);
|
91 |
-
$options['headers'] = array_merge(...array_values($options['normalized_headers']));
|
92 |
-
$options['body'] = self::dechunk($options['body']);
|
93 |
-
}
|
94 |
-
if ('' === $options['body'] && $hasBody && !$hasContentLength) {
|
95 |
-
$options['headers'][] = 'Content-Length: 0';
|
96 |
-
}
|
97 |
-
if ($hasBody && !isset($options['normalized_headers']['content-type'])) {
|
98 |
-
$options['headers'][] = 'Content-Type: application/x-www-form-urlencoded';
|
99 |
-
}
|
100 |
-
|
101 |
-
if (\extension_loaded('zlib') && !isset($options['normalized_headers']['accept-encoding'])) {
|
102 |
-
// gzip is the most widely available algo, no need to deal with deflate
|
103 |
-
$options['headers'][] = 'Accept-Encoding: gzip';
|
104 |
-
}
|
105 |
-
|
106 |
-
if ($options['peer_fingerprint']) {
|
107 |
-
if (isset($options['peer_fingerprint']['pin-sha256']) && 1 === \count($options['peer_fingerprint'])) {
|
108 |
-
throw new TransportException(__CLASS__.' cannot verify "pin-sha256" fingerprints, please provide a "sha256" one.');
|
109 |
-
}
|
110 |
-
|
111 |
-
unset($options['peer_fingerprint']['pin-sha256']);
|
112 |
-
}
|
113 |
-
|
114 |
-
$info = [
|
115 |
-
'response_headers' => [],
|
116 |
-
'url' => $url,
|
117 |
-
'error' => null,
|
118 |
-
'canceled' => false,
|
119 |
-
'http_method' => $method,
|
120 |
-
'http_code' => 0,
|
121 |
-
'redirect_count' => 0,
|
122 |
-
'start_time' => 0.0,
|
123 |
-
'connect_time' => 0.0,
|
124 |
-
'redirect_time' => 0.0,
|
125 |
-
'pretransfer_time' => 0.0,
|
126 |
-
'starttransfer_time' => 0.0,
|
127 |
-
'total_time' => 0.0,
|
128 |
-
'namelookup_time' => 0.0,
|
129 |
-
'size_upload' => 0,
|
130 |
-
'size_download' => 0,
|
131 |
-
'size_body' => \strlen($options['body']),
|
132 |
-
'primary_ip' => '',
|
133 |
-
'primary_port' => 'http:' === $url['scheme'] ? 80 : 443,
|
134 |
-
'debug' => \extension_loaded('curl') ? '' : "* Enable the curl extension for better performance\n",
|
135 |
-
];
|
136 |
-
|
137 |
-
if ($onProgress = $options['on_progress']) {
|
138 |
-
// Memoize the last progress to ease calling the callback periodically when no network transfer happens
|
139 |
-
$lastProgress = [0, 0];
|
140 |
-
$maxDuration = 0 < $options['max_duration'] ? $options['max_duration'] : \INF;
|
141 |
-
$onProgress = static function (...$progress) use ($onProgress, &$lastProgress, &$info, $maxDuration) {
|
142 |
-
if ($info['total_time'] >= $maxDuration) {
|
143 |
-
throw new TransportException(sprintf('Max duration was reached for "%s".', implode('', $info['url'])));
|
144 |
-
}
|
145 |
-
|
146 |
-
$progressInfo = $info;
|
147 |
-
$progressInfo['url'] = implode('', $info['url']);
|
148 |
-
unset($progressInfo['size_body']);
|
149 |
-
|
150 |
-
if ($progress && -1 === $progress[0]) {
|
151 |
-
// Response completed
|
152 |
-
$lastProgress[0] = max($lastProgress);
|
153 |
-
} else {
|
154 |
-
$lastProgress = $progress ?: $lastProgress;
|
155 |
-
}
|
156 |
-
|
157 |
-
$onProgress($lastProgress[0], $lastProgress[1], $progressInfo);
|
158 |
-
};
|
159 |
-
} elseif (0 < $options['max_duration']) {
|
160 |
-
$maxDuration = $options['max_duration'];
|
161 |
-
$onProgress = static function () use (&$info, $maxDuration): void {
|
162 |
-
if ($info['total_time'] >= $maxDuration) {
|
163 |
-
throw new TransportException(sprintf('Max duration was reached for "%s".', implode('', $info['url'])));
|
164 |
-
}
|
165 |
-
};
|
166 |
-
}
|
167 |
-
|
168 |
-
// Always register a notification callback to compute live stats about the response
|
169 |
-
$notification = static function (int $code, int $severity, ?string $msg, int $msgCode, int $dlNow, int $dlSize) use ($onProgress, &$info) {
|
170 |
-
$info['total_time'] = microtime(true) - $info['start_time'];
|
171 |
-
|
172 |
-
if (\STREAM_NOTIFY_PROGRESS === $code) {
|
173 |
-
$info['starttransfer_time'] = $info['starttransfer_time'] ?: $info['total_time'];
|
174 |
-
$info['size_upload'] += $dlNow ? 0 : $info['size_body'];
|
175 |
-
$info['size_download'] = $dlNow;
|
176 |
-
} elseif (\STREAM_NOTIFY_CONNECT === $code) {
|
177 |
-
$info['connect_time'] = $info['total_time'];
|
178 |
-
$info['debug'] .= $info['request_header'];
|
179 |
-
unset($info['request_header']);
|
180 |
-
} else {
|
181 |
-
return;
|
182 |
-
}
|
183 |
-
|
184 |
-
if ($onProgress) {
|
185 |
-
$onProgress($dlNow, $dlSize);
|
186 |
-
}
|
187 |
-
};
|
188 |
-
|
189 |
-
if ($options['resolve']) {
|
190 |
-
$this->multi->dnsCache = $options['resolve'] + $this->multi->dnsCache;
|
191 |
-
}
|
192 |
-
|
193 |
-
$this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, implode('', $url)));
|
194 |
-
|
195 |
-
if (!isset($options['normalized_headers']['user-agent'])) {
|
196 |
-
$options['headers'][] = 'User-Agent: Symfony HttpClient/Native';
|
197 |
-
}
|
198 |
-
|
199 |
-
if (0 < $options['max_duration']) {
|
200 |
-
$options['timeout'] = min($options['max_duration'], $options['timeout']);
|
201 |
-
}
|
202 |
-
|
203 |
-
$bindto = $options['bindto'];
|
204 |
-
if (!$bindto && (70322 === \PHP_VERSION_ID || 70410 === \PHP_VERSION_ID)) {
|
205 |
-
$bindto = '0:0';
|
206 |
-
}
|
207 |
-
|
208 |
-
$context = [
|
209 |
-
'http' => [
|
210 |
-
'protocol_version' => min($options['http_version'] ?: '1.1', '1.1'),
|
211 |
-
'method' => $method,
|
212 |
-
'content' => $options['body'],
|
213 |
-
'ignore_errors' => true,
|
214 |
-
'curl_verify_ssl_peer' => $options['verify_peer'],
|
215 |
-
'curl_verify_ssl_host' => $options['verify_host'],
|
216 |
-
'auto_decode' => false, // Disable dechunk filter, it's incompatible with stream_select()
|
217 |
-
'timeout' => $options['timeout'],
|
218 |
-
'follow_location' => false, // We follow redirects ourselves - the native logic is too limited
|
219 |
-
],
|
220 |
-
'ssl' => array_filter([
|
221 |
-
'verify_peer' => $options['verify_peer'],
|
222 |
-
'verify_peer_name' => $options['verify_host'],
|
223 |
-
'cafile' => $options['cafile'],
|
224 |
-
'capath' => $options['capath'],
|
225 |
-
'local_cert' => $options['local_cert'],
|
226 |
-
'local_pk' => $options['local_pk'],
|
227 |
-
'passphrase' => $options['passphrase'],
|
228 |
-
'ciphers' => $options['ciphers'],
|
229 |
-
'peer_fingerprint' => $options['peer_fingerprint'],
|
230 |
-
'capture_peer_cert_chain' => $options['capture_peer_cert_chain'],
|
231 |
-
'allow_self_signed' => (bool) $options['peer_fingerprint'],
|
232 |
-
'SNI_enabled' => true,
|
233 |
-
'disable_compression' => true,
|
234 |
-
], static function ($v) { return null !== $v; }),
|
235 |
-
'socket' => [
|
236 |
-
'bindto' => $bindto,
|
237 |
-
'tcp_nodelay' => true,
|
238 |
-
],
|
239 |
-
];
|
240 |
-
|
241 |
-
$context = stream_context_create($context, ['notification' => $notification]);
|
242 |
-
|
243 |
-
$resolver = static function ($multi) use ($context, $options, $url, &$info, $onProgress) {
|
244 |
-
[$host, $port] = self::parseHostPort($url, $info);
|
245 |
-
|
246 |
-
if (!isset($options['normalized_headers']['host'])) {
|
247 |
-
$options['headers'][] = 'Host: '.$host.$port;
|
248 |
-
}
|
249 |
-
|
250 |
-
$proxy = self::getProxy($options['proxy'], $url, $options['no_proxy']);
|
251 |
-
|
252 |
-
if (!self::configureHeadersAndProxy($context, $host, $options['headers'], $proxy, 'https:' === $url['scheme'])) {
|
253 |
-
$ip = self::dnsResolve($host, $multi, $info, $onProgress);
|
254 |
-
$url['authority'] = substr_replace($url['authority'], $ip, -\strlen($host) - \strlen($port), \strlen($host));
|
255 |
-
}
|
256 |
-
|
257 |
-
return [self::createRedirectResolver($options, $host, $proxy, $info, $onProgress), implode('', $url)];
|
258 |
-
};
|
259 |
-
|
260 |
-
return new NativeResponse($this->multi, $context, implode('', $url), $options, $info, $resolver, $onProgress, $this->logger);
|
261 |
-
}
|
262 |
-
|
263 |
-
/**
|
264 |
-
* {@inheritdoc}
|
265 |
-
*/
|
266 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
267 |
-
{
|
268 |
-
if ($responses instanceof NativeResponse) {
|
269 |
-
$responses = [$responses];
|
270 |
-
} elseif (!is_iterable($responses)) {
|
271 |
-
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of NativeResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
|
272 |
-
}
|
273 |
-
|
274 |
-
return new ResponseStream(NativeResponse::stream($responses, $timeout));
|
275 |
-
}
|
276 |
-
|
277 |
-
public function reset()
|
278 |
-
{
|
279 |
-
$this->multi->reset();
|
280 |
-
}
|
281 |
-
|
282 |
-
private static function getBodyAsString($body): string
|
283 |
-
{
|
284 |
-
if (\is_resource($body)) {
|
285 |
-
return stream_get_contents($body);
|
286 |
-
}
|
287 |
-
|
288 |
-
if (!$body instanceof \Closure) {
|
289 |
-
return $body;
|
290 |
-
}
|
291 |
-
|
292 |
-
$result = '';
|
293 |
-
|
294 |
-
while ('' !== $data = $body(self::$CHUNK_SIZE)) {
|
295 |
-
if (!\is_string($data)) {
|
296 |
-
throw new TransportException(sprintf('Return value of the "body" option callback must be string, "%s" returned.', get_debug_type($data)));
|
297 |
-
}
|
298 |
-
|
299 |
-
$result .= $data;
|
300 |
-
}
|
301 |
-
|
302 |
-
return $result;
|
303 |
-
}
|
304 |
-
|
305 |
-
/**
|
306 |
-
* Extracts the host and the port from the URL.
|
307 |
-
*/
|
308 |
-
private static function parseHostPort(array $url, array &$info): array
|
309 |
-
{
|
310 |
-
if ($port = parse_url($url['authority'], \PHP_URL_PORT) ?: '') {
|
311 |
-
$info['primary_port'] = $port;
|
312 |
-
$port = ':'.$port;
|
313 |
-
} else {
|
314 |
-
$info['primary_port'] = 'http:' === $url['scheme'] ? 80 : 443;
|
315 |
-
}
|
316 |
-
|
317 |
-
return [parse_url($url['authority'], \PHP_URL_HOST), $port];
|
318 |
-
}
|
319 |
-
|
320 |
-
/**
|
321 |
-
* Resolves the IP of the host using the local DNS cache if possible.
|
322 |
-
*/
|
323 |
-
private static function dnsResolve($host, NativeClientState $multi, array &$info, ?\Closure $onProgress): string
|
324 |
-
{
|
325 |
-
if (null === $ip = $multi->dnsCache[$host] ?? null) {
|
326 |
-
$info['debug'] .= "* Hostname was NOT found in DNS cache\n";
|
327 |
-
$now = microtime(true);
|
328 |
-
|
329 |
-
if (!$ip = gethostbynamel($host)) {
|
330 |
-
throw new TransportException(sprintf('Could not resolve host "%s".', $host));
|
331 |
-
}
|
332 |
-
|
333 |
-
$info['namelookup_time'] = microtime(true) - ($info['start_time'] ?: $now);
|
334 |
-
$multi->dnsCache[$host] = $ip = $ip[0];
|
335 |
-
$info['debug'] .= "* Added {$host}:0:{$ip} to DNS cache\n";
|
336 |
-
} else {
|
337 |
-
$info['debug'] .= "* Hostname was found in DNS cache\n";
|
338 |
-
}
|
339 |
-
|
340 |
-
$info['primary_ip'] = $ip;
|
341 |
-
|
342 |
-
if ($onProgress) {
|
343 |
-
// Notify DNS resolution
|
344 |
-
$onProgress();
|
345 |
-
}
|
346 |
-
|
347 |
-
return $ip;
|
348 |
-
}
|
349 |
-
|
350 |
-
/**
|
351 |
-
* Handles redirects - the native logic is too buggy to be used.
|
352 |
-
*/
|
353 |
-
private static function createRedirectResolver(array $options, string $host, ?array $proxy, array &$info, ?\Closure $onProgress): \Closure
|
354 |
-
{
|
355 |
-
$redirectHeaders = [];
|
356 |
-
if (0 < $maxRedirects = $options['max_redirects']) {
|
357 |
-
$redirectHeaders = ['host' => $host];
|
358 |
-
$redirectHeaders['with_auth'] = $redirectHeaders['no_auth'] = array_filter($options['headers'], static function ($h) {
|
359 |
-
return 0 !== stripos($h, 'Host:');
|
360 |
-
});
|
361 |
-
|
362 |
-
if (isset($options['normalized_headers']['authorization']) || isset($options['normalized_headers']['cookie'])) {
|
363 |
-
$redirectHeaders['no_auth'] = array_filter($redirectHeaders['no_auth'], static function ($h) {
|
364 |
-
return 0 !== stripos($h, 'Authorization:') && 0 !== stripos($h, 'Cookie:');
|
365 |
-
});
|
366 |
-
}
|
367 |
-
}
|
368 |
-
|
369 |
-
return static function (NativeClientState $multi, ?string $location, $context) use (&$redirectHeaders, $proxy, &$info, $maxRedirects, $onProgress): ?string {
|
370 |
-
if (null === $location || $info['http_code'] < 300 || 400 <= $info['http_code']) {
|
371 |
-
$info['redirect_url'] = null;
|
372 |
-
|
373 |
-
return null;
|
374 |
-
}
|
375 |
-
|
376 |
-
try {
|
377 |
-
$url = self::parseUrl($location);
|
378 |
-
} catch (InvalidArgumentException $e) {
|
379 |
-
$info['redirect_url'] = null;
|
380 |
-
|
381 |
-
return null;
|
382 |
-
}
|
383 |
-
|
384 |
-
$url = self::resolveUrl($url, $info['url']);
|
385 |
-
$info['redirect_url'] = implode('', $url);
|
386 |
-
|
387 |
-
if ($info['redirect_count'] >= $maxRedirects) {
|
388 |
-
return null;
|
389 |
-
}
|
390 |
-
|
391 |
-
$info['url'] = $url;
|
392 |
-
++$info['redirect_count'];
|
393 |
-
$info['redirect_time'] = microtime(true) - $info['start_time'];
|
394 |
-
|
395 |
-
// Do like curl and browsers: turn POST to GET on 301, 302 and 303
|
396 |
-
if (\in_array($info['http_code'], [301, 302, 303], true)) {
|
397 |
-
$options = stream_context_get_options($context)['http'];
|
398 |
-
|
399 |
-
if ('POST' === $options['method'] || 303 === $info['http_code']) {
|
400 |
-
$info['http_method'] = $options['method'] = 'HEAD' === $options['method'] ? 'HEAD' : 'GET';
|
401 |
-
$options['content'] = '';
|
402 |
-
$filterContentHeaders = static function ($h) {
|
403 |
-
return 0 !== stripos($h, 'Content-Length:') && 0 !== stripos($h, 'Content-Type:') && 0 !== stripos($h, 'Transfer-Encoding:');
|
404 |
-
};
|
405 |
-
$options['header'] = array_filter($options['header'], $filterContentHeaders);
|
406 |
-
$redirectHeaders['no_auth'] = array_filter($redirectHeaders['no_auth'], $filterContentHeaders);
|
407 |
-
$redirectHeaders['with_auth'] = array_filter($redirectHeaders['with_auth'], $filterContentHeaders);
|
408 |
-
|
409 |
-
stream_context_set_option($context, ['http' => $options]);
|
410 |
-
}
|
411 |
-
}
|
412 |
-
|
413 |
-
[$host, $port] = self::parseHostPort($url, $info);
|
414 |
-
|
415 |
-
if (false !== (parse_url($location, \PHP_URL_HOST) ?? false)) {
|
416 |
-
// Authorization and Cookie headers MUST NOT follow except for the initial host name
|
417 |
-
$requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth'];
|
418 |
-
$requestHeaders[] = 'Host: '.$host.$port;
|
419 |
-
$dnsResolve = !self::configureHeadersAndProxy($context, $host, $requestHeaders, $proxy, 'https:' === $url['scheme']);
|
420 |
-
} else {
|
421 |
-
$dnsResolve = isset(stream_context_get_options($context)['ssl']['peer_name']);
|
422 |
-
}
|
423 |
-
|
424 |
-
if ($dnsResolve) {
|
425 |
-
$ip = self::dnsResolve($host, $multi, $info, $onProgress);
|
426 |
-
$url['authority'] = substr_replace($url['authority'], $ip, -\strlen($host) - \strlen($port), \strlen($host));
|
427 |
-
}
|
428 |
-
|
429 |
-
return implode('', $url);
|
430 |
-
};
|
431 |
-
}
|
432 |
-
|
433 |
-
private static function configureHeadersAndProxy($context, string $host, array $requestHeaders, ?array $proxy, bool $isSsl): bool
|
434 |
-
{
|
435 |
-
if (null === $proxy) {
|
436 |
-
stream_context_set_option($context, 'http', 'header', $requestHeaders);
|
437 |
-
stream_context_set_option($context, 'ssl', 'peer_name', $host);
|
438 |
-
|
439 |
-
return false;
|
440 |
-
}
|
441 |
-
|
442 |
-
// Matching "no_proxy" should follow the behavior of curl
|
443 |
-
|
444 |
-
foreach ($proxy['no_proxy'] as $rule) {
|
445 |
-
$dotRule = '.'.ltrim($rule, '.');
|
446 |
-
|
447 |
-
if ('*' === $rule || $host === $rule || str_ends_with($host, $dotRule)) {
|
448 |
-
stream_context_set_option($context, 'http', 'proxy', null);
|
449 |
-
stream_context_set_option($context, 'http', 'request_fulluri', false);
|
450 |
-
stream_context_set_option($context, 'http', 'header', $requestHeaders);
|
451 |
-
stream_context_set_option($context, 'ssl', 'peer_name', $host);
|
452 |
-
|
453 |
-
return false;
|
454 |
-
}
|
455 |
-
}
|
456 |
-
|
457 |
-
if (null !== $proxy['auth']) {
|
458 |
-
$requestHeaders[] = 'Proxy-Authorization: '.$proxy['auth'];
|
459 |
-
}
|
460 |
-
|
461 |
-
stream_context_set_option($context, 'http', 'proxy', $proxy['url']);
|
462 |
-
stream_context_set_option($context, 'http', 'request_fulluri', !$isSsl);
|
463 |
-
stream_context_set_option($context, 'http', 'header', $requestHeaders);
|
464 |
-
stream_context_set_option($context, 'ssl', 'peer_name', null);
|
465 |
-
|
466 |
-
return true;
|
467 |
-
}
|
468 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php
DELETED
@@ -1,132 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerAwareInterface;
|
15 |
-
use Psr\Log\LoggerInterface;
|
16 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
17 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
18 |
-
use Symfony\Component\HttpFoundation\IpUtils;
|
19 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
20 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
21 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
22 |
-
use Symfony\Contracts\Service\ResetInterface;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Decorator that blocks requests to private networks by default.
|
26 |
-
*
|
27 |
-
* @author Hallison Boaventura <hallisonboaventura@gmail.com>
|
28 |
-
*/
|
29 |
-
final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwareInterface, ResetInterface
|
30 |
-
{
|
31 |
-
use HttpClientTrait;
|
32 |
-
|
33 |
-
private const PRIVATE_SUBNETS = [
|
34 |
-
'127.0.0.0/8',
|
35 |
-
'10.0.0.0/8',
|
36 |
-
'192.168.0.0/16',
|
37 |
-
'172.16.0.0/12',
|
38 |
-
'169.254.0.0/16',
|
39 |
-
'0.0.0.0/8',
|
40 |
-
'240.0.0.0/4',
|
41 |
-
'::1/128',
|
42 |
-
'fc00::/7',
|
43 |
-
'fe80::/10',
|
44 |
-
'::ffff:0:0/96',
|
45 |
-
'::/128',
|
46 |
-
];
|
47 |
-
|
48 |
-
private $client;
|
49 |
-
private $subnets;
|
50 |
-
|
51 |
-
/**
|
52 |
-
* @param string|array|null $subnets String or array of subnets using CIDR notation that will be used by IpUtils.
|
53 |
-
* If null is passed, the standard private subnets will be used.
|
54 |
-
*/
|
55 |
-
public function __construct(HttpClientInterface $client, $subnets = null)
|
56 |
-
{
|
57 |
-
if (!(\is_array($subnets) || \is_string($subnets) || null === $subnets)) {
|
58 |
-
throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be of the type array, string or null. "%s" given.', __METHOD__, get_debug_type($subnets)));
|
59 |
-
}
|
60 |
-
|
61 |
-
if (!class_exists(IpUtils::class)) {
|
62 |
-
throw new \LogicException(sprintf('You cannot use "%s" if the HttpFoundation component is not installed. Try running "composer require symfony/http-foundation".', __CLASS__));
|
63 |
-
}
|
64 |
-
|
65 |
-
$this->client = $client;
|
66 |
-
$this->subnets = $subnets;
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* {@inheritdoc}
|
71 |
-
*/
|
72 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
73 |
-
{
|
74 |
-
$onProgress = $options['on_progress'] ?? null;
|
75 |
-
if (null !== $onProgress && !\is_callable($onProgress)) {
|
76 |
-
throw new InvalidArgumentException(sprintf('Option "on_progress" must be callable, "%s" given.', get_debug_type($onProgress)));
|
77 |
-
}
|
78 |
-
|
79 |
-
$subnets = $this->subnets;
|
80 |
-
$lastPrimaryIp = '';
|
81 |
-
|
82 |
-
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, &$lastPrimaryIp): void {
|
83 |
-
if ($info['primary_ip'] !== $lastPrimaryIp) {
|
84 |
-
if ($info['primary_ip'] && IpUtils::checkIp($info['primary_ip'], $subnets ?? self::PRIVATE_SUBNETS)) {
|
85 |
-
throw new TransportException(sprintf('IP "%s" is blocked for "%s".', $info['primary_ip'], $info['url']));
|
86 |
-
}
|
87 |
-
|
88 |
-
$lastPrimaryIp = $info['primary_ip'];
|
89 |
-
}
|
90 |
-
|
91 |
-
null !== $onProgress && $onProgress($dlNow, $dlSize, $info);
|
92 |
-
};
|
93 |
-
|
94 |
-
return $this->client->request($method, $url, $options);
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* {@inheritdoc}
|
99 |
-
*/
|
100 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
101 |
-
{
|
102 |
-
return $this->client->stream($responses, $timeout);
|
103 |
-
}
|
104 |
-
|
105 |
-
/**
|
106 |
-
* {@inheritdoc}
|
107 |
-
*/
|
108 |
-
public function setLogger(LoggerInterface $logger): void
|
109 |
-
{
|
110 |
-
if ($this->client instanceof LoggerAwareInterface) {
|
111 |
-
$this->client->setLogger($logger);
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* {@inheritdoc}
|
117 |
-
*/
|
118 |
-
public function withOptions(array $options): self
|
119 |
-
{
|
120 |
-
$clone = clone $this;
|
121 |
-
$clone->client = $this->client->withOptions($options);
|
122 |
-
|
123 |
-
return $clone;
|
124 |
-
}
|
125 |
-
|
126 |
-
public function reset()
|
127 |
-
{
|
128 |
-
if ($this->client instanceof ResetInterface) {
|
129 |
-
$this->client->reset();
|
130 |
-
}
|
131 |
-
}
|
132 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Psr18Client.php
DELETED
@@ -1,239 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Http\Discovery\Exception\NotFoundException;
|
15 |
-
use Http\Discovery\Psr17FactoryDiscovery;
|
16 |
-
use Nyholm\Psr7\Factory\Psr17Factory;
|
17 |
-
use Nyholm\Psr7\Request;
|
18 |
-
use Nyholm\Psr7\Uri;
|
19 |
-
use Psr\Http\Client\ClientInterface;
|
20 |
-
use Psr\Http\Client\NetworkExceptionInterface;
|
21 |
-
use Psr\Http\Client\RequestExceptionInterface;
|
22 |
-
use Psr\Http\Message\RequestFactoryInterface;
|
23 |
-
use Psr\Http\Message\RequestInterface;
|
24 |
-
use Psr\Http\Message\ResponseFactoryInterface;
|
25 |
-
use Psr\Http\Message\ResponseInterface;
|
26 |
-
use Psr\Http\Message\StreamFactoryInterface;
|
27 |
-
use Psr\Http\Message\StreamInterface;
|
28 |
-
use Psr\Http\Message\UriFactoryInterface;
|
29 |
-
use Psr\Http\Message\UriInterface;
|
30 |
-
use Symfony\Component\HttpClient\Response\StreamableInterface;
|
31 |
-
use Symfony\Component\HttpClient\Response\StreamWrapper;
|
32 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
33 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
34 |
-
use Symfony\Contracts\Service\ResetInterface;
|
35 |
-
|
36 |
-
if (!interface_exists(RequestFactoryInterface::class)) {
|
37 |
-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-factory" package is not installed. Try running "composer require nyholm/psr7".');
|
38 |
-
}
|
39 |
-
|
40 |
-
if (!interface_exists(ClientInterface::class)) {
|
41 |
-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-client" package is not installed. Try running "composer require psr/http-client".');
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* An adapter to turn a Symfony HttpClientInterface into a PSR-18 ClientInterface.
|
46 |
-
*
|
47 |
-
* Run "composer require psr/http-client" to install the base ClientInterface. Run
|
48 |
-
* "composer require nyholm/psr7" to install an efficient implementation of response
|
49 |
-
* and stream factories with flex-provided autowiring aliases.
|
50 |
-
*
|
51 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
52 |
-
*/
|
53 |
-
final class Psr18Client implements ClientInterface, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, ResetInterface
|
54 |
-
{
|
55 |
-
private $client;
|
56 |
-
private $responseFactory;
|
57 |
-
private $streamFactory;
|
58 |
-
|
59 |
-
public function __construct(HttpClientInterface $client = null, ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null)
|
60 |
-
{
|
61 |
-
$this->client = $client ?? HttpClient::create();
|
62 |
-
$this->responseFactory = $responseFactory;
|
63 |
-
$this->streamFactory = $streamFactory ?? ($responseFactory instanceof StreamFactoryInterface ? $responseFactory : null);
|
64 |
-
|
65 |
-
if (null !== $this->responseFactory && null !== $this->streamFactory) {
|
66 |
-
return;
|
67 |
-
}
|
68 |
-
|
69 |
-
if (!class_exists(Psr17Factory::class) && !class_exists(Psr17FactoryDiscovery::class)) {
|
70 |
-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
|
71 |
-
}
|
72 |
-
|
73 |
-
try {
|
74 |
-
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
|
75 |
-
$this->responseFactory = $this->responseFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
|
76 |
-
$this->streamFactory = $this->streamFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
|
77 |
-
} catch (NotFoundException $e) {
|
78 |
-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been found. Try running "composer require nyholm/psr7".', 0, $e);
|
79 |
-
}
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* {@inheritdoc}
|
84 |
-
*/
|
85 |
-
public function sendRequest(RequestInterface $request): ResponseInterface
|
86 |
-
{
|
87 |
-
try {
|
88 |
-
$body = $request->getBody();
|
89 |
-
|
90 |
-
if ($body->isSeekable()) {
|
91 |
-
$body->seek(0);
|
92 |
-
}
|
93 |
-
|
94 |
-
$response = $this->client->request($request->getMethod(), (string) $request->getUri(), [
|
95 |
-
'headers' => $request->getHeaders(),
|
96 |
-
'body' => $body->getContents(),
|
97 |
-
'http_version' => '1.0' === $request->getProtocolVersion() ? '1.0' : null,
|
98 |
-
]);
|
99 |
-
|
100 |
-
$psrResponse = $this->responseFactory->createResponse($response->getStatusCode());
|
101 |
-
|
102 |
-
foreach ($response->getHeaders(false) as $name => $values) {
|
103 |
-
foreach ($values as $value) {
|
104 |
-
$psrResponse = $psrResponse->withAddedHeader($name, $value);
|
105 |
-
}
|
106 |
-
}
|
107 |
-
|
108 |
-
$body = $response instanceof StreamableInterface ? $response->toStream(false) : StreamWrapper::createResource($response, $this->client);
|
109 |
-
$body = $this->streamFactory->createStreamFromResource($body);
|
110 |
-
|
111 |
-
if ($body->isSeekable()) {
|
112 |
-
$body->seek(0);
|
113 |
-
}
|
114 |
-
|
115 |
-
return $psrResponse->withBody($body);
|
116 |
-
} catch (TransportExceptionInterface $e) {
|
117 |
-
if ($e instanceof \InvalidArgumentException) {
|
118 |
-
throw new Psr18RequestException($e, $request);
|
119 |
-
}
|
120 |
-
|
121 |
-
throw new Psr18NetworkException($e, $request);
|
122 |
-
}
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* {@inheritdoc}
|
127 |
-
*/
|
128 |
-
public function createRequest(string $method, $uri): RequestInterface
|
129 |
-
{
|
130 |
-
if ($this->responseFactory instanceof RequestFactoryInterface) {
|
131 |
-
return $this->responseFactory->createRequest($method, $uri);
|
132 |
-
}
|
133 |
-
|
134 |
-
if (class_exists(Request::class)) {
|
135 |
-
return new Request($method, $uri);
|
136 |
-
}
|
137 |
-
|
138 |
-
if (class_exists(Psr17FactoryDiscovery::class)) {
|
139 |
-
return Psr17FactoryDiscovery::findRequestFactory()->createRequest($method, $uri);
|
140 |
-
}
|
141 |
-
|
142 |
-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
|
143 |
-
}
|
144 |
-
|
145 |
-
/**
|
146 |
-
* {@inheritdoc}
|
147 |
-
*/
|
148 |
-
public function createStream(string $content = ''): StreamInterface
|
149 |
-
{
|
150 |
-
$stream = $this->streamFactory->createStream($content);
|
151 |
-
|
152 |
-
if ($stream->isSeekable()) {
|
153 |
-
$stream->seek(0);
|
154 |
-
}
|
155 |
-
|
156 |
-
return $stream;
|
157 |
-
}
|
158 |
-
|
159 |
-
/**
|
160 |
-
* {@inheritdoc}
|
161 |
-
*/
|
162 |
-
public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface
|
163 |
-
{
|
164 |
-
return $this->streamFactory->createStreamFromFile($filename, $mode);
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* {@inheritdoc}
|
169 |
-
*/
|
170 |
-
public function createStreamFromResource($resource): StreamInterface
|
171 |
-
{
|
172 |
-
return $this->streamFactory->createStreamFromResource($resource);
|
173 |
-
}
|
174 |
-
|
175 |
-
/**
|
176 |
-
* {@inheritdoc}
|
177 |
-
*/
|
178 |
-
public function createUri(string $uri = ''): UriInterface
|
179 |
-
{
|
180 |
-
if ($this->responseFactory instanceof UriFactoryInterface) {
|
181 |
-
return $this->responseFactory->createUri($uri);
|
182 |
-
}
|
183 |
-
|
184 |
-
if (class_exists(Uri::class)) {
|
185 |
-
return new Uri($uri);
|
186 |
-
}
|
187 |
-
|
188 |
-
if (class_exists(Psr17FactoryDiscovery::class)) {
|
189 |
-
return Psr17FactoryDiscovery::findUrlFactory()->createUri($uri);
|
190 |
-
}
|
191 |
-
|
192 |
-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
|
193 |
-
}
|
194 |
-
|
195 |
-
public function reset()
|
196 |
-
{
|
197 |
-
if ($this->client instanceof ResetInterface) {
|
198 |
-
$this->client->reset();
|
199 |
-
}
|
200 |
-
}
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* @internal
|
205 |
-
*/
|
206 |
-
class Psr18NetworkException extends \RuntimeException implements NetworkExceptionInterface
|
207 |
-
{
|
208 |
-
private $request;
|
209 |
-
|
210 |
-
public function __construct(TransportExceptionInterface $e, RequestInterface $request)
|
211 |
-
{
|
212 |
-
parent::__construct($e->getMessage(), 0, $e);
|
213 |
-
$this->request = $request;
|
214 |
-
}
|
215 |
-
|
216 |
-
public function getRequest(): RequestInterface
|
217 |
-
{
|
218 |
-
return $this->request;
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* @internal
|
224 |
-
*/
|
225 |
-
class Psr18RequestException extends \InvalidArgumentException implements RequestExceptionInterface
|
226 |
-
{
|
227 |
-
private $request;
|
228 |
-
|
229 |
-
public function __construct(TransportExceptionInterface $e, RequestInterface $request)
|
230 |
-
{
|
231 |
-
parent::__construct($e->getMessage(), 0, $e);
|
232 |
-
$this->request = $request;
|
233 |
-
}
|
234 |
-
|
235 |
-
public function getRequest(): RequestInterface
|
236 |
-
{
|
237 |
-
return $this->request;
|
238 |
-
}
|
239 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/README.md
DELETED
@@ -1,27 +0,0 @@
|
|
1 |
-
HttpClient component
|
2 |
-
====================
|
3 |
-
|
4 |
-
The HttpClient component provides powerful methods to fetch HTTP resources synchronously or asynchronously.
|
5 |
-
|
6 |
-
Sponsor
|
7 |
-
-------
|
8 |
-
|
9 |
-
The Httpclient component for Symfony 5.4/6.0 is [backed][1] by [Klaxoon][2].
|
10 |
-
|
11 |
-
Klaxoon is a platform that empowers organizations to run effective and
|
12 |
-
productive workshops easily in a hybrid environment. Anytime, Anywhere.
|
13 |
-
|
14 |
-
Help Symfony by [sponsoring][3] its development!
|
15 |
-
|
16 |
-
Resources
|
17 |
-
---------
|
18 |
-
|
19 |
-
* [Documentation](https://symfony.com/doc/current/components/http_client.html)
|
20 |
-
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
21 |
-
* [Report issues](https://github.com/symfony/symfony/issues) and
|
22 |
-
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
23 |
-
in the [main Symfony repository](https://github.com/symfony/symfony)
|
24 |
-
|
25 |
-
[1]: https://symfony.com/backers
|
26 |
-
[2]: https://klaxoon.com
|
27 |
-
[3]: https://symfony.com/sponsor
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/AmpResponse.php
DELETED
@@ -1,461 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Amp\ByteStream\StreamException;
|
15 |
-
use Amp\CancellationTokenSource;
|
16 |
-
use Amp\Coroutine;
|
17 |
-
use Amp\Deferred;
|
18 |
-
use Amp\Http\Client\HttpException;
|
19 |
-
use Amp\Http\Client\Request;
|
20 |
-
use Amp\Http\Client\Response;
|
21 |
-
use Amp\Loop;
|
22 |
-
use Amp\Promise;
|
23 |
-
use Amp\Success;
|
24 |
-
use Psr\Log\LoggerInterface;
|
25 |
-
use Symfony\Component\HttpClient\Chunk\FirstChunk;
|
26 |
-
use Symfony\Component\HttpClient\Chunk\InformationalChunk;
|
27 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
28 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
29 |
-
use Symfony\Component\HttpClient\HttpClientTrait;
|
30 |
-
use Symfony\Component\HttpClient\Internal\AmpBody;
|
31 |
-
use Symfony\Component\HttpClient\Internal\AmpClientState;
|
32 |
-
use Symfony\Component\HttpClient\Internal\Canary;
|
33 |
-
use Symfony\Component\HttpClient\Internal\ClientState;
|
34 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
38 |
-
*
|
39 |
-
* @internal
|
40 |
-
*/
|
41 |
-
final class AmpResponse implements ResponseInterface, StreamableInterface
|
42 |
-
{
|
43 |
-
use CommonResponseTrait;
|
44 |
-
use TransportResponseTrait;
|
45 |
-
|
46 |
-
private static $nextId = 'a';
|
47 |
-
|
48 |
-
private $multi;
|
49 |
-
private $options;
|
50 |
-
private $canceller;
|
51 |
-
private $onProgress;
|
52 |
-
|
53 |
-
private static $delay;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* @internal
|
57 |
-
*/
|
58 |
-
public function __construct(AmpClientState $multi, Request $request, array $options, ?LoggerInterface $logger)
|
59 |
-
{
|
60 |
-
$this->multi = $multi;
|
61 |
-
$this->options = &$options;
|
62 |
-
$this->logger = $logger;
|
63 |
-
$this->timeout = $options['timeout'];
|
64 |
-
$this->shouldBuffer = $options['buffer'];
|
65 |
-
|
66 |
-
if ($this->inflate = \extension_loaded('zlib') && !$request->hasHeader('accept-encoding')) {
|
67 |
-
$request->setHeader('Accept-Encoding', 'gzip');
|
68 |
-
}
|
69 |
-
|
70 |
-
$this->initializer = static function (self $response) {
|
71 |
-
return null !== $response->options;
|
72 |
-
};
|
73 |
-
|
74 |
-
$info = &$this->info;
|
75 |
-
$headers = &$this->headers;
|
76 |
-
$canceller = $this->canceller = new CancellationTokenSource();
|
77 |
-
$handle = &$this->handle;
|
78 |
-
|
79 |
-
$info['url'] = (string) $request->getUri();
|
80 |
-
$info['http_method'] = $request->getMethod();
|
81 |
-
$info['start_time'] = null;
|
82 |
-
$info['redirect_url'] = null;
|
83 |
-
$info['redirect_time'] = 0.0;
|
84 |
-
$info['redirect_count'] = 0;
|
85 |
-
$info['size_upload'] = 0.0;
|
86 |
-
$info['size_download'] = 0.0;
|
87 |
-
$info['upload_content_length'] = -1.0;
|
88 |
-
$info['download_content_length'] = -1.0;
|
89 |
-
$info['user_data'] = $options['user_data'];
|
90 |
-
$info['max_duration'] = $options['max_duration'];
|
91 |
-
$info['debug'] = '';
|
92 |
-
|
93 |
-
$onProgress = $options['on_progress'] ?? static function () {};
|
94 |
-
$onProgress = $this->onProgress = static function () use (&$info, $onProgress) {
|
95 |
-
$info['total_time'] = microtime(true) - $info['start_time'];
|
96 |
-
$onProgress((int) $info['size_download'], ((int) (1 + $info['download_content_length']) ?: 1) - 1, (array) $info);
|
97 |
-
};
|
98 |
-
|
99 |
-
$pauseDeferred = new Deferred();
|
100 |
-
$pause = new Success();
|
101 |
-
|
102 |
-
$throttleWatcher = null;
|
103 |
-
|
104 |
-
$this->id = $id = self::$nextId++;
|
105 |
-
Loop::defer(static function () use ($request, $multi, &$id, &$info, &$headers, $canceller, &$options, $onProgress, &$handle, $logger, &$pause) {
|
106 |
-
return new Coroutine(self::generateResponse($request, $multi, $id, $info, $headers, $canceller, $options, $onProgress, $handle, $logger, $pause));
|
107 |
-
});
|
108 |
-
|
109 |
-
$info['pause_handler'] = static function (float $duration) use (&$throttleWatcher, &$pauseDeferred, &$pause) {
|
110 |
-
if (null !== $throttleWatcher) {
|
111 |
-
Loop::cancel($throttleWatcher);
|
112 |
-
}
|
113 |
-
|
114 |
-
$pause = $pauseDeferred->promise();
|
115 |
-
|
116 |
-
if ($duration <= 0) {
|
117 |
-
$deferred = $pauseDeferred;
|
118 |
-
$pauseDeferred = new Deferred();
|
119 |
-
$deferred->resolve();
|
120 |
-
} else {
|
121 |
-
$throttleWatcher = Loop::delay(ceil(1000 * $duration), static function () use (&$pauseDeferred) {
|
122 |
-
$deferred = $pauseDeferred;
|
123 |
-
$pauseDeferred = new Deferred();
|
124 |
-
$deferred->resolve();
|
125 |
-
});
|
126 |
-
}
|
127 |
-
};
|
128 |
-
|
129 |
-
$multi->lastTimeout = null;
|
130 |
-
$multi->openHandles[$id] = $id;
|
131 |
-
++$multi->responseCount;
|
132 |
-
|
133 |
-
$this->canary = new Canary(static function () use ($canceller, $multi, $id) {
|
134 |
-
$canceller->cancel();
|
135 |
-
unset($multi->openHandles[$id], $multi->handlesActivity[$id]);
|
136 |
-
});
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* {@inheritdoc}
|
141 |
-
*/
|
142 |
-
public function getInfo(string $type = null)
|
143 |
-
{
|
144 |
-
return null !== $type ? $this->info[$type] ?? null : $this->info;
|
145 |
-
}
|
146 |
-
|
147 |
-
public function __sleep(): array
|
148 |
-
{
|
149 |
-
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
150 |
-
}
|
151 |
-
|
152 |
-
public function __wakeup()
|
153 |
-
{
|
154 |
-
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
155 |
-
}
|
156 |
-
|
157 |
-
public function __destruct()
|
158 |
-
{
|
159 |
-
try {
|
160 |
-
$this->doDestruct();
|
161 |
-
} finally {
|
162 |
-
// Clear the DNS cache when all requests completed
|
163 |
-
if (0 >= --$this->multi->responseCount) {
|
164 |
-
$this->multi->responseCount = 0;
|
165 |
-
$this->multi->dnsCache = [];
|
166 |
-
}
|
167 |
-
}
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* {@inheritdoc}
|
172 |
-
*/
|
173 |
-
private static function schedule(self $response, array &$runningResponses): void
|
174 |
-
{
|
175 |
-
if (isset($runningResponses[0])) {
|
176 |
-
$runningResponses[0][1][$response->id] = $response;
|
177 |
-
} else {
|
178 |
-
$runningResponses[0] = [$response->multi, [$response->id => $response]];
|
179 |
-
}
|
180 |
-
|
181 |
-
if (!isset($response->multi->openHandles[$response->id])) {
|
182 |
-
$response->multi->handlesActivity[$response->id][] = null;
|
183 |
-
$response->multi->handlesActivity[$response->id][] = null !== $response->info['error'] ? new TransportException($response->info['error']) : null;
|
184 |
-
}
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* {@inheritdoc}
|
189 |
-
*
|
190 |
-
* @param AmpClientState $multi
|
191 |
-
*/
|
192 |
-
private static function perform(ClientState $multi, array &$responses = null): void
|
193 |
-
{
|
194 |
-
if ($responses) {
|
195 |
-
foreach ($responses as $response) {
|
196 |
-
try {
|
197 |
-
if ($response->info['start_time']) {
|
198 |
-
$response->info['total_time'] = microtime(true) - $response->info['start_time'];
|
199 |
-
($response->onProgress)();
|
200 |
-
}
|
201 |
-
} catch (\Throwable $e) {
|
202 |
-
$multi->handlesActivity[$response->id][] = null;
|
203 |
-
$multi->handlesActivity[$response->id][] = $e;
|
204 |
-
}
|
205 |
-
}
|
206 |
-
}
|
207 |
-
}
|
208 |
-
|
209 |
-
/**
|
210 |
-
* {@inheritdoc}
|
211 |
-
*
|
212 |
-
* @param AmpClientState $multi
|
213 |
-
*/
|
214 |
-
private static function select(ClientState $multi, float $timeout): int
|
215 |
-
{
|
216 |
-
$timeout += microtime(true);
|
217 |
-
self::$delay = Loop::defer(static function () use ($timeout) {
|
218 |
-
if (0 < $timeout -= microtime(true)) {
|
219 |
-
self::$delay = Loop::delay(ceil(1000 * $timeout), [Loop::class, 'stop']);
|
220 |
-
} else {
|
221 |
-
Loop::stop();
|
222 |
-
}
|
223 |
-
});
|
224 |
-
|
225 |
-
Loop::run();
|
226 |
-
|
227 |
-
return null === self::$delay ? 1 : 0;
|
228 |
-
}
|
229 |
-
|
230 |
-
private static function generateResponse(Request $request, AmpClientState $multi, string $id, array &$info, array &$headers, CancellationTokenSource $canceller, array &$options, \Closure $onProgress, &$handle, ?LoggerInterface $logger, Promise &$pause)
|
231 |
-
{
|
232 |
-
$request->setInformationalResponseHandler(static function (Response $response) use ($multi, $id, &$info, &$headers) {
|
233 |
-
self::addResponseHeaders($response, $info, $headers);
|
234 |
-
$multi->handlesActivity[$id][] = new InformationalChunk($response->getStatus(), $response->getHeaders());
|
235 |
-
self::stopLoop();
|
236 |
-
});
|
237 |
-
|
238 |
-
try {
|
239 |
-
/* @var Response $response */
|
240 |
-
if (null === $response = yield from self::getPushedResponse($request, $multi, $info, $headers, $options, $logger)) {
|
241 |
-
$logger && $logger->info(sprintf('Request: "%s %s"', $info['http_method'], $info['url']));
|
242 |
-
|
243 |
-
$response = yield from self::followRedirects($request, $multi, $info, $headers, $canceller, $options, $onProgress, $handle, $logger, $pause);
|
244 |
-
}
|
245 |
-
|
246 |
-
$options = null;
|
247 |
-
|
248 |
-
$multi->handlesActivity[$id][] = new FirstChunk();
|
249 |
-
|
250 |
-
if ('HEAD' === $response->getRequest()->getMethod() || \in_array($info['http_code'], [204, 304], true)) {
|
251 |
-
$multi->handlesActivity[$id][] = null;
|
252 |
-
$multi->handlesActivity[$id][] = null;
|
253 |
-
self::stopLoop();
|
254 |
-
|
255 |
-
return;
|
256 |
-
}
|
257 |
-
|
258 |
-
if ($response->hasHeader('content-length')) {
|
259 |
-
$info['download_content_length'] = (float) $response->getHeader('content-length');
|
260 |
-
}
|
261 |
-
|
262 |
-
$body = $response->getBody();
|
263 |
-
|
264 |
-
while (true) {
|
265 |
-
self::stopLoop();
|
266 |
-
|
267 |
-
yield $pause;
|
268 |
-
|
269 |
-
if (null === $data = yield $body->read()) {
|
270 |
-
break;
|
271 |
-
}
|
272 |
-
|
273 |
-
$info['size_download'] += \strlen($data);
|
274 |
-
$multi->handlesActivity[$id][] = $data;
|
275 |
-
}
|
276 |
-
|
277 |
-
$multi->handlesActivity[$id][] = null;
|
278 |
-
$multi->handlesActivity[$id][] = null;
|
279 |
-
} catch (\Throwable $e) {
|
280 |
-
$multi->handlesActivity[$id][] = null;
|
281 |
-
$multi->handlesActivity[$id][] = $e;
|
282 |
-
} finally {
|
283 |
-
$info['download_content_length'] = $info['size_download'];
|
284 |
-
}
|
285 |
-
|
286 |
-
self::stopLoop();
|
287 |
-
}
|
288 |
-
|
289 |
-
private static function followRedirects(Request $originRequest, AmpClientState $multi, array &$info, array &$headers, CancellationTokenSource $canceller, array $options, \Closure $onProgress, &$handle, ?LoggerInterface $logger, Promise &$pause)
|
290 |
-
{
|
291 |
-
yield $pause;
|
292 |
-
|
293 |
-
$originRequest->setBody(new AmpBody($options['body'], $info, $onProgress));
|
294 |
-
$response = yield $multi->request($options, $originRequest, $canceller->getToken(), $info, $onProgress, $handle);
|
295 |
-
$previousUrl = null;
|
296 |
-
|
297 |
-
while (true) {
|
298 |
-
self::addResponseHeaders($response, $info, $headers);
|
299 |
-
$status = $response->getStatus();
|
300 |
-
|
301 |
-
if (!\in_array($status, [301, 302, 303, 307, 308], true) || null === $location = $response->getHeader('location')) {
|
302 |
-
return $response;
|
303 |
-
}
|
304 |
-
|
305 |
-
$urlResolver = new class() {
|
306 |
-
use HttpClientTrait {
|
307 |
-
parseUrl as public;
|
308 |
-
resolveUrl as public;
|
309 |
-
}
|
310 |
-
};
|
311 |
-
|
312 |
-
try {
|
313 |
-
$previousUrl = $previousUrl ?? $urlResolver::parseUrl($info['url']);
|
314 |
-
$location = $urlResolver::parseUrl($location);
|
315 |
-
$location = $urlResolver::resolveUrl($location, $previousUrl);
|
316 |
-
$info['redirect_url'] = implode('', $location);
|
317 |
-
} catch (InvalidArgumentException $e) {
|
318 |
-
return $response;
|
319 |
-
}
|
320 |
-
|
321 |
-
if (0 >= $options['max_redirects'] || $info['redirect_count'] >= $options['max_redirects']) {
|
322 |
-
return $response;
|
323 |
-
}
|
324 |
-
|
325 |
-
$logger && $logger->info(sprintf('Redirecting: "%s %s"', $status, $info['url']));
|
326 |
-
|
327 |
-
try {
|
328 |
-
// Discard body of redirects
|
329 |
-
while (null !== yield $response->getBody()->read()) {
|
330 |
-
}
|
331 |
-
} catch (HttpException|StreamException $e) {
|
332 |
-
// Ignore streaming errors on previous responses
|
333 |
-
}
|
334 |
-
|
335 |
-
++$info['redirect_count'];
|
336 |
-
$info['url'] = $info['redirect_url'];
|
337 |
-
$info['redirect_url'] = null;
|
338 |
-
$previousUrl = $location;
|
339 |
-
|
340 |
-
$request = new Request($info['url'], $info['http_method']);
|
341 |
-
$request->setProtocolVersions($originRequest->getProtocolVersions());
|
342 |
-
$request->setTcpConnectTimeout($originRequest->getTcpConnectTimeout());
|
343 |
-
$request->setTlsHandshakeTimeout($originRequest->getTlsHandshakeTimeout());
|
344 |
-
$request->setTransferTimeout($originRequest->getTransferTimeout());
|
345 |
-
|
346 |
-
if (\in_array($status, [301, 302, 303], true)) {
|
347 |
-
$originRequest->removeHeader('transfer-encoding');
|
348 |
-
$originRequest->removeHeader('content-length');
|
349 |
-
$originRequest->removeHeader('content-type');
|
350 |
-
|
351 |
-
// Do like curl and browsers: turn POST to GET on 301, 302 and 303
|
352 |
-
if ('POST' === $response->getRequest()->getMethod() || 303 === $status) {
|
353 |
-
$info['http_method'] = 'HEAD' === $response->getRequest()->getMethod() ? 'HEAD' : 'GET';
|
354 |
-
$request->setMethod($info['http_method']);
|
355 |
-
}
|
356 |
-
} else {
|
357 |
-
$request->setBody(AmpBody::rewind($response->getRequest()->getBody()));
|
358 |
-
}
|
359 |
-
|
360 |
-
foreach ($originRequest->getRawHeaders() as [$name, $value]) {
|
361 |
-
$request->setHeader($name, $value);
|
362 |
-
}
|
363 |
-
|
364 |
-
if ($request->getUri()->getAuthority() !== $originRequest->getUri()->getAuthority()) {
|
365 |
-
$request->removeHeader('authorization');
|
366 |
-
$request->removeHeader('cookie');
|
367 |
-
$request->removeHeader('host');
|
368 |
-
}
|
369 |
-
|
370 |
-
yield $pause;
|
371 |
-
|
372 |
-
$response = yield $multi->request($options, $request, $canceller->getToken(), $info, $onProgress, $handle);
|
373 |
-
$info['redirect_time'] = microtime(true) - $info['start_time'];
|
374 |
-
}
|
375 |
-
}
|
376 |
-
|
377 |
-
private static function addResponseHeaders(Response $response, array &$info, array &$headers): void
|
378 |
-
{
|
379 |
-
$info['http_code'] = $response->getStatus();
|
380 |
-
|
381 |
-
if ($headers) {
|
382 |
-
$info['debug'] .= "< \r\n";
|
383 |
-
$headers = [];
|
384 |
-
}
|
385 |
-
|
386 |
-
$h = sprintf('HTTP/%s %s %s', $response->getProtocolVersion(), $response->getStatus(), $response->getReason());
|
387 |
-
$info['debug'] .= "< {$h}\r\n";
|
388 |
-
$info['response_headers'][] = $h;
|
389 |
-
|
390 |
-
foreach ($response->getRawHeaders() as [$name, $value]) {
|
391 |
-
$headers[strtolower($name)][] = $value;
|
392 |
-
$h = $name.': '.$value;
|
393 |
-
$info['debug'] .= "< {$h}\r\n";
|
394 |
-
$info['response_headers'][] = $h;
|
395 |
-
}
|
396 |
-
|
397 |
-
$info['debug'] .= "< \r\n";
|
398 |
-
}
|
399 |
-
|
400 |
-
/**
|
401 |
-
* Accepts pushed responses only if their headers related to authentication match the request.
|
402 |
-
*/
|
403 |
-
private static function getPushedResponse(Request $request, AmpClientState $multi, array &$info, array &$headers, array $options, ?LoggerInterface $logger)
|
404 |
-
{
|
405 |
-
if ('' !== $options['body']) {
|
406 |
-
return null;
|
407 |
-
}
|
408 |
-
|
409 |
-
$authority = $request->getUri()->getAuthority();
|
410 |
-
|
411 |
-
foreach ($multi->pushedResponses[$authority] ?? [] as $i => [$pushedUrl, $pushDeferred, $pushedRequest, $pushedResponse, $parentOptions]) {
|
412 |
-
if ($info['url'] !== $pushedUrl || $info['http_method'] !== $pushedRequest->getMethod()) {
|
413 |
-
continue;
|
414 |
-
}
|
415 |
-
|
416 |
-
foreach ($parentOptions as $k => $v) {
|
417 |
-
if ($options[$k] !== $v) {
|
418 |
-
continue 2;
|
419 |
-
}
|
420 |
-
}
|
421 |
-
|
422 |
-
foreach (['authorization', 'cookie', 'range', 'proxy-authorization'] as $k) {
|
423 |
-
if ($pushedRequest->getHeaderArray($k) !== $request->getHeaderArray($k)) {
|
424 |
-
continue 2;
|
425 |
-
}
|
426 |
-
}
|
427 |
-
|
428 |
-
$response = yield $pushedResponse;
|
429 |
-
|
430 |
-
foreach ($response->getHeaderArray('vary') as $vary) {
|
431 |
-
foreach (preg_split('/\s*+,\s*+/', $vary) as $v) {
|
432 |
-
if ('*' === $v || ($pushedRequest->getHeaderArray($v) !== $request->getHeaderArray($v) && 'accept-encoding' !== strtolower($v))) {
|
433 |
-
$logger && $logger->debug(sprintf('Skipping pushed response: "%s"', $info['url']));
|
434 |
-
continue 3;
|
435 |
-
}
|
436 |
-
}
|
437 |
-
}
|
438 |
-
|
439 |
-
$pushDeferred->resolve();
|
440 |
-
$logger && $logger->debug(sprintf('Accepting pushed response: "%s %s"', $info['http_method'], $info['url']));
|
441 |
-
self::addResponseHeaders($response, $info, $headers);
|
442 |
-
unset($multi->pushedResponses[$authority][$i]);
|
443 |
-
|
444 |
-
if (!$multi->pushedResponses[$authority]) {
|
445 |
-
unset($multi->pushedResponses[$authority]);
|
446 |
-
}
|
447 |
-
|
448 |
-
return $response;
|
449 |
-
}
|
450 |
-
}
|
451 |
-
|
452 |
-
private static function stopLoop(): void
|
453 |
-
{
|
454 |
-
if (null !== self::$delay) {
|
455 |
-
Loop::cancel(self::$delay);
|
456 |
-
self::$delay = null;
|
457 |
-
}
|
458 |
-
|
459 |
-
Loop::defer([Loop::class, 'stop']);
|
460 |
-
}
|
461 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/AsyncContext.php
DELETED
@@ -1,189 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Chunk\DataChunk;
|
15 |
-
use Symfony\Component\HttpClient\Chunk\LastChunk;
|
16 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
17 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
18 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
19 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* A DTO to work with AsyncResponse.
|
23 |
-
*
|
24 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
25 |
-
*/
|
26 |
-
final class AsyncContext
|
27 |
-
{
|
28 |
-
private $passthru;
|
29 |
-
private $client;
|
30 |
-
private $response;
|
31 |
-
private $info = [];
|
32 |
-
private $content;
|
33 |
-
private $offset;
|
34 |
-
|
35 |
-
public function __construct(&$passthru, HttpClientInterface $client, ResponseInterface &$response, array &$info, $content, int $offset)
|
36 |
-
{
|
37 |
-
$this->passthru = &$passthru;
|
38 |
-
$this->client = $client;
|
39 |
-
$this->response = &$response;
|
40 |
-
$this->info = &$info;
|
41 |
-
$this->content = $content;
|
42 |
-
$this->offset = $offset;
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Returns the HTTP status without consuming the response.
|
47 |
-
*/
|
48 |
-
public function getStatusCode(): int
|
49 |
-
{
|
50 |
-
return $this->response->getInfo('http_code');
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Returns the headers without consuming the response.
|
55 |
-
*/
|
56 |
-
public function getHeaders(): array
|
57 |
-
{
|
58 |
-
$headers = [];
|
59 |
-
|
60 |
-
foreach ($this->response->getInfo('response_headers') as $h) {
|
61 |
-
if (11 <= \strlen($h) && '/' === $h[4] && preg_match('#^HTTP/\d+(?:\.\d+)? ([123456789]\d\d)(?: |$)#', $h, $m)) {
|
62 |
-
$headers = [];
|
63 |
-
} elseif (2 === \count($m = explode(':', $h, 2))) {
|
64 |
-
$headers[strtolower($m[0])][] = ltrim($m[1]);
|
65 |
-
}
|
66 |
-
}
|
67 |
-
|
68 |
-
return $headers;
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* @return resource|null The PHP stream resource where the content is buffered, if it is
|
73 |
-
*/
|
74 |
-
public function getContent()
|
75 |
-
{
|
76 |
-
return $this->content;
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Creates a new chunk of content.
|
81 |
-
*/
|
82 |
-
public function createChunk(string $data): ChunkInterface
|
83 |
-
{
|
84 |
-
return new DataChunk($this->offset, $data);
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* Pauses the request for the given number of seconds.
|
89 |
-
*/
|
90 |
-
public function pause(float $duration): void
|
91 |
-
{
|
92 |
-
if (\is_callable($pause = $this->response->getInfo('pause_handler'))) {
|
93 |
-
$pause($duration);
|
94 |
-
} elseif (0 < $duration) {
|
95 |
-
usleep(1E6 * $duration);
|
96 |
-
}
|
97 |
-
}
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Cancels the request and returns the last chunk to yield.
|
101 |
-
*/
|
102 |
-
public function cancel(): ChunkInterface
|
103 |
-
{
|
104 |
-
$this->info['canceled'] = true;
|
105 |
-
$this->info['error'] = 'Response has been canceled.';
|
106 |
-
$this->response->cancel();
|
107 |
-
|
108 |
-
return new LastChunk();
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* Returns the current info of the response.
|
113 |
-
*/
|
114 |
-
public function getInfo(string $type = null)
|
115 |
-
{
|
116 |
-
if (null !== $type) {
|
117 |
-
return $this->info[$type] ?? $this->response->getInfo($type);
|
118 |
-
}
|
119 |
-
|
120 |
-
return $this->info + $this->response->getInfo();
|
121 |
-
}
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Attaches an info to the response.
|
125 |
-
*
|
126 |
-
* @return $this
|
127 |
-
*/
|
128 |
-
public function setInfo(string $type, $value): self
|
129 |
-
{
|
130 |
-
if ('canceled' === $type && $value !== $this->info['canceled']) {
|
131 |
-
throw new \LogicException('You cannot set the "canceled" info directly.');
|
132 |
-
}
|
133 |
-
|
134 |
-
if (null === $value) {
|
135 |
-
unset($this->info[$type]);
|
136 |
-
} else {
|
137 |
-
$this->info[$type] = $value;
|
138 |
-
}
|
139 |
-
|
140 |
-
return $this;
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* Returns the currently processed response.
|
145 |
-
*/
|
146 |
-
public function getResponse(): ResponseInterface
|
147 |
-
{
|
148 |
-
return $this->response;
|
149 |
-
}
|
150 |
-
|
151 |
-
/**
|
152 |
-
* Replaces the currently processed response by doing a new request.
|
153 |
-
*/
|
154 |
-
public function replaceRequest(string $method, string $url, array $options = []): ResponseInterface
|
155 |
-
{
|
156 |
-
$this->info['previous_info'][] = $info = $this->response->getInfo();
|
157 |
-
if (null !== $onProgress = $options['on_progress'] ?? null) {
|
158 |
-
$thisInfo = &$this->info;
|
159 |
-
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) {
|
160 |
-
$onProgress($dlNow, $dlSize, $thisInfo + $info);
|
161 |
-
};
|
162 |
-
}
|
163 |
-
if (0 < ($info['max_duration'] ?? 0) && 0 < ($info['total_time'] ?? 0)) {
|
164 |
-
if (0 >= $options['max_duration'] = $info['max_duration'] - $info['total_time']) {
|
165 |
-
throw new TransportException(sprintf('Max duration was reached for "%s".', $info['url']));
|
166 |
-
}
|
167 |
-
}
|
168 |
-
|
169 |
-
return $this->response = $this->client->request($method, $url, ['buffer' => false] + $options);
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* Replaces the currently processed response by another one.
|
174 |
-
*/
|
175 |
-
public function replaceResponse(ResponseInterface $response): ResponseInterface
|
176 |
-
{
|
177 |
-
$this->info['previous_info'][] = $this->response->getInfo();
|
178 |
-
|
179 |
-
return $this->response = $response;
|
180 |
-
}
|
181 |
-
|
182 |
-
/**
|
183 |
-
* Replaces or removes the chunk filter iterator.
|
184 |
-
*/
|
185 |
-
public function passthru(callable $passthru = null): void
|
186 |
-
{
|
187 |
-
$this->passthru = $passthru;
|
188 |
-
}
|
189 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/AsyncResponse.php
DELETED
@@ -1,478 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Chunk\ErrorChunk;
|
15 |
-
use Symfony\Component\HttpClient\Chunk\FirstChunk;
|
16 |
-
use Symfony\Component\HttpClient\Chunk\LastChunk;
|
17 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
18 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
19 |
-
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
|
20 |
-
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
|
21 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
22 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
23 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Provides a single extension point to process a response's content stream.
|
27 |
-
*
|
28 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
29 |
-
*/
|
30 |
-
final class AsyncResponse implements ResponseInterface, StreamableInterface
|
31 |
-
{
|
32 |
-
use CommonResponseTrait;
|
33 |
-
|
34 |
-
private const FIRST_CHUNK_YIELDED = 1;
|
35 |
-
private const LAST_CHUNK_YIELDED = 2;
|
36 |
-
|
37 |
-
private $client;
|
38 |
-
private $response;
|
39 |
-
private $info = ['canceled' => false];
|
40 |
-
private $passthru;
|
41 |
-
private $stream;
|
42 |
-
private $yieldedState;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* @param ?callable(ChunkInterface, AsyncContext): ?\Iterator $passthru
|
46 |
-
*/
|
47 |
-
public function __construct(HttpClientInterface $client, string $method, string $url, array $options, callable $passthru = null)
|
48 |
-
{
|
49 |
-
$this->client = $client;
|
50 |
-
$this->shouldBuffer = $options['buffer'] ?? true;
|
51 |
-
|
52 |
-
if (null !== $onProgress = $options['on_progress'] ?? null) {
|
53 |
-
$thisInfo = &$this->info;
|
54 |
-
$options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) {
|
55 |
-
$onProgress($dlNow, $dlSize, $thisInfo + $info);
|
56 |
-
};
|
57 |
-
}
|
58 |
-
$this->response = $client->request($method, $url, ['buffer' => false] + $options);
|
59 |
-
$this->passthru = $passthru;
|
60 |
-
$this->initializer = static function (self $response, float $timeout = null) {
|
61 |
-
if (null === $response->shouldBuffer) {
|
62 |
-
return false;
|
63 |
-
}
|
64 |
-
|
65 |
-
while (true) {
|
66 |
-
foreach (self::stream([$response], $timeout) as $chunk) {
|
67 |
-
if ($chunk->isTimeout() && $response->passthru) {
|
68 |
-
foreach (self::passthru($response->client, $response, new ErrorChunk($response->offset, new TransportException($chunk->getError()))) as $chunk) {
|
69 |
-
if ($chunk->isFirst()) {
|
70 |
-
return false;
|
71 |
-
}
|
72 |
-
}
|
73 |
-
|
74 |
-
continue 2;
|
75 |
-
}
|
76 |
-
|
77 |
-
if ($chunk->isFirst()) {
|
78 |
-
return false;
|
79 |
-
}
|
80 |
-
}
|
81 |
-
|
82 |
-
return false;
|
83 |
-
}
|
84 |
-
};
|
85 |
-
if (\array_key_exists('user_data', $options)) {
|
86 |
-
$this->info['user_data'] = $options['user_data'];
|
87 |
-
}
|
88 |
-
if (\array_key_exists('max_duration', $options)) {
|
89 |
-
$this->info['max_duration'] = $options['max_duration'];
|
90 |
-
}
|
91 |
-
}
|
92 |
-
|
93 |
-
public function getStatusCode(): int
|
94 |
-
{
|
95 |
-
if ($this->initializer) {
|
96 |
-
self::initialize($this);
|
97 |
-
}
|
98 |
-
|
99 |
-
return $this->response->getStatusCode();
|
100 |
-
}
|
101 |
-
|
102 |
-
public function getHeaders(bool $throw = true): array
|
103 |
-
{
|
104 |
-
if ($this->initializer) {
|
105 |
-
self::initialize($this);
|
106 |
-
}
|
107 |
-
|
108 |
-
$headers = $this->response->getHeaders(false);
|
109 |
-
|
110 |
-
if ($throw) {
|
111 |
-
$this->checkStatusCode();
|
112 |
-
}
|
113 |
-
|
114 |
-
return $headers;
|
115 |
-
}
|
116 |
-
|
117 |
-
public function getInfo(string $type = null)
|
118 |
-
{
|
119 |
-
if (null !== $type) {
|
120 |
-
return $this->info[$type] ?? $this->response->getInfo($type);
|
121 |
-
}
|
122 |
-
|
123 |
-
return $this->info + $this->response->getInfo();
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* {@inheritdoc}
|
128 |
-
*/
|
129 |
-
public function toStream(bool $throw = true)
|
130 |
-
{
|
131 |
-
if ($throw) {
|
132 |
-
// Ensure headers arrived
|
133 |
-
$this->getHeaders(true);
|
134 |
-
}
|
135 |
-
|
136 |
-
$handle = function () {
|
137 |
-
$stream = $this->response instanceof StreamableInterface ? $this->response->toStream(false) : StreamWrapper::createResource($this->response);
|
138 |
-
|
139 |
-
return stream_get_meta_data($stream)['wrapper_data']->stream_cast(\STREAM_CAST_FOR_SELECT);
|
140 |
-
};
|
141 |
-
|
142 |
-
$stream = StreamWrapper::createResource($this);
|
143 |
-
stream_get_meta_data($stream)['wrapper_data']
|
144 |
-
->bindHandles($handle, $this->content);
|
145 |
-
|
146 |
-
return $stream;
|
147 |
-
}
|
148 |
-
|
149 |
-
/**
|
150 |
-
* {@inheritdoc}
|
151 |
-
*/
|
152 |
-
public function cancel(): void
|
153 |
-
{
|
154 |
-
if ($this->info['canceled']) {
|
155 |
-
return;
|
156 |
-
}
|
157 |
-
|
158 |
-
$this->info['canceled'] = true;
|
159 |
-
$this->info['error'] = 'Response has been canceled.';
|
160 |
-
$this->close();
|
161 |
-
$client = $this->client;
|
162 |
-
$this->client = null;
|
163 |
-
|
164 |
-
if (!$this->passthru) {
|
165 |
-
return;
|
166 |
-
}
|
167 |
-
|
168 |
-
try {
|
169 |
-
foreach (self::passthru($client, $this, new LastChunk()) as $chunk) {
|
170 |
-
// no-op
|
171 |
-
}
|
172 |
-
|
173 |
-
$this->passthru = null;
|
174 |
-
} catch (ExceptionInterface $e) {
|
175 |
-
// ignore any errors when canceling
|
176 |
-
}
|
177 |
-
}
|
178 |
-
|
179 |
-
public function __destruct()
|
180 |
-
{
|
181 |
-
$httpException = null;
|
182 |
-
|
183 |
-
if ($this->initializer && null === $this->getInfo('error')) {
|
184 |
-
try {
|
185 |
-
self::initialize($this, -0.0);
|
186 |
-
$this->getHeaders(true);
|
187 |
-
} catch (HttpExceptionInterface $httpException) {
|
188 |
-
// no-op
|
189 |
-
}
|
190 |
-
}
|
191 |
-
|
192 |
-
if ($this->passthru && null === $this->getInfo('error')) {
|
193 |
-
$this->info['canceled'] = true;
|
194 |
-
|
195 |
-
try {
|
196 |
-
foreach (self::passthru($this->client, $this, new LastChunk()) as $chunk) {
|
197 |
-
// no-op
|
198 |
-
}
|
199 |
-
} catch (ExceptionInterface $e) {
|
200 |
-
// ignore any errors when destructing
|
201 |
-
}
|
202 |
-
}
|
203 |
-
|
204 |
-
if (null !== $httpException) {
|
205 |
-
throw $httpException;
|
206 |
-
}
|
207 |
-
}
|
208 |
-
|
209 |
-
/**
|
210 |
-
* @internal
|
211 |
-
*/
|
212 |
-
public static function stream(iterable $responses, float $timeout = null, string $class = null): \Generator
|
213 |
-
{
|
214 |
-
while ($responses) {
|
215 |
-
$wrappedResponses = [];
|
216 |
-
$asyncMap = new \SplObjectStorage();
|
217 |
-
$client = null;
|
218 |
-
|
219 |
-
foreach ($responses as $r) {
|
220 |
-
if (!$r instanceof self) {
|
221 |
-
throw new \TypeError(sprintf('"%s::stream()" expects parameter 1 to be an iterable of AsyncResponse objects, "%s" given.', $class ?? static::class, get_debug_type($r)));
|
222 |
-
}
|
223 |
-
|
224 |
-
if (null !== $e = $r->info['error'] ?? null) {
|
225 |
-
yield $r => $chunk = new ErrorChunk($r->offset, new TransportException($e));
|
226 |
-
$chunk->didThrow() ?: $chunk->getContent();
|
227 |
-
continue;
|
228 |
-
}
|
229 |
-
|
230 |
-
if (null === $client) {
|
231 |
-
$client = $r->client;
|
232 |
-
} elseif ($r->client !== $client) {
|
233 |
-
throw new TransportException('Cannot stream AsyncResponse objects with many clients.');
|
234 |
-
}
|
235 |
-
|
236 |
-
$asyncMap[$r->response] = $r;
|
237 |
-
$wrappedResponses[] = $r->response;
|
238 |
-
|
239 |
-
if ($r->stream) {
|
240 |
-
yield from self::passthruStream($response = $r->response, $r, new FirstChunk(), $asyncMap);
|
241 |
-
|
242 |
-
if (!isset($asyncMap[$response])) {
|
243 |
-
array_pop($wrappedResponses);
|
244 |
-
}
|
245 |
-
|
246 |
-
if ($r->response !== $response && !isset($asyncMap[$r->response])) {
|
247 |
-
$asyncMap[$r->response] = $r;
|
248 |
-
$wrappedResponses[] = $r->response;
|
249 |
-
}
|
250 |
-
}
|
251 |
-
}
|
252 |
-
|
253 |
-
if (!$client || !$wrappedResponses) {
|
254 |
-
return;
|
255 |
-
}
|
256 |
-
|
257 |
-
foreach ($client->stream($wrappedResponses, $timeout) as $response => $chunk) {
|
258 |
-
$r = $asyncMap[$response];
|
259 |
-
|
260 |
-
if (null === $chunk->getError()) {
|
261 |
-
if ($chunk->isFirst()) {
|
262 |
-
// Ensure no exception is thrown on destruct for the wrapped response
|
263 |
-
$r->response->getStatusCode();
|
264 |
-
} elseif (0 === $r->offset && null === $r->content && $chunk->isLast()) {
|
265 |
-
$r->content = fopen('php://memory', 'w+');
|
266 |
-
}
|
267 |
-
}
|
268 |
-
|
269 |
-
if (!$r->passthru) {
|
270 |
-
if (null !== $chunk->getError() || $chunk->isLast()) {
|
271 |
-
unset($asyncMap[$response]);
|
272 |
-
} elseif (null !== $r->content && '' !== ($content = $chunk->getContent()) && \strlen($content) !== fwrite($r->content, $content)) {
|
273 |
-
$chunk = new ErrorChunk($r->offset, new TransportException(sprintf('Failed writing %d bytes to the response buffer.', \strlen($content))));
|
274 |
-
$r->info['error'] = $chunk->getError();
|
275 |
-
$r->response->cancel();
|
276 |
-
}
|
277 |
-
|
278 |
-
yield $r => $chunk;
|
279 |
-
continue;
|
280 |
-
}
|
281 |
-
|
282 |
-
if (null !== $chunk->getError()) {
|
283 |
-
// no-op
|
284 |
-
} elseif ($chunk->isFirst()) {
|
285 |
-
$r->yieldedState = self::FIRST_CHUNK_YIELDED;
|
286 |
-
} elseif (self::FIRST_CHUNK_YIELDED !== $r->yieldedState && null === $chunk->getInformationalStatus()) {
|
287 |
-
throw new \LogicException(sprintf('Instance of "%s" is already consumed and cannot be managed by "%s". A decorated client should not call any of the response\'s methods in its "request()" method.', get_debug_type($response), $class ?? static::class));
|
288 |
-
}
|
289 |
-
|
290 |
-
foreach (self::passthru($r->client, $r, $chunk, $asyncMap) as $chunk) {
|
291 |
-
yield $r => $chunk;
|
292 |
-
}
|
293 |
-
|
294 |
-
if ($r->response !== $response && isset($asyncMap[$response])) {
|
295 |
-
break;
|
296 |
-
}
|
297 |
-
}
|
298 |
-
|
299 |
-
if (null === $chunk->getError() && $chunk->isLast()) {
|
300 |
-
$r->yieldedState = self::LAST_CHUNK_YIELDED;
|
301 |
-
}
|
302 |
-
if (null === $chunk->getError() && self::LAST_CHUNK_YIELDED !== $r->yieldedState && $r->response === $response && null !== $r->client) {
|
303 |
-
throw new \LogicException('A chunk passthru must yield an "isLast()" chunk before ending a stream.');
|
304 |
-
}
|
305 |
-
|
306 |
-
$responses = [];
|
307 |
-
foreach ($asyncMap as $response) {
|
308 |
-
$r = $asyncMap[$response];
|
309 |
-
|
310 |
-
if (null !== $r->client) {
|
311 |
-
$responses[] = $asyncMap[$response];
|
312 |
-
}
|
313 |
-
}
|
314 |
-
}
|
315 |
-
}
|
316 |
-
|
317 |
-
/**
|
318 |
-
* @param \SplObjectStorage<ResponseInterface, AsyncResponse>|null $asyncMap
|
319 |
-
*/
|
320 |
-
private static function passthru(HttpClientInterface $client, self $r, ChunkInterface $chunk, \SplObjectStorage $asyncMap = null): \Generator
|
321 |
-
{
|
322 |
-
$r->stream = null;
|
323 |
-
$response = $r->response;
|
324 |
-
$context = new AsyncContext($r->passthru, $client, $r->response, $r->info, $r->content, $r->offset);
|
325 |
-
if (null === $stream = ($r->passthru)($chunk, $context)) {
|
326 |
-
if ($r->response === $response && (null !== $chunk->getError() || $chunk->isLast())) {
|
327 |
-
throw new \LogicException('A chunk passthru cannot swallow the last chunk.');
|
328 |
-
}
|
329 |
-
|
330 |
-
return;
|
331 |
-
}
|
332 |
-
|
333 |
-
if (!$stream instanceof \Iterator) {
|
334 |
-
throw new \LogicException(sprintf('A chunk passthru must return an "Iterator", "%s" returned.', get_debug_type($stream)));
|
335 |
-
}
|
336 |
-
$r->stream = $stream;
|
337 |
-
|
338 |
-
yield from self::passthruStream($response, $r, null, $asyncMap);
|
339 |
-
}
|
340 |
-
|
341 |
-
/**
|
342 |
-
* @param \SplObjectStorage<ResponseInterface, AsyncResponse>|null $asyncMap
|
343 |
-
*/
|
344 |
-
private static function passthruStream(ResponseInterface $response, self $r, ?ChunkInterface $chunk, ?\SplObjectStorage $asyncMap): \Generator
|
345 |
-
{
|
346 |
-
while (true) {
|
347 |
-
try {
|
348 |
-
if (null !== $chunk && $r->stream) {
|
349 |
-
$r->stream->next();
|
350 |
-
}
|
351 |
-
|
352 |
-
if (!$r->stream || !$r->stream->valid() || !$r->stream) {
|
353 |
-
$r->stream = null;
|
354 |
-
break;
|
355 |
-
}
|
356 |
-
} catch (\Throwable $e) {
|
357 |
-
unset($asyncMap[$response]);
|
358 |
-
$r->stream = null;
|
359 |
-
$r->info['error'] = $e->getMessage();
|
360 |
-
$r->response->cancel();
|
361 |
-
|
362 |
-
yield $r => $chunk = new ErrorChunk($r->offset, $e);
|
363 |
-
$chunk->didThrow() ?: $chunk->getContent();
|
364 |
-
break;
|
365 |
-
}
|
366 |
-
|
367 |
-
$chunk = $r->stream->current();
|
368 |
-
|
369 |
-
if (!$chunk instanceof ChunkInterface) {
|
370 |
-
throw new \LogicException(sprintf('A chunk passthru must yield instances of "%s", "%s" yielded.', ChunkInterface::class, get_debug_type($chunk)));
|
371 |
-
}
|
372 |
-
|
373 |
-
if (null !== $chunk->getError()) {
|
374 |
-
// no-op
|
375 |
-
} elseif ($chunk->isFirst()) {
|
376 |
-
$e = $r->openBuffer();
|
377 |
-
|
378 |
-
yield $r => $chunk;
|
379 |
-
|
380 |
-
if ($r->initializer && null === $r->getInfo('error')) {
|
381 |
-
// Ensure the HTTP status code is always checked
|
382 |
-
$r->getHeaders(true);
|
383 |
-
}
|
384 |
-
|
385 |
-
if (null === $e) {
|
386 |
-
continue;
|
387 |
-
}
|
388 |
-
|
389 |
-
$r->response->cancel();
|
390 |
-
$chunk = new ErrorChunk($r->offset, $e);
|
391 |
-
} elseif ('' !== $content = $chunk->getContent()) {
|
392 |
-
if (null !== $r->shouldBuffer) {
|
393 |
-
throw new \LogicException('A chunk passthru must yield an "isFirst()" chunk before any content chunk.');
|
394 |
-
}
|
395 |
-
|
396 |
-
if (null !== $r->content && \strlen($content) !== fwrite($r->content, $content)) {
|
397 |
-
$chunk = new ErrorChunk($r->offset, new TransportException(sprintf('Failed writing %d bytes to the response buffer.', \strlen($content))));
|
398 |
-
$r->info['error'] = $chunk->getError();
|
399 |
-
$r->response->cancel();
|
400 |
-
}
|
401 |
-
}
|
402 |
-
|
403 |
-
if (null !== $chunk->getError() || $chunk->isLast()) {
|
404 |
-
$stream = $r->stream;
|
405 |
-
$r->stream = null;
|
406 |
-
unset($asyncMap[$response]);
|
407 |
-
}
|
408 |
-
|
409 |
-
if (null === $chunk->getError()) {
|
410 |
-
$r->offset += \strlen($content);
|
411 |
-
|
412 |
-
yield $r => $chunk;
|
413 |
-
|
414 |
-
if (!$chunk->isLast()) {
|
415 |
-
continue;
|
416 |
-
}
|
417 |
-
|
418 |
-
$stream->next();
|
419 |
-
|
420 |
-
if ($stream->valid()) {
|
421 |
-
throw new \LogicException('A chunk passthru cannot yield after an "isLast()" chunk.');
|
422 |
-
}
|
423 |
-
|
424 |
-
$r->passthru = null;
|
425 |
-
} else {
|
426 |
-
if ($chunk instanceof ErrorChunk) {
|
427 |
-
$chunk->didThrow(false);
|
428 |
-
} else {
|
429 |
-
try {
|
430 |
-
$chunk = new ErrorChunk($chunk->getOffset(), !$chunk->isTimeout() ?: $chunk->getError());
|
431 |
-
} catch (TransportExceptionInterface $e) {
|
432 |
-
$chunk = new ErrorChunk($chunk->getOffset(), $e);
|
433 |
-
}
|
434 |
-
}
|
435 |
-
|
436 |
-
yield $r => $chunk;
|
437 |
-
$chunk->didThrow() ?: $chunk->getContent();
|
438 |
-
}
|
439 |
-
|
440 |
-
break;
|
441 |
-
}
|
442 |
-
}
|
443 |
-
|
444 |
-
private function openBuffer(): ?\Throwable
|
445 |
-
{
|
446 |
-
if (null === $shouldBuffer = $this->shouldBuffer) {
|
447 |
-
throw new \LogicException('A chunk passthru cannot yield more than one "isFirst()" chunk.');
|
448 |
-
}
|
449 |
-
|
450 |
-
$e = $this->shouldBuffer = null;
|
451 |
-
|
452 |
-
if ($shouldBuffer instanceof \Closure) {
|
453 |
-
try {
|
454 |
-
$shouldBuffer = $shouldBuffer($this->getHeaders(false));
|
455 |
-
|
456 |
-
if (null !== $e = $this->response->getInfo('error')) {
|
457 |
-
throw new TransportException($e);
|
458 |
-
}
|
459 |
-
} catch (\Throwable $e) {
|
460 |
-
$this->info['error'] = $e->getMessage();
|
461 |
-
$this->response->cancel();
|
462 |
-
}
|
463 |
-
}
|
464 |
-
|
465 |
-
if (true === $shouldBuffer) {
|
466 |
-
$this->content = fopen('php://temp', 'w+');
|
467 |
-
} elseif (\is_resource($shouldBuffer)) {
|
468 |
-
$this->content = $shouldBuffer;
|
469 |
-
}
|
470 |
-
|
471 |
-
return $e;
|
472 |
-
}
|
473 |
-
|
474 |
-
private function close(): void
|
475 |
-
{
|
476 |
-
$this->response->cancel();
|
477 |
-
}
|
478 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/CommonResponseTrait.php
DELETED
@@ -1,185 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Exception\ClientException;
|
15 |
-
use Symfony\Component\HttpClient\Exception\JsonException;
|
16 |
-
use Symfony\Component\HttpClient\Exception\RedirectionException;
|
17 |
-
use Symfony\Component\HttpClient\Exception\ServerException;
|
18 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Implements common logic for response classes.
|
22 |
-
*
|
23 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
24 |
-
*
|
25 |
-
* @internal
|
26 |
-
*/
|
27 |
-
trait CommonResponseTrait
|
28 |
-
{
|
29 |
-
/**
|
30 |
-
* @var callable|null A callback that tells whether we're waiting for response headers
|
31 |
-
*/
|
32 |
-
private $initializer;
|
33 |
-
private $shouldBuffer;
|
34 |
-
private $content;
|
35 |
-
private $offset = 0;
|
36 |
-
private $jsonData;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* {@inheritdoc}
|
40 |
-
*/
|
41 |
-
public function getContent(bool $throw = true): string
|
42 |
-
{
|
43 |
-
if ($this->initializer) {
|
44 |
-
self::initialize($this);
|
45 |
-
}
|
46 |
-
|
47 |
-
if ($throw) {
|
48 |
-
$this->checkStatusCode();
|
49 |
-
}
|
50 |
-
|
51 |
-
if (null === $this->content) {
|
52 |
-
$content = null;
|
53 |
-
|
54 |
-
foreach (self::stream([$this]) as $chunk) {
|
55 |
-
if (!$chunk->isLast()) {
|
56 |
-
$content .= $chunk->getContent();
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
if (null !== $content) {
|
61 |
-
return $content;
|
62 |
-
}
|
63 |
-
|
64 |
-
if (null === $this->content) {
|
65 |
-
throw new TransportException('Cannot get the content of the response twice: buffering is disabled.');
|
66 |
-
}
|
67 |
-
} else {
|
68 |
-
foreach (self::stream([$this]) as $chunk) {
|
69 |
-
// Chunks are buffered in $this->content already
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
73 |
-
rewind($this->content);
|
74 |
-
|
75 |
-
return stream_get_contents($this->content);
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* {@inheritdoc}
|
80 |
-
*/
|
81 |
-
public function toArray(bool $throw = true): array
|
82 |
-
{
|
83 |
-
if ('' === $content = $this->getContent($throw)) {
|
84 |
-
throw new JsonException('Response body is empty.');
|
85 |
-
}
|
86 |
-
|
87 |
-
if (null !== $this->jsonData) {
|
88 |
-
return $this->jsonData;
|
89 |
-
}
|
90 |
-
|
91 |
-
try {
|
92 |
-
$content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0));
|
93 |
-
} catch (\JsonException $e) {
|
94 |
-
throw new JsonException($e->getMessage().sprintf(' for "%s".', $this->getInfo('url')), $e->getCode());
|
95 |
-
}
|
96 |
-
|
97 |
-
if (\PHP_VERSION_ID < 70300 && \JSON_ERROR_NONE !== json_last_error()) {
|
98 |
-
throw new JsonException(json_last_error_msg().sprintf(' for "%s".', $this->getInfo('url')), json_last_error());
|
99 |
-
}
|
100 |
-
|
101 |
-
if (!\is_array($content)) {
|
102 |
-
throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned for "%s".', get_debug_type($content), $this->getInfo('url')));
|
103 |
-
}
|
104 |
-
|
105 |
-
if (null !== $this->content) {
|
106 |
-
// Option "buffer" is true
|
107 |
-
return $this->jsonData = $content;
|
108 |
-
}
|
109 |
-
|
110 |
-
return $content;
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* {@inheritdoc}
|
115 |
-
*/
|
116 |
-
public function toStream(bool $throw = true)
|
117 |
-
{
|
118 |
-
if ($throw) {
|
119 |
-
// Ensure headers arrived
|
120 |
-
$this->getHeaders($throw);
|
121 |
-
}
|
122 |
-
|
123 |
-
$stream = StreamWrapper::createResource($this);
|
124 |
-
stream_get_meta_data($stream)['wrapper_data']
|
125 |
-
->bindHandles($this->handle, $this->content);
|
126 |
-
|
127 |
-
return $stream;
|
128 |
-
}
|
129 |
-
|
130 |
-
public function __sleep(): array
|
131 |
-
{
|
132 |
-
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
133 |
-
}
|
134 |
-
|
135 |
-
public function __wakeup()
|
136 |
-
{
|
137 |
-
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* Closes the response and all its network handles.
|
142 |
-
*/
|
143 |
-
abstract protected function close(): void;
|
144 |
-
|
145 |
-
private static function initialize(self $response): void
|
146 |
-
{
|
147 |
-
if (null !== $response->getInfo('error')) {
|
148 |
-
throw new TransportException($response->getInfo('error'));
|
149 |
-
}
|
150 |
-
|
151 |
-
try {
|
152 |
-
if (($response->initializer)($response, -0.0)) {
|
153 |
-
foreach (self::stream([$response], -0.0) as $chunk) {
|
154 |
-
if ($chunk->isFirst()) {
|
155 |
-
break;
|
156 |
-
}
|
157 |
-
}
|
158 |
-
}
|
159 |
-
} catch (\Throwable $e) {
|
160 |
-
// Persist timeouts thrown during initialization
|
161 |
-
$response->info['error'] = $e->getMessage();
|
162 |
-
$response->close();
|
163 |
-
throw $e;
|
164 |
-
}
|
165 |
-
|
166 |
-
$response->initializer = null;
|
167 |
-
}
|
168 |
-
|
169 |
-
private function checkStatusCode()
|
170 |
-
{
|
171 |
-
$code = $this->getInfo('http_code');
|
172 |
-
|
173 |
-
if (500 <= $code) {
|
174 |
-
throw new ServerException($this);
|
175 |
-
}
|
176 |
-
|
177 |
-
if (400 <= $code) {
|
178 |
-
throw new ClientException($this);
|
179 |
-
}
|
180 |
-
|
181 |
-
if (300 <= $code) {
|
182 |
-
throw new RedirectionException($this);
|
183 |
-
}
|
184 |
-
}
|
185 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/CurlResponse.php
DELETED
@@ -1,474 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerInterface;
|
15 |
-
use Symfony\Component\HttpClient\Chunk\FirstChunk;
|
16 |
-
use Symfony\Component\HttpClient\Chunk\InformationalChunk;
|
17 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
18 |
-
use Symfony\Component\HttpClient\Internal\Canary;
|
19 |
-
use Symfony\Component\HttpClient\Internal\ClientState;
|
20 |
-
use Symfony\Component\HttpClient\Internal\CurlClientState;
|
21 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
25 |
-
*
|
26 |
-
* @internal
|
27 |
-
*/
|
28 |
-
final class CurlResponse implements ResponseInterface, StreamableInterface
|
29 |
-
{
|
30 |
-
use CommonResponseTrait {
|
31 |
-
getContent as private doGetContent;
|
32 |
-
}
|
33 |
-
use TransportResponseTrait;
|
34 |
-
|
35 |
-
private static $performing = false;
|
36 |
-
private $multi;
|
37 |
-
private $debugBuffer;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* @param \CurlHandle|resource|string $ch
|
41 |
-
*
|
42 |
-
* @internal
|
43 |
-
*/
|
44 |
-
public function __construct(CurlClientState $multi, $ch, array $options = null, LoggerInterface $logger = null, string $method = 'GET', callable $resolveRedirect = null, int $curlVersion = null)
|
45 |
-
{
|
46 |
-
$this->multi = $multi;
|
47 |
-
|
48 |
-
if (\is_resource($ch) || $ch instanceof \CurlHandle) {
|
49 |
-
$this->handle = $ch;
|
50 |
-
$this->debugBuffer = fopen('php://temp', 'w+');
|
51 |
-
if (0x074000 === $curlVersion) {
|
52 |
-
fwrite($this->debugBuffer, 'Due to a bug in curl 7.64.0, the debug log is disabled; use another version to work around the issue.');
|
53 |
-
} else {
|
54 |
-
curl_setopt($ch, \CURLOPT_VERBOSE, true);
|
55 |
-
curl_setopt($ch, \CURLOPT_STDERR, $this->debugBuffer);
|
56 |
-
}
|
57 |
-
} else {
|
58 |
-
$this->info['url'] = $ch;
|
59 |
-
$ch = $this->handle;
|
60 |
-
}
|
61 |
-
|
62 |
-
$this->id = $id = (int) $ch;
|
63 |
-
$this->logger = $logger;
|
64 |
-
$this->shouldBuffer = $options['buffer'] ?? true;
|
65 |
-
$this->timeout = $options['timeout'] ?? null;
|
66 |
-
$this->info['http_method'] = $method;
|
67 |
-
$this->info['user_data'] = $options['user_data'] ?? null;
|
68 |
-
$this->info['max_duration'] = $options['max_duration'] ?? null;
|
69 |
-
$this->info['start_time'] = $this->info['start_time'] ?? microtime(true);
|
70 |
-
$info = &$this->info;
|
71 |
-
$headers = &$this->headers;
|
72 |
-
$debugBuffer = $this->debugBuffer;
|
73 |
-
|
74 |
-
if (!$info['response_headers']) {
|
75 |
-
// Used to keep track of what we're waiting for
|
76 |
-
curl_setopt($ch, \CURLOPT_PRIVATE, \in_array($method, ['GET', 'HEAD', 'OPTIONS', 'TRACE'], true) && 1.0 < (float) ($options['http_version'] ?? 1.1) ? 'H2' : 'H0'); // H = headers + retry counter
|
77 |
-
}
|
78 |
-
|
79 |
-
curl_setopt($ch, \CURLOPT_HEADERFUNCTION, static function ($ch, string $data) use (&$info, &$headers, $options, $multi, $id, &$location, $resolveRedirect, $logger): int {
|
80 |
-
if (0 !== substr_compare($data, "\r\n", -2)) {
|
81 |
-
return 0;
|
82 |
-
}
|
83 |
-
|
84 |
-
$len = 0;
|
85 |
-
|
86 |
-
foreach (explode("\r\n", substr($data, 0, -2)) as $data) {
|
87 |
-
$len += 2 + self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger);
|
88 |
-
}
|
89 |
-
|
90 |
-
return $len;
|
91 |
-
});
|
92 |
-
|
93 |
-
if (null === $options) {
|
94 |
-
// Pushed response: buffer until requested
|
95 |
-
curl_setopt($ch, \CURLOPT_WRITEFUNCTION, static function ($ch, string $data) use ($multi, $id): int {
|
96 |
-
$multi->handlesActivity[$id][] = $data;
|
97 |
-
curl_pause($ch, \CURLPAUSE_RECV);
|
98 |
-
|
99 |
-
return \strlen($data);
|
100 |
-
});
|
101 |
-
|
102 |
-
return;
|
103 |
-
}
|
104 |
-
|
105 |
-
$execCounter = $multi->execCounter;
|
106 |
-
$this->info['pause_handler'] = static function (float $duration) use ($ch, $multi, $execCounter) {
|
107 |
-
if (0 < $duration) {
|
108 |
-
if ($execCounter === $multi->execCounter) {
|
109 |
-
$multi->execCounter = !\is_float($execCounter) ? 1 + $execCounter : \PHP_INT_MIN;
|
110 |
-
curl_multi_remove_handle($multi->handle, $ch);
|
111 |
-
}
|
112 |
-
|
113 |
-
$lastExpiry = end($multi->pauseExpiries);
|
114 |
-
$multi->pauseExpiries[(int) $ch] = $duration += microtime(true);
|
115 |
-
if (false !== $lastExpiry && $lastExpiry > $duration) {
|
116 |
-
asort($multi->pauseExpiries);
|
117 |
-
}
|
118 |
-
curl_pause($ch, \CURLPAUSE_ALL);
|
119 |
-
} else {
|
120 |
-
unset($multi->pauseExpiries[(int) $ch]);
|
121 |
-
curl_pause($ch, \CURLPAUSE_CONT);
|
122 |
-
curl_multi_add_handle($multi->handle, $ch);
|
123 |
-
}
|
124 |
-
};
|
125 |
-
|
126 |
-
$this->inflate = !isset($options['normalized_headers']['accept-encoding']);
|
127 |
-
curl_pause($ch, \CURLPAUSE_CONT);
|
128 |
-
|
129 |
-
if ($onProgress = $options['on_progress']) {
|
130 |
-
$url = isset($info['url']) ? ['url' => $info['url']] : [];
|
131 |
-
curl_setopt($ch, \CURLOPT_NOPROGRESS, false);
|
132 |
-
curl_setopt($ch, \CURLOPT_PROGRESSFUNCTION, static function ($ch, $dlSize, $dlNow) use ($onProgress, &$info, $url, $multi, $debugBuffer) {
|
133 |
-
try {
|
134 |
-
rewind($debugBuffer);
|
135 |
-
$debug = ['debug' => stream_get_contents($debugBuffer)];
|
136 |
-
$onProgress($dlNow, $dlSize, $url + curl_getinfo($ch) + $info + $debug);
|
137 |
-
} catch (\Throwable $e) {
|
138 |
-
$multi->handlesActivity[(int) $ch][] = null;
|
139 |
-
$multi->handlesActivity[(int) $ch][] = $e;
|
140 |
-
|
141 |
-
return 1; // Abort the request
|
142 |
-
}
|
143 |
-
|
144 |
-
return null;
|
145 |
-
});
|
146 |
-
}
|
147 |
-
|
148 |
-
curl_setopt($ch, \CURLOPT_WRITEFUNCTION, static function ($ch, string $data) use ($multi, $id): int {
|
149 |
-
if ('H' === (curl_getinfo($ch, \CURLINFO_PRIVATE)[0] ?? null)) {
|
150 |
-
$multi->handlesActivity[$id][] = null;
|
151 |
-
$multi->handlesActivity[$id][] = new TransportException(sprintf('Unsupported protocol for "%s"', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL)));
|
152 |
-
|
153 |
-
return 0;
|
154 |
-
}
|
155 |
-
|
156 |
-
curl_setopt($ch, \CURLOPT_WRITEFUNCTION, static function ($ch, string $data) use ($multi, $id): int {
|
157 |
-
$multi->handlesActivity[$id][] = $data;
|
158 |
-
|
159 |
-
return \strlen($data);
|
160 |
-
});
|
161 |
-
|
162 |
-
$multi->handlesActivity[$id][] = $data;
|
163 |
-
|
164 |
-
return \strlen($data);
|
165 |
-
});
|
166 |
-
|
167 |
-
$this->initializer = static function (self $response) {
|
168 |
-
$waitFor = curl_getinfo($ch = $response->handle, \CURLINFO_PRIVATE);
|
169 |
-
|
170 |
-
return 'H' === $waitFor[0];
|
171 |
-
};
|
172 |
-
|
173 |
-
// Schedule the request in a non-blocking way
|
174 |
-
$multi->lastTimeout = null;
|
175 |
-
$multi->openHandles[$id] = [$ch, $options];
|
176 |
-
curl_multi_add_handle($multi->handle, $ch);
|
177 |
-
|
178 |
-
$this->canary = new Canary(static function () use ($ch, $multi, $id) {
|
179 |
-
unset($multi->pauseExpiries[$id], $multi->openHandles[$id], $multi->handlesActivity[$id]);
|
180 |
-
curl_setopt($ch, \CURLOPT_PRIVATE, '_0');
|
181 |
-
|
182 |
-
if (self::$performing) {
|
183 |
-
return;
|
184 |
-
}
|
185 |
-
|
186 |
-
curl_multi_remove_handle($multi->handle, $ch);
|
187 |
-
curl_setopt_array($ch, [
|
188 |
-
\CURLOPT_NOPROGRESS => true,
|
189 |
-
\CURLOPT_PROGRESSFUNCTION => null,
|
190 |
-
\CURLOPT_HEADERFUNCTION => null,
|
191 |
-
\CURLOPT_WRITEFUNCTION => null,
|
192 |
-
\CURLOPT_READFUNCTION => null,
|
193 |
-
\CURLOPT_INFILE => null,
|
194 |
-
]);
|
195 |
-
|
196 |
-
if (!$multi->openHandles) {
|
197 |
-
// Schedule DNS cache eviction for the next request
|
198 |
-
$multi->dnsCache->evictions = $multi->dnsCache->evictions ?: $multi->dnsCache->removals;
|
199 |
-
$multi->dnsCache->removals = $multi->dnsCache->hostnames = [];
|
200 |
-
}
|
201 |
-
});
|
202 |
-
}
|
203 |
-
|
204 |
-
/**
|
205 |
-
* {@inheritdoc}
|
206 |
-
*/
|
207 |
-
public function getInfo(string $type = null)
|
208 |
-
{
|
209 |
-
if (!$info = $this->finalInfo) {
|
210 |
-
$info = array_merge($this->info, curl_getinfo($this->handle));
|
211 |
-
$info['url'] = $this->info['url'] ?? $info['url'];
|
212 |
-
$info['redirect_url'] = $this->info['redirect_url'] ?? null;
|
213 |
-
|
214 |
-
// workaround curl not subtracting the time offset for pushed responses
|
215 |
-
if (isset($this->info['url']) && $info['start_time'] / 1000 < $info['total_time']) {
|
216 |
-
$info['total_time'] -= $info['starttransfer_time'] ?: $info['total_time'];
|
217 |
-
$info['starttransfer_time'] = 0.0;
|
218 |
-
}
|
219 |
-
|
220 |
-
rewind($this->debugBuffer);
|
221 |
-
$info['debug'] = stream_get_contents($this->debugBuffer);
|
222 |
-
$waitFor = curl_getinfo($this->handle, \CURLINFO_PRIVATE);
|
223 |
-
|
224 |
-
if ('H' !== $waitFor[0] && 'C' !== $waitFor[0]) {
|
225 |
-
curl_setopt($this->handle, \CURLOPT_VERBOSE, false);
|
226 |
-
rewind($this->debugBuffer);
|
227 |
-
ftruncate($this->debugBuffer, 0);
|
228 |
-
$this->finalInfo = $info;
|
229 |
-
}
|
230 |
-
}
|
231 |
-
|
232 |
-
return null !== $type ? $info[$type] ?? null : $info;
|
233 |
-
}
|
234 |
-
|
235 |
-
/**
|
236 |
-
* {@inheritdoc}
|
237 |
-
*/
|
238 |
-
public function getContent(bool $throw = true): string
|
239 |
-
{
|
240 |
-
$performing = self::$performing;
|
241 |
-
self::$performing = $performing || '_0' === curl_getinfo($this->handle, \CURLINFO_PRIVATE);
|
242 |
-
|
243 |
-
try {
|
244 |
-
return $this->doGetContent($throw);
|
245 |
-
} finally {
|
246 |
-
self::$performing = $performing;
|
247 |
-
}
|
248 |
-
}
|
249 |
-
|
250 |
-
public function __destruct()
|
251 |
-
{
|
252 |
-
try {
|
253 |
-
if (null === $this->timeout) {
|
254 |
-
return; // Unused pushed response
|
255 |
-
}
|
256 |
-
|
257 |
-
$this->doDestruct();
|
258 |
-
} finally {
|
259 |
-
if (\is_resource($this->handle) || $this->handle instanceof \CurlHandle) {
|
260 |
-
curl_setopt($this->handle, \CURLOPT_VERBOSE, false);
|
261 |
-
}
|
262 |
-
}
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* {@inheritdoc}
|
267 |
-
*/
|
268 |
-
private static function schedule(self $response, array &$runningResponses): void
|
269 |
-
{
|
270 |
-
if (isset($runningResponses[$i = (int) $response->multi->handle])) {
|
271 |
-
$runningResponses[$i][1][$response->id] = $response;
|
272 |
-
} else {
|
273 |
-
$runningResponses[$i] = [$response->multi, [$response->id => $response]];
|
274 |
-
}
|
275 |
-
|
276 |
-
if ('_0' === curl_getinfo($ch = $response->handle, \CURLINFO_PRIVATE)) {
|
277 |
-
// Response already completed
|
278 |
-
$response->multi->handlesActivity[$response->id][] = null;
|
279 |
-
$response->multi->handlesActivity[$response->id][] = null !== $response->info['error'] ? new TransportException($response->info['error']) : null;
|
280 |
-
}
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* {@inheritdoc}
|
285 |
-
*
|
286 |
-
* @param CurlClientState $multi
|
287 |
-
*/
|
288 |
-
private static function perform(ClientState $multi, array &$responses = null): void
|
289 |
-
{
|
290 |
-
if (self::$performing) {
|
291 |
-
if ($responses) {
|
292 |
-
$response = current($responses);
|
293 |
-
$multi->handlesActivity[(int) $response->handle][] = null;
|
294 |
-
$multi->handlesActivity[(int) $response->handle][] = new TransportException(sprintf('Userland callback cannot use the client nor the response while processing "%s".', curl_getinfo($response->handle, \CURLINFO_EFFECTIVE_URL)));
|
295 |
-
}
|
296 |
-
|
297 |
-
return;
|
298 |
-
}
|
299 |
-
|
300 |
-
try {
|
301 |
-
self::$performing = true;
|
302 |
-
++$multi->execCounter;
|
303 |
-
$active = 0;
|
304 |
-
while (\CURLM_CALL_MULTI_PERFORM === ($err = curl_multi_exec($multi->handle, $active))) {
|
305 |
-
}
|
306 |
-
|
307 |
-
if (\CURLM_OK !== $err) {
|
308 |
-
throw new TransportException(curl_multi_strerror($err));
|
309 |
-
}
|
310 |
-
|
311 |
-
while ($info = curl_multi_info_read($multi->handle)) {
|
312 |
-
if (\CURLMSG_DONE !== $info['msg']) {
|
313 |
-
continue;
|
314 |
-
}
|
315 |
-
$result = $info['result'];
|
316 |
-
$id = (int) $ch = $info['handle'];
|
317 |
-
$waitFor = @curl_getinfo($ch, \CURLINFO_PRIVATE) ?: '_0';
|
318 |
-
|
319 |
-
if (\in_array($result, [\CURLE_SEND_ERROR, \CURLE_RECV_ERROR, /*CURLE_HTTP2*/ 16, /*CURLE_HTTP2_STREAM*/ 92], true) && $waitFor[1] && 'C' !== $waitFor[0]) {
|
320 |
-
curl_multi_remove_handle($multi->handle, $ch);
|
321 |
-
$waitFor[1] = (string) ((int) $waitFor[1] - 1); // decrement the retry counter
|
322 |
-
curl_setopt($ch, \CURLOPT_PRIVATE, $waitFor);
|
323 |
-
curl_setopt($ch, \CURLOPT_FORBID_REUSE, true);
|
324 |
-
|
325 |
-
if (0 === curl_multi_add_handle($multi->handle, $ch)) {
|
326 |
-
continue;
|
327 |
-
}
|
328 |
-
}
|
329 |
-
|
330 |
-
if (\CURLE_RECV_ERROR === $result && 'H' === $waitFor[0] && 400 <= ($responses[(int) $ch]->info['http_code'] ?? 0)) {
|
331 |
-
$multi->handlesActivity[$id][] = new FirstChunk();
|
332 |
-
}
|
333 |
-
|
334 |
-
$multi->handlesActivity[$id][] = null;
|
335 |
-
$multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL)));
|
336 |
-
}
|
337 |
-
} finally {
|
338 |
-
self::$performing = false;
|
339 |
-
}
|
340 |
-
}
|
341 |
-
|
342 |
-
/**
|
343 |
-
* {@inheritdoc}
|
344 |
-
*
|
345 |
-
* @param CurlClientState $multi
|
346 |
-
*/
|
347 |
-
private static function select(ClientState $multi, float $timeout): int
|
348 |
-
{
|
349 |
-
if (\PHP_VERSION_ID < 70211) {
|
350 |
-
// workaround https://bugs.php.net/76480
|
351 |
-
$timeout = min($timeout, 0.01);
|
352 |
-
}
|
353 |
-
|
354 |
-
if ($multi->pauseExpiries) {
|
355 |
-
$now = microtime(true);
|
356 |
-
|
357 |
-
foreach ($multi->pauseExpiries as $id => $pauseExpiry) {
|
358 |
-
if ($now < $pauseExpiry) {
|
359 |
-
$timeout = min($timeout, $pauseExpiry - $now);
|
360 |
-
break;
|
361 |
-
}
|
362 |
-
|
363 |
-
unset($multi->pauseExpiries[$id]);
|
364 |
-
curl_pause($multi->openHandles[$id][0], \CURLPAUSE_CONT);
|
365 |
-
curl_multi_add_handle($multi->handle, $multi->openHandles[$id][0]);
|
366 |
-
}
|
367 |
-
}
|
368 |
-
|
369 |
-
if (0 !== $selected = curl_multi_select($multi->handle, $timeout)) {
|
370 |
-
return $selected;
|
371 |
-
}
|
372 |
-
|
373 |
-
if ($multi->pauseExpiries && 0 < $timeout -= microtime(true) - $now) {
|
374 |
-
usleep((int) (1E6 * $timeout));
|
375 |
-
}
|
376 |
-
|
377 |
-
return 0;
|
378 |
-
}
|
379 |
-
|
380 |
-
/**
|
381 |
-
* Parses header lines as curl yields them to us.
|
382 |
-
*/
|
383 |
-
private static function parseHeaderLine($ch, string $data, array &$info, array &$headers, ?array $options, CurlClientState $multi, int $id, ?string &$location, ?callable $resolveRedirect, ?LoggerInterface $logger): int
|
384 |
-
{
|
385 |
-
$waitFor = @curl_getinfo($ch, \CURLINFO_PRIVATE) ?: '_0';
|
386 |
-
|
387 |
-
if ('H' !== $waitFor[0]) {
|
388 |
-
return \strlen($data); // Ignore HTTP trailers
|
389 |
-
}
|
390 |
-
|
391 |
-
if ('' !== $data) {
|
392 |
-
// Regular header line: add it to the list
|
393 |
-
self::addResponseHeaders([$data], $info, $headers);
|
394 |
-
|
395 |
-
if (!str_starts_with($data, 'HTTP/')) {
|
396 |
-
if (0 === stripos($data, 'Location:')) {
|
397 |
-
$location = trim(substr($data, 9));
|
398 |
-
}
|
399 |
-
|
400 |
-
return \strlen($data);
|
401 |
-
}
|
402 |
-
|
403 |
-
if (\function_exists('openssl_x509_read') && $certinfo = curl_getinfo($ch, \CURLINFO_CERTINFO)) {
|
404 |
-
$info['peer_certificate_chain'] = array_map('openssl_x509_read', array_column($certinfo, 'Cert'));
|
405 |
-
}
|
406 |
-
|
407 |
-
if (300 <= $info['http_code'] && $info['http_code'] < 400) {
|
408 |
-
if (curl_getinfo($ch, \CURLINFO_REDIRECT_COUNT) === $options['max_redirects']) {
|
409 |
-
curl_setopt($ch, \CURLOPT_FOLLOWLOCATION, false);
|
410 |
-
} elseif (303 === $info['http_code'] || ('POST' === $info['http_method'] && \in_array($info['http_code'], [301, 302], true))) {
|
411 |
-
curl_setopt($ch, \CURLOPT_POSTFIELDS, '');
|
412 |
-
}
|
413 |
-
}
|
414 |
-
|
415 |
-
return \strlen($data);
|
416 |
-
}
|
417 |
-
|
418 |
-
// End of headers: handle informational responses, redirects, etc.
|
419 |
-
|
420 |
-
if (200 > $statusCode = curl_getinfo($ch, \CURLINFO_RESPONSE_CODE)) {
|
421 |
-
$multi->handlesActivity[$id][] = new InformationalChunk($statusCode, $headers);
|
422 |
-
$location = null;
|
423 |
-
|
424 |
-
return \strlen($data);
|
425 |
-
}
|
426 |
-
|
427 |
-
$info['redirect_url'] = null;
|
428 |
-
|
429 |
-
if (300 <= $statusCode && $statusCode < 400 && null !== $location) {
|
430 |
-
if ($noContent = 303 === $statusCode || ('POST' === $info['http_method'] && \in_array($statusCode, [301, 302], true))) {
|
431 |
-
$info['http_method'] = 'HEAD' === $info['http_method'] ? 'HEAD' : 'GET';
|
432 |
-
curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, $info['http_method']);
|
433 |
-
}
|
434 |
-
|
435 |
-
if (null === $info['redirect_url'] = $resolveRedirect($ch, $location, $noContent)) {
|
436 |
-
$options['max_redirects'] = curl_getinfo($ch, \CURLINFO_REDIRECT_COUNT);
|
437 |
-
curl_setopt($ch, \CURLOPT_FOLLOWLOCATION, false);
|
438 |
-
curl_setopt($ch, \CURLOPT_MAXREDIRS, $options['max_redirects']);
|
439 |
-
} else {
|
440 |
-
$url = parse_url($location ?? ':');
|
441 |
-
|
442 |
-
if (isset($url['host']) && null !== $ip = $multi->dnsCache->hostnames[$url['host'] = strtolower($url['host'])] ?? null) {
|
443 |
-
// Populate DNS cache for redirects if needed
|
444 |
-
$port = $url['port'] ?? ('http' === ($url['scheme'] ?? parse_url(curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL), \PHP_URL_SCHEME)) ? 80 : 443);
|
445 |
-
curl_setopt($ch, \CURLOPT_RESOLVE, ["{$url['host']}:$port:$ip"]);
|
446 |
-
$multi->dnsCache->removals["-{$url['host']}:$port"] = "-{$url['host']}:$port";
|
447 |
-
}
|
448 |
-
}
|
449 |
-
}
|
450 |
-
|
451 |
-
if (401 === $statusCode && isset($options['auth_ntlm']) && 0 === strncasecmp($headers['www-authenticate'][0] ?? '', 'NTLM ', 5)) {
|
452 |
-
// Continue with NTLM auth
|
453 |
-
} elseif ($statusCode < 300 || 400 <= $statusCode || null === $location || curl_getinfo($ch, \CURLINFO_REDIRECT_COUNT) === $options['max_redirects']) {
|
454 |
-
// Headers and redirects completed, time to get the response's content
|
455 |
-
$multi->handlesActivity[$id][] = new FirstChunk();
|
456 |
-
|
457 |
-
if ('HEAD' === $info['http_method'] || \in_array($statusCode, [204, 304], true)) {
|
458 |
-
$waitFor = '_0'; // no content expected
|
459 |
-
$multi->handlesActivity[$id][] = null;
|
460 |
-
$multi->handlesActivity[$id][] = null;
|
461 |
-
} else {
|
462 |
-
$waitFor[0] = 'C'; // C = content
|
463 |
-
}
|
464 |
-
|
465 |
-
curl_setopt($ch, \CURLOPT_PRIVATE, $waitFor);
|
466 |
-
} elseif (null !== $info['redirect_url'] && $logger) {
|
467 |
-
$logger->info(sprintf('Redirecting: "%s %s"', $info['http_code'], $info['redirect_url']));
|
468 |
-
}
|
469 |
-
|
470 |
-
$location = null;
|
471 |
-
|
472 |
-
return \strlen($data);
|
473 |
-
}
|
474 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/HttplugPromise.php
DELETED
@@ -1,80 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use GuzzleHttp\Promise\Create;
|
15 |
-
use GuzzleHttp\Promise\PromiseInterface as GuzzlePromiseInterface;
|
16 |
-
use Http\Promise\Promise as HttplugPromiseInterface;
|
17 |
-
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
21 |
-
*
|
22 |
-
* @internal
|
23 |
-
*/
|
24 |
-
final class HttplugPromise implements HttplugPromiseInterface
|
25 |
-
{
|
26 |
-
private $promise;
|
27 |
-
|
28 |
-
public function __construct(GuzzlePromiseInterface $promise)
|
29 |
-
{
|
30 |
-
$this->promise = $promise;
|
31 |
-
}
|
32 |
-
|
33 |
-
public function then(callable $onFulfilled = null, callable $onRejected = null): self
|
34 |
-
{
|
35 |
-
return new self($this->promise->then(
|
36 |
-
$this->wrapThenCallback($onFulfilled),
|
37 |
-
$this->wrapThenCallback($onRejected)
|
38 |
-
));
|
39 |
-
}
|
40 |
-
|
41 |
-
public function cancel(): void
|
42 |
-
{
|
43 |
-
$this->promise->cancel();
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* {@inheritdoc}
|
48 |
-
*/
|
49 |
-
public function getState(): string
|
50 |
-
{
|
51 |
-
return $this->promise->getState();
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* {@inheritdoc}
|
56 |
-
*
|
57 |
-
* @return Psr7ResponseInterface|mixed
|
58 |
-
*/
|
59 |
-
public function wait($unwrap = true)
|
60 |
-
{
|
61 |
-
$result = $this->promise->wait($unwrap);
|
62 |
-
|
63 |
-
while ($result instanceof HttplugPromiseInterface || $result instanceof GuzzlePromiseInterface) {
|
64 |
-
$result = $result->wait($unwrap);
|
65 |
-
}
|
66 |
-
|
67 |
-
return $result;
|
68 |
-
}
|
69 |
-
|
70 |
-
private function wrapThenCallback(?callable $callback): ?callable
|
71 |
-
{
|
72 |
-
if (null === $callback) {
|
73 |
-
return null;
|
74 |
-
}
|
75 |
-
|
76 |
-
return static function ($value) use ($callback) {
|
77 |
-
return Create::promiseFor($callback($value));
|
78 |
-
};
|
79 |
-
}
|
80 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/MockResponse.php
DELETED
@@ -1,339 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Chunk\ErrorChunk;
|
15 |
-
use Symfony\Component\HttpClient\Chunk\FirstChunk;
|
16 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
17 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
18 |
-
use Symfony\Component\HttpClient\Internal\ClientState;
|
19 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* A test-friendly response.
|
23 |
-
*
|
24 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
25 |
-
*/
|
26 |
-
class MockResponse implements ResponseInterface, StreamableInterface
|
27 |
-
{
|
28 |
-
use CommonResponseTrait;
|
29 |
-
use TransportResponseTrait {
|
30 |
-
doDestruct as public __destruct;
|
31 |
-
}
|
32 |
-
|
33 |
-
private $body;
|
34 |
-
private $requestOptions = [];
|
35 |
-
private $requestUrl;
|
36 |
-
private $requestMethod;
|
37 |
-
|
38 |
-
private static $mainMulti;
|
39 |
-
private static $idSequence = 0;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* @param string|string[]|iterable $body The response body as a string or an iterable of strings,
|
43 |
-
* yielding an empty string simulates an idle timeout,
|
44 |
-
* throwing an exception yields an ErrorChunk
|
45 |
-
*
|
46 |
-
* @see ResponseInterface::getInfo() for possible info, e.g. "response_headers"
|
47 |
-
*/
|
48 |
-
public function __construct($body = '', array $info = [])
|
49 |
-
{
|
50 |
-
$this->body = is_iterable($body) ? $body : (string) $body;
|
51 |
-
$this->info = $info + ['http_code' => 200] + $this->info;
|
52 |
-
|
53 |
-
if (!isset($info['response_headers'])) {
|
54 |
-
return;
|
55 |
-
}
|
56 |
-
|
57 |
-
$responseHeaders = [];
|
58 |
-
|
59 |
-
foreach ($info['response_headers'] as $k => $v) {
|
60 |
-
foreach ((array) $v as $v) {
|
61 |
-
$responseHeaders[] = (\is_string($k) ? $k.': ' : '').$v;
|
62 |
-
}
|
63 |
-
}
|
64 |
-
|
65 |
-
$this->info['response_headers'] = [];
|
66 |
-
self::addResponseHeaders($responseHeaders, $this->info, $this->headers);
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Returns the options used when doing the request.
|
71 |
-
*/
|
72 |
-
public function getRequestOptions(): array
|
73 |
-
{
|
74 |
-
return $this->requestOptions;
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Returns the URL used when doing the request.
|
79 |
-
*/
|
80 |
-
public function getRequestUrl(): string
|
81 |
-
{
|
82 |
-
return $this->requestUrl;
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Returns the method used when doing the request.
|
87 |
-
*/
|
88 |
-
public function getRequestMethod(): string
|
89 |
-
{
|
90 |
-
return $this->requestMethod;
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* {@inheritdoc}
|
95 |
-
*/
|
96 |
-
public function getInfo(string $type = null)
|
97 |
-
{
|
98 |
-
return null !== $type ? $this->info[$type] ?? null : $this->info;
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* {@inheritdoc}
|
103 |
-
*/
|
104 |
-
public function cancel(): void
|
105 |
-
{
|
106 |
-
$this->info['canceled'] = true;
|
107 |
-
$this->info['error'] = 'Response has been canceled.';
|
108 |
-
try {
|
109 |
-
$this->body = null;
|
110 |
-
} catch (TransportException $e) {
|
111 |
-
// ignore errors when canceling
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* {@inheritdoc}
|
117 |
-
*/
|
118 |
-
protected function close(): void
|
119 |
-
{
|
120 |
-
$this->inflate = null;
|
121 |
-
$this->body = [];
|
122 |
-
}
|
123 |
-
|
124 |
-
/**
|
125 |
-
* @internal
|
126 |
-
*/
|
127 |
-
public static function fromRequest(string $method, string $url, array $options, ResponseInterface $mock): self
|
128 |
-
{
|
129 |
-
$response = new self([]);
|
130 |
-
$response->requestOptions = $options;
|
131 |
-
$response->id = ++self::$idSequence;
|
132 |
-
$response->shouldBuffer = $options['buffer'] ?? true;
|
133 |
-
$response->initializer = static function (self $response) {
|
134 |
-
return \is_array($response->body[0] ?? null);
|
135 |
-
};
|
136 |
-
|
137 |
-
$response->info['redirect_count'] = 0;
|
138 |
-
$response->info['redirect_url'] = null;
|
139 |
-
$response->info['start_time'] = microtime(true);
|
140 |
-
$response->info['http_method'] = $method;
|
141 |
-
$response->info['http_code'] = 0;
|
142 |
-
$response->info['user_data'] = $options['user_data'] ?? null;
|
143 |
-
$response->info['max_duration'] = $options['max_duration'] ?? null;
|
144 |
-
$response->info['url'] = $url;
|
145 |
-
|
146 |
-
if ($mock instanceof self) {
|
147 |
-
$mock->requestOptions = $response->requestOptions;
|
148 |
-
$mock->requestMethod = $method;
|
149 |
-
$mock->requestUrl = $url;
|
150 |
-
}
|
151 |
-
|
152 |
-
self::writeRequest($response, $options, $mock);
|
153 |
-
$response->body[] = [$options, $mock];
|
154 |
-
|
155 |
-
return $response;
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
* {@inheritdoc}
|
160 |
-
*/
|
161 |
-
protected static function schedule(self $response, array &$runningResponses): void
|
162 |
-
{
|
163 |
-
if (!$response->id) {
|
164 |
-
throw new InvalidArgumentException('MockResponse instances must be issued by MockHttpClient before processing.');
|
165 |
-
}
|
166 |
-
|
167 |
-
$multi = self::$mainMulti ?? self::$mainMulti = new ClientState();
|
168 |
-
|
169 |
-
if (!isset($runningResponses[0])) {
|
170 |
-
$runningResponses[0] = [$multi, []];
|
171 |
-
}
|
172 |
-
|
173 |
-
$runningResponses[0][1][$response->id] = $response;
|
174 |
-
}
|
175 |
-
|
176 |
-
/**
|
177 |
-
* {@inheritdoc}
|
178 |
-
*/
|
179 |
-
protected static function perform(ClientState $multi, array &$responses): void
|
180 |
-
{
|
181 |
-
foreach ($responses as $response) {
|
182 |
-
$id = $response->id;
|
183 |
-
|
184 |
-
if (null === $response->body) {
|
185 |
-
// Canceled response
|
186 |
-
$response->body = [];
|
187 |
-
} elseif ([] === $response->body) {
|
188 |
-
// Error chunk
|
189 |
-
$multi->handlesActivity[$id][] = null;
|
190 |
-
$multi->handlesActivity[$id][] = null !== $response->info['error'] ? new TransportException($response->info['error']) : null;
|
191 |
-
} elseif (null === $chunk = array_shift($response->body)) {
|
192 |
-
// Last chunk
|
193 |
-
$multi->handlesActivity[$id][] = null;
|
194 |
-
$multi->handlesActivity[$id][] = array_shift($response->body);
|
195 |
-
} elseif (\is_array($chunk)) {
|
196 |
-
// First chunk
|
197 |
-
try {
|
198 |
-
$offset = 0;
|
199 |
-
$chunk[1]->getStatusCode();
|
200 |
-
$chunk[1]->getHeaders(false);
|
201 |
-
self::readResponse($response, $chunk[0], $chunk[1], $offset);
|
202 |
-
$multi->handlesActivity[$id][] = new FirstChunk();
|
203 |
-
$buffer = $response->requestOptions['buffer'] ?? null;
|
204 |
-
|
205 |
-
if ($buffer instanceof \Closure && $response->content = $buffer($response->headers) ?: null) {
|
206 |
-
$response->content = \is_resource($response->content) ? $response->content : fopen('php://temp', 'w+');
|
207 |
-
}
|
208 |
-
} catch (\Throwable $e) {
|
209 |
-
$multi->handlesActivity[$id][] = null;
|
210 |
-
$multi->handlesActivity[$id][] = $e;
|
211 |
-
}
|
212 |
-
} elseif ($chunk instanceof \Throwable) {
|
213 |
-
$multi->handlesActivity[$id][] = null;
|
214 |
-
$multi->handlesActivity[$id][] = $chunk;
|
215 |
-
} else {
|
216 |
-
// Data or timeout chunk
|
217 |
-
$multi->handlesActivity[$id][] = $chunk;
|
218 |
-
}
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* {@inheritdoc}
|
224 |
-
*/
|
225 |
-
protected static function select(ClientState $multi, float $timeout): int
|
226 |
-
{
|
227 |
-
return 42;
|
228 |
-
}
|
229 |
-
|
230 |
-
/**
|
231 |
-
* Simulates sending the request.
|
232 |
-
*/
|
233 |
-
private static function writeRequest(self $response, array $options, ResponseInterface $mock)
|
234 |
-
{
|
235 |
-
$onProgress = $options['on_progress'] ?? static function () {};
|
236 |
-
$response->info += $mock->getInfo() ?: [];
|
237 |
-
|
238 |
-
// simulate "size_upload" if it is set
|
239 |
-
if (isset($response->info['size_upload'])) {
|
240 |
-
$response->info['size_upload'] = 0.0;
|
241 |
-
}
|
242 |
-
|
243 |
-
// simulate "total_time" if it is not set
|
244 |
-
if (!isset($response->info['total_time'])) {
|
245 |
-
$response->info['total_time'] = microtime(true) - $response->info['start_time'];
|
246 |
-
}
|
247 |
-
|
248 |
-
// "notify" DNS resolution
|
249 |
-
$onProgress(0, 0, $response->info);
|
250 |
-
|
251 |
-
// consume the request body
|
252 |
-
if (\is_resource($body = $options['body'] ?? '')) {
|
253 |
-
$data = stream_get_contents($body);
|
254 |
-
if (isset($response->info['size_upload'])) {
|
255 |
-
$response->info['size_upload'] += \strlen($data);
|
256 |
-
}
|
257 |
-
} elseif ($body instanceof \Closure) {
|
258 |
-
while ('' !== $data = $body(16372)) {
|
259 |
-
if (!\is_string($data)) {
|
260 |
-
throw new TransportException(sprintf('Return value of the "body" option callback must be string, "%s" returned.', get_debug_type($data)));
|
261 |
-
}
|
262 |
-
|
263 |
-
// "notify" upload progress
|
264 |
-
if (isset($response->info['size_upload'])) {
|
265 |
-
$response->info['size_upload'] += \strlen($data);
|
266 |
-
}
|
267 |
-
|
268 |
-
$onProgress(0, 0, $response->info);
|
269 |
-
}
|
270 |
-
}
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* Simulates reading the response.
|
275 |
-
*/
|
276 |
-
private static function readResponse(self $response, array $options, ResponseInterface $mock, int &$offset)
|
277 |
-
{
|
278 |
-
$onProgress = $options['on_progress'] ?? static function () {};
|
279 |
-
|
280 |
-
// populate info related to headers
|
281 |
-
$info = $mock->getInfo() ?: [];
|
282 |
-
$response->info['http_code'] = ($info['http_code'] ?? 0) ?: $mock->getStatusCode() ?: 200;
|
283 |
-
$response->addResponseHeaders($info['response_headers'] ?? [], $response->info, $response->headers);
|
284 |
-
$dlSize = isset($response->headers['content-encoding']) || 'HEAD' === $response->info['http_method'] || \in_array($response->info['http_code'], [204, 304], true) ? 0 : (int) ($response->headers['content-length'][0] ?? 0);
|
285 |
-
|
286 |
-
$response->info = [
|
287 |
-
'start_time' => $response->info['start_time'],
|
288 |
-
'user_data' => $response->info['user_data'],
|
289 |
-
'max_duration' => $response->info['max_duration'],
|
290 |
-
'http_code' => $response->info['http_code'],
|
291 |
-
] + $info + $response->info;
|
292 |
-
|
293 |
-
if (null !== $response->info['error']) {
|
294 |
-
throw new TransportException($response->info['error']);
|
295 |
-
}
|
296 |
-
|
297 |
-
if (!isset($response->info['total_time'])) {
|
298 |
-
$response->info['total_time'] = microtime(true) - $response->info['start_time'];
|
299 |
-
}
|
300 |
-
|
301 |
-
// "notify" headers arrival
|
302 |
-
$onProgress(0, $dlSize, $response->info);
|
303 |
-
|
304 |
-
// cast response body to activity list
|
305 |
-
$body = $mock instanceof self ? $mock->body : $mock->getContent(false);
|
306 |
-
|
307 |
-
if (!\is_string($body)) {
|
308 |
-
try {
|
309 |
-
foreach ($body as $chunk) {
|
310 |
-
if ('' === $chunk = (string) $chunk) {
|
311 |
-
// simulate an idle timeout
|
312 |
-
$response->body[] = new ErrorChunk($offset, sprintf('Idle timeout reached for "%s".', $response->info['url']));
|
313 |
-
} else {
|
314 |
-
$response->body[] = $chunk;
|
315 |
-
$offset += \strlen($chunk);
|
316 |
-
// "notify" download progress
|
317 |
-
$onProgress($offset, $dlSize, $response->info);
|
318 |
-
}
|
319 |
-
}
|
320 |
-
} catch (\Throwable $e) {
|
321 |
-
$response->body[] = $e;
|
322 |
-
}
|
323 |
-
} elseif ('' !== $body) {
|
324 |
-
$response->body[] = $body;
|
325 |
-
$offset = \strlen($body);
|
326 |
-
}
|
327 |
-
|
328 |
-
if (!isset($response->info['total_time'])) {
|
329 |
-
$response->info['total_time'] = microtime(true) - $response->info['start_time'];
|
330 |
-
}
|
331 |
-
|
332 |
-
// "notify" completion
|
333 |
-
$onProgress($offset, $dlSize, $response->info);
|
334 |
-
|
335 |
-
if ($dlSize && $offset !== $dlSize) {
|
336 |
-
throw new TransportException(sprintf('Transfer closed with %d bytes remaining to read.', $dlSize - $offset));
|
337 |
-
}
|
338 |
-
}
|
339 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/NativeResponse.php
DELETED
@@ -1,376 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerInterface;
|
15 |
-
use Symfony\Component\HttpClient\Chunk\FirstChunk;
|
16 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
17 |
-
use Symfony\Component\HttpClient\Internal\Canary;
|
18 |
-
use Symfony\Component\HttpClient\Internal\ClientState;
|
19 |
-
use Symfony\Component\HttpClient\Internal\NativeClientState;
|
20 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
24 |
-
*
|
25 |
-
* @internal
|
26 |
-
*/
|
27 |
-
final class NativeResponse implements ResponseInterface, StreamableInterface
|
28 |
-
{
|
29 |
-
use CommonResponseTrait;
|
30 |
-
use TransportResponseTrait;
|
31 |
-
|
32 |
-
private $context;
|
33 |
-
private $url;
|
34 |
-
private $resolver;
|
35 |
-
private $onProgress;
|
36 |
-
private $remaining;
|
37 |
-
private $buffer;
|
38 |
-
private $multi;
|
39 |
-
private $pauseExpiry = 0;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* @internal
|
43 |
-
*/
|
44 |
-
public function __construct(NativeClientState $multi, $context, string $url, array $options, array &$info, callable $resolver, ?callable $onProgress, ?LoggerInterface $logger)
|
45 |
-
{
|
46 |
-
$this->multi = $multi;
|
47 |
-
$this->id = $id = (int) $context;
|
48 |
-
$this->context = $context;
|
49 |
-
$this->url = $url;
|
50 |
-
$this->logger = $logger;
|
51 |
-
$this->timeout = $options['timeout'];
|
52 |
-
$this->info = &$info;
|
53 |
-
$this->resolver = $resolver;
|
54 |
-
$this->onProgress = $onProgress;
|
55 |
-
$this->inflate = !isset($options['normalized_headers']['accept-encoding']);
|
56 |
-
$this->shouldBuffer = $options['buffer'] ?? true;
|
57 |
-
|
58 |
-
// Temporary resource to dechunk the response stream
|
59 |
-
$this->buffer = fopen('php://temp', 'w+');
|
60 |
-
|
61 |
-
$info['user_data'] = $options['user_data'];
|
62 |
-
$info['max_duration'] = $options['max_duration'];
|
63 |
-
++$multi->responseCount;
|
64 |
-
|
65 |
-
$this->initializer = static function (self $response) {
|
66 |
-
return null === $response->remaining;
|
67 |
-
};
|
68 |
-
|
69 |
-
$pauseExpiry = &$this->pauseExpiry;
|
70 |
-
$info['pause_handler'] = static function (float $duration) use (&$pauseExpiry) {
|
71 |
-
$pauseExpiry = 0 < $duration ? microtime(true) + $duration : 0;
|
72 |
-
};
|
73 |
-
|
74 |
-
$this->canary = new Canary(static function () use ($multi, $id) {
|
75 |
-
if (null !== ($host = $multi->openHandles[$id][6] ?? null) && 0 >= --$multi->hosts[$host]) {
|
76 |
-
unset($multi->hosts[$host]);
|
77 |
-
}
|
78 |
-
unset($multi->openHandles[$id], $multi->handlesActivity[$id]);
|
79 |
-
});
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* {@inheritdoc}
|
84 |
-
*/
|
85 |
-
public function getInfo(string $type = null)
|
86 |
-
{
|
87 |
-
if (!$info = $this->finalInfo) {
|
88 |
-
$info = $this->info;
|
89 |
-
$info['url'] = implode('', $info['url']);
|
90 |
-
unset($info['size_body'], $info['request_header']);
|
91 |
-
|
92 |
-
if (null === $this->buffer) {
|
93 |
-
$this->finalInfo = $info;
|
94 |
-
}
|
95 |
-
}
|
96 |
-
|
97 |
-
return null !== $type ? $info[$type] ?? null : $info;
|
98 |
-
}
|
99 |
-
|
100 |
-
public function __destruct()
|
101 |
-
{
|
102 |
-
try {
|
103 |
-
$this->doDestruct();
|
104 |
-
} finally {
|
105 |
-
// Clear the DNS cache when all requests completed
|
106 |
-
if (0 >= --$this->multi->responseCount) {
|
107 |
-
$this->multi->responseCount = 0;
|
108 |
-
$this->multi->dnsCache = [];
|
109 |
-
}
|
110 |
-
}
|
111 |
-
}
|
112 |
-
|
113 |
-
private function open(): void
|
114 |
-
{
|
115 |
-
$url = $this->url;
|
116 |
-
|
117 |
-
set_error_handler(function ($type, $msg) use (&$url) {
|
118 |
-
if (\E_NOTICE !== $type || 'fopen(): Content-type not specified assuming application/x-www-form-urlencoded' !== $msg) {
|
119 |
-
throw new TransportException($msg);
|
120 |
-
}
|
121 |
-
|
122 |
-
$this->logger && $this->logger->info(sprintf('%s for "%s".', $msg, $url ?? $this->url));
|
123 |
-
});
|
124 |
-
|
125 |
-
try {
|
126 |
-
$this->info['start_time'] = microtime(true);
|
127 |
-
|
128 |
-
[$resolver, $url] = ($this->resolver)($this->multi);
|
129 |
-
|
130 |
-
while (true) {
|
131 |
-
$context = stream_context_get_options($this->context);
|
132 |
-
|
133 |
-
if ($proxy = $context['http']['proxy'] ?? null) {
|
134 |
-
$this->info['debug'] .= "* Establish HTTP proxy tunnel to {$proxy}\n";
|
135 |
-
$this->info['request_header'] = $url;
|
136 |
-
} else {
|
137 |
-
$this->info['debug'] .= "* Trying {$this->info['primary_ip']}...\n";
|
138 |
-
$this->info['request_header'] = $this->info['url']['path'].$this->info['url']['query'];
|
139 |
-
}
|
140 |
-
|
141 |
-
$this->info['request_header'] = sprintf("> %s %s HTTP/%s \r\n", $context['http']['method'], $this->info['request_header'], $context['http']['protocol_version']);
|
142 |
-
$this->info['request_header'] .= implode("\r\n", $context['http']['header'])."\r\n\r\n";
|
143 |
-
|
144 |
-
if (\array_key_exists('peer_name', $context['ssl']) && null === $context['ssl']['peer_name']) {
|
145 |
-
unset($context['ssl']['peer_name']);
|
146 |
-
$this->context = stream_context_create([], ['options' => $context] + stream_context_get_params($this->context));
|
147 |
-
}
|
148 |
-
|
149 |
-
// Send request and follow redirects when needed
|
150 |
-
$this->handle = $h = fopen($url, 'r', false, $this->context);
|
151 |
-
self::addResponseHeaders(stream_get_meta_data($h)['wrapper_data'], $this->info, $this->headers, $this->info['debug']);
|
152 |
-
$url = $resolver($this->multi, $this->headers['location'][0] ?? null, $this->context);
|
153 |
-
|
154 |
-
if (null === $url) {
|
155 |
-
break;
|
156 |
-
}
|
157 |
-
|
158 |
-
$this->logger && $this->logger->info(sprintf('Redirecting: "%s %s"', $this->info['http_code'], $url ?? $this->url));
|
159 |
-
}
|
160 |
-
} catch (\Throwable $e) {
|
161 |
-
$this->close();
|
162 |
-
$this->multi->handlesActivity[$this->id][] = null;
|
163 |
-
$this->multi->handlesActivity[$this->id][] = $e;
|
164 |
-
|
165 |
-
return;
|
166 |
-
} finally {
|
167 |
-
$this->info['pretransfer_time'] = $this->info['total_time'] = microtime(true) - $this->info['start_time'];
|
168 |
-
restore_error_handler();
|
169 |
-
}
|
170 |
-
|
171 |
-
if (isset($context['ssl']['capture_peer_cert_chain']) && isset(($context = stream_context_get_options($this->context))['ssl']['peer_certificate_chain'])) {
|
172 |
-
$this->info['peer_certificate_chain'] = $context['ssl']['peer_certificate_chain'];
|
173 |
-
}
|
174 |
-
|
175 |
-
stream_set_blocking($h, false);
|
176 |
-
$this->context = $this->resolver = null;
|
177 |
-
|
178 |
-
// Create dechunk buffers
|
179 |
-
if (isset($this->headers['content-length'])) {
|
180 |
-
$this->remaining = (int) $this->headers['content-length'][0];
|
181 |
-
} elseif ('chunked' === ($this->headers['transfer-encoding'][0] ?? null)) {
|
182 |
-
stream_filter_append($this->buffer, 'dechunk', \STREAM_FILTER_WRITE);
|
183 |
-
$this->remaining = -1;
|
184 |
-
} else {
|
185 |
-
$this->remaining = -2;
|
186 |
-
}
|
187 |
-
|
188 |
-
$this->multi->handlesActivity[$this->id] = [new FirstChunk()];
|
189 |
-
|
190 |
-
if ('HEAD' === $context['http']['method'] || \in_array($this->info['http_code'], [204, 304], true)) {
|
191 |
-
$this->multi->handlesActivity[$this->id][] = null;
|
192 |
-
$this->multi->handlesActivity[$this->id][] = null;
|
193 |
-
|
194 |
-
return;
|
195 |
-
}
|
196 |
-
|
197 |
-
$host = parse_url($this->info['redirect_url'] ?? $this->url, \PHP_URL_HOST);
|
198 |
-
$this->multi->lastTimeout = null;
|
199 |
-
$this->multi->openHandles[$this->id] = [&$this->pauseExpiry, $h, $this->buffer, $this->onProgress, &$this->remaining, &$this->info, $host];
|
200 |
-
$this->multi->hosts[$host] = 1 + ($this->multi->hosts[$host] ?? 0);
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* {@inheritdoc}
|
205 |
-
*/
|
206 |
-
private function close(): void
|
207 |
-
{
|
208 |
-
$this->canary->cancel();
|
209 |
-
$this->handle = $this->buffer = $this->inflate = $this->onProgress = null;
|
210 |
-
}
|
211 |
-
|
212 |
-
/**
|
213 |
-
* {@inheritdoc}
|
214 |
-
*/
|
215 |
-
private static function schedule(self $response, array &$runningResponses): void
|
216 |
-
{
|
217 |
-
if (!isset($runningResponses[$i = $response->multi->id])) {
|
218 |
-
$runningResponses[$i] = [$response->multi, []];
|
219 |
-
}
|
220 |
-
|
221 |
-
$runningResponses[$i][1][$response->id] = $response;
|
222 |
-
|
223 |
-
if (null === $response->buffer) {
|
224 |
-
// Response already completed
|
225 |
-
$response->multi->handlesActivity[$response->id][] = null;
|
226 |
-
$response->multi->handlesActivity[$response->id][] = null !== $response->info['error'] ? new TransportException($response->info['error']) : null;
|
227 |
-
}
|
228 |
-
}
|
229 |
-
|
230 |
-
/**
|
231 |
-
* {@inheritdoc}
|
232 |
-
*
|
233 |
-
* @param NativeClientState $multi
|
234 |
-
*/
|
235 |
-
private static function perform(ClientState $multi, array &$responses = null): void
|
236 |
-
{
|
237 |
-
foreach ($multi->openHandles as $i => [$pauseExpiry, $h, $buffer, $onProgress]) {
|
238 |
-
if ($pauseExpiry) {
|
239 |
-
if (microtime(true) < $pauseExpiry) {
|
240 |
-
continue;
|
241 |
-
}
|
242 |
-
|
243 |
-
$multi->openHandles[$i][0] = 0;
|
244 |
-
}
|
245 |
-
|
246 |
-
$hasActivity = false;
|
247 |
-
$remaining = &$multi->openHandles[$i][4];
|
248 |
-
$info = &$multi->openHandles[$i][5];
|
249 |
-
$e = null;
|
250 |
-
|
251 |
-
// Read incoming buffer and write it to the dechunk one
|
252 |
-
try {
|
253 |
-
if ($remaining && '' !== $data = (string) fread($h, 0 > $remaining ? 16372 : $remaining)) {
|
254 |
-
fwrite($buffer, $data);
|
255 |
-
$hasActivity = true;
|
256 |
-
$multi->sleep = false;
|
257 |
-
|
258 |
-
if (-1 !== $remaining) {
|
259 |
-
$remaining -= \strlen($data);
|
260 |
-
}
|
261 |
-
}
|
262 |
-
} catch (\Throwable $e) {
|
263 |
-
$hasActivity = $onProgress = false;
|
264 |
-
}
|
265 |
-
|
266 |
-
if (!$hasActivity) {
|
267 |
-
if ($onProgress) {
|
268 |
-
try {
|
269 |
-
// Notify the progress callback so that it can e.g. cancel
|
270 |
-
// the request if the stream is inactive for too long
|
271 |
-
$info['total_time'] = microtime(true) - $info['start_time'];
|
272 |
-
$onProgress();
|
273 |
-
} catch (\Throwable $e) {
|
274 |
-
// no-op
|
275 |
-
}
|
276 |
-
}
|
277 |
-
} elseif ('' !== $data = stream_get_contents($buffer, -1, 0)) {
|
278 |
-
rewind($buffer);
|
279 |
-
ftruncate($buffer, 0);
|
280 |
-
|
281 |
-
if (null === $e) {
|
282 |
-
$multi->handlesActivity[$i][] = $data;
|
283 |
-
}
|
284 |
-
}
|
285 |
-
|
286 |
-
if (null !== $e || !$remaining || feof($h)) {
|
287 |
-
// Stream completed
|
288 |
-
$info['total_time'] = microtime(true) - $info['start_time'];
|
289 |
-
$info['starttransfer_time'] = $info['starttransfer_time'] ?: $info['total_time'];
|
290 |
-
|
291 |
-
if ($onProgress) {
|
292 |
-
try {
|
293 |
-
$onProgress(-1);
|
294 |
-
} catch (\Throwable $e) {
|
295 |
-
// no-op
|
296 |
-
}
|
297 |
-
}
|
298 |
-
|
299 |
-
if (null === $e) {
|
300 |
-
if (0 < $remaining) {
|
301 |
-
$e = new TransportException(sprintf('Transfer closed with %s bytes remaining to read.', $remaining));
|
302 |
-
} elseif (-1 === $remaining && fwrite($buffer, '-') && '' !== stream_get_contents($buffer, -1, 0)) {
|
303 |
-
$e = new TransportException('Transfer closed with outstanding data remaining from chunked response.');
|
304 |
-
}
|
305 |
-
}
|
306 |
-
|
307 |
-
$multi->handlesActivity[$i][] = null;
|
308 |
-
$multi->handlesActivity[$i][] = $e;
|
309 |
-
if (null !== ($host = $multi->openHandles[$i][6] ?? null) && 0 >= --$multi->hosts[$host]) {
|
310 |
-
unset($multi->hosts[$host]);
|
311 |
-
}
|
312 |
-
unset($multi->openHandles[$i]);
|
313 |
-
$multi->sleep = false;
|
314 |
-
}
|
315 |
-
}
|
316 |
-
|
317 |
-
if (null === $responses) {
|
318 |
-
return;
|
319 |
-
}
|
320 |
-
|
321 |
-
$maxHosts = $multi->maxHostConnections;
|
322 |
-
|
323 |
-
foreach ($responses as $i => $response) {
|
324 |
-
if (null !== $response->remaining || null === $response->buffer) {
|
325 |
-
continue;
|
326 |
-
}
|
327 |
-
|
328 |
-
if ($response->pauseExpiry && microtime(true) < $response->pauseExpiry) {
|
329 |
-
// Create empty open handles to tell we still have pending requests
|
330 |
-
$multi->openHandles[$i] = [\INF, null, null, null];
|
331 |
-
} elseif ($maxHosts && $maxHosts > ($multi->hosts[parse_url($response->url, \PHP_URL_HOST)] ?? 0)) {
|
332 |
-
// Open the next pending request - this is a blocking operation so we do only one of them
|
333 |
-
$response->open();
|
334 |
-
$multi->sleep = false;
|
335 |
-
self::perform($multi);
|
336 |
-
$maxHosts = 0;
|
337 |
-
}
|
338 |
-
}
|
339 |
-
}
|
340 |
-
|
341 |
-
/**
|
342 |
-
* {@inheritdoc}
|
343 |
-
*
|
344 |
-
* @param NativeClientState $multi
|
345 |
-
*/
|
346 |
-
private static function select(ClientState $multi, float $timeout): int
|
347 |
-
{
|
348 |
-
if (!$multi->sleep = !$multi->sleep) {
|
349 |
-
return -1;
|
350 |
-
}
|
351 |
-
|
352 |
-
$_ = $handles = [];
|
353 |
-
$now = null;
|
354 |
-
|
355 |
-
foreach ($multi->openHandles as [$pauseExpiry, $h]) {
|
356 |
-
if (null === $h) {
|
357 |
-
continue;
|
358 |
-
}
|
359 |
-
|
360 |
-
if ($pauseExpiry && ($now ?? $now = microtime(true)) < $pauseExpiry) {
|
361 |
-
$timeout = min($timeout, $pauseExpiry - $now);
|
362 |
-
continue;
|
363 |
-
}
|
364 |
-
|
365 |
-
$handles[] = $h;
|
366 |
-
}
|
367 |
-
|
368 |
-
if (!$handles) {
|
369 |
-
usleep((int) (1E6 * $timeout));
|
370 |
-
|
371 |
-
return 0;
|
372 |
-
}
|
373 |
-
|
374 |
-
return stream_select($handles, $_, $_, (int) $timeout, (int) (1E6 * ($timeout - (int) $timeout)));
|
375 |
-
}
|
376 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/ResponseStream.php
DELETED
@@ -1,54 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
15 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
16 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
*/
|
21 |
-
final class ResponseStream implements ResponseStreamInterface
|
22 |
-
{
|
23 |
-
private $generator;
|
24 |
-
|
25 |
-
public function __construct(\Generator $generator)
|
26 |
-
{
|
27 |
-
$this->generator = $generator;
|
28 |
-
}
|
29 |
-
|
30 |
-
public function key(): ResponseInterface
|
31 |
-
{
|
32 |
-
return $this->generator->key();
|
33 |
-
}
|
34 |
-
|
35 |
-
public function current(): ChunkInterface
|
36 |
-
{
|
37 |
-
return $this->generator->current();
|
38 |
-
}
|
39 |
-
|
40 |
-
public function next(): void
|
41 |
-
{
|
42 |
-
$this->generator->next();
|
43 |
-
}
|
44 |
-
|
45 |
-
public function rewind(): void
|
46 |
-
{
|
47 |
-
$this->generator->rewind();
|
48 |
-
}
|
49 |
-
|
50 |
-
public function valid(): bool
|
51 |
-
{
|
52 |
-
return $this->generator->valid();
|
53 |
-
}
|
54 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/StreamWrapper.php
DELETED
@@ -1,304 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
|
15 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
16 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Allows turning ResponseInterface instances to PHP streams.
|
20 |
-
*
|
21 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
22 |
-
*/
|
23 |
-
class StreamWrapper
|
24 |
-
{
|
25 |
-
/** @var resource|string|null */
|
26 |
-
public $context;
|
27 |
-
|
28 |
-
/** @var HttpClientInterface */
|
29 |
-
private $client;
|
30 |
-
|
31 |
-
/** @var ResponseInterface */
|
32 |
-
private $response;
|
33 |
-
|
34 |
-
/** @var resource|null */
|
35 |
-
private $content;
|
36 |
-
|
37 |
-
/** @var resource|null */
|
38 |
-
private $handle;
|
39 |
-
|
40 |
-
private $blocking = true;
|
41 |
-
private $timeout;
|
42 |
-
private $eof = false;
|
43 |
-
private $offset = 0;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Creates a PHP stream resource from a ResponseInterface.
|
47 |
-
*
|
48 |
-
* @return resource
|
49 |
-
*/
|
50 |
-
public static function createResource(ResponseInterface $response, HttpClientInterface $client = null)
|
51 |
-
{
|
52 |
-
if ($response instanceof StreamableInterface) {
|
53 |
-
$stack = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
54 |
-
|
55 |
-
if ($response !== ($stack[1]['object'] ?? null)) {
|
56 |
-
return $response->toStream(false);
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
if (null === $client && !method_exists($response, 'stream')) {
|
61 |
-
throw new \InvalidArgumentException(sprintf('Providing a client to "%s()" is required when the response doesn\'t have any "stream()" method.', __CLASS__));
|
62 |
-
}
|
63 |
-
|
64 |
-
if (false === stream_wrapper_register('symfony', __CLASS__)) {
|
65 |
-
throw new \RuntimeException(error_get_last()['message'] ?? 'Registering the "symfony" stream wrapper failed.');
|
66 |
-
}
|
67 |
-
|
68 |
-
try {
|
69 |
-
$context = [
|
70 |
-
'client' => $client ?? $response,
|
71 |
-
'response' => $response,
|
72 |
-
];
|
73 |
-
|
74 |
-
return fopen('symfony://'.$response->getInfo('url'), 'r', false, stream_context_create(['symfony' => $context])) ?: null;
|
75 |
-
} finally {
|
76 |
-
stream_wrapper_unregister('symfony');
|
77 |
-
}
|
78 |
-
}
|
79 |
-
|
80 |
-
public function getResponse(): ResponseInterface
|
81 |
-
{
|
82 |
-
return $this->response;
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* @param resource|callable|null $handle The resource handle that should be monitored when
|
87 |
-
* stream_select() is used on the created stream
|
88 |
-
* @param resource|null $content The seekable resource where the response body is buffered
|
89 |
-
*/
|
90 |
-
public function bindHandles(&$handle, &$content): void
|
91 |
-
{
|
92 |
-
$this->handle = &$handle;
|
93 |
-
$this->content = &$content;
|
94 |
-
}
|
95 |
-
|
96 |
-
public function stream_open(string $path, string $mode, int $options): bool
|
97 |
-
{
|
98 |
-
if ('r' !== $mode) {
|
99 |
-
if ($options & \STREAM_REPORT_ERRORS) {
|
100 |
-
trigger_error(sprintf('Invalid mode "%s": only "r" is supported.', $mode), \E_USER_WARNING);
|
101 |
-
}
|
102 |
-
|
103 |
-
return false;
|
104 |
-
}
|
105 |
-
|
106 |
-
$context = stream_context_get_options($this->context)['symfony'] ?? null;
|
107 |
-
$this->client = $context['client'] ?? null;
|
108 |
-
$this->response = $context['response'] ?? null;
|
109 |
-
$this->context = null;
|
110 |
-
|
111 |
-
if (null !== $this->client && null !== $this->response) {
|
112 |
-
return true;
|
113 |
-
}
|
114 |
-
|
115 |
-
if ($options & \STREAM_REPORT_ERRORS) {
|
116 |
-
trigger_error('Missing options "client" or "response" in "symfony" stream context.', \E_USER_WARNING);
|
117 |
-
}
|
118 |
-
|
119 |
-
return false;
|
120 |
-
}
|
121 |
-
|
122 |
-
public function stream_read(int $count)
|
123 |
-
{
|
124 |
-
if (\is_resource($this->content)) {
|
125 |
-
// Empty the internal activity list
|
126 |
-
foreach ($this->client->stream([$this->response], 0) as $chunk) {
|
127 |
-
try {
|
128 |
-
if (!$chunk->isTimeout() && $chunk->isFirst()) {
|
129 |
-
$this->response->getStatusCode(); // ignore 3/4/5xx
|
130 |
-
}
|
131 |
-
} catch (ExceptionInterface $e) {
|
132 |
-
trigger_error($e->getMessage(), \E_USER_WARNING);
|
133 |
-
|
134 |
-
return false;
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
-
if (0 !== fseek($this->content, $this->offset)) {
|
139 |
-
return false;
|
140 |
-
}
|
141 |
-
|
142 |
-
if ('' !== $data = fread($this->content, $count)) {
|
143 |
-
fseek($this->content, 0, \SEEK_END);
|
144 |
-
$this->offset += \strlen($data);
|
145 |
-
|
146 |
-
return $data;
|
147 |
-
}
|
148 |
-
}
|
149 |
-
|
150 |
-
if (\is_string($this->content)) {
|
151 |
-
if (\strlen($this->content) <= $count) {
|
152 |
-
$data = $this->content;
|
153 |
-
$this->content = null;
|
154 |
-
} else {
|
155 |
-
$data = substr($this->content, 0, $count);
|
156 |
-
$this->content = substr($this->content, $count);
|
157 |
-
}
|
158 |
-
$this->offset += \strlen($data);
|
159 |
-
|
160 |
-
return $data;
|
161 |
-
}
|
162 |
-
|
163 |
-
foreach ($this->client->stream([$this->response], $this->blocking ? $this->timeout : 0) as $chunk) {
|
164 |
-
try {
|
165 |
-
$this->eof = true;
|
166 |
-
$this->eof = !$chunk->isTimeout();
|
167 |
-
$this->eof = $chunk->isLast();
|
168 |
-
|
169 |
-
if ($chunk->isFirst()) {
|
170 |
-
$this->response->getStatusCode(); // ignore 3/4/5xx
|
171 |
-
}
|
172 |
-
|
173 |
-
if ('' !== $data = $chunk->getContent()) {
|
174 |
-
if (\strlen($data) > $count) {
|
175 |
-
if (null === $this->content) {
|
176 |
-
$this->content = substr($data, $count);
|
177 |
-
}
|
178 |
-
$data = substr($data, 0, $count);
|
179 |
-
}
|
180 |
-
$this->offset += \strlen($data);
|
181 |
-
|
182 |
-
return $data;
|
183 |
-
}
|
184 |
-
} catch (ExceptionInterface $e) {
|
185 |
-
trigger_error($e->getMessage(), \E_USER_WARNING);
|
186 |
-
|
187 |
-
return false;
|
188 |
-
}
|
189 |
-
}
|
190 |
-
|
191 |
-
return '';
|
192 |
-
}
|
193 |
-
|
194 |
-
public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
|
195 |
-
{
|
196 |
-
if (\STREAM_OPTION_BLOCKING === $option) {
|
197 |
-
$this->blocking = (bool) $arg1;
|
198 |
-
} elseif (\STREAM_OPTION_READ_TIMEOUT === $option) {
|
199 |
-
$this->timeout = $arg1 + $arg2 / 1e6;
|
200 |
-
} else {
|
201 |
-
return false;
|
202 |
-
}
|
203 |
-
|
204 |
-
return true;
|
205 |
-
}
|
206 |
-
|
207 |
-
public function stream_tell(): int
|
208 |
-
{
|
209 |
-
return $this->offset;
|
210 |
-
}
|
211 |
-
|
212 |
-
public function stream_eof(): bool
|
213 |
-
{
|
214 |
-
return $this->eof && !\is_string($this->content);
|
215 |
-
}
|
216 |
-
|
217 |
-
public function stream_seek(int $offset, int $whence = \SEEK_SET): bool
|
218 |
-
{
|
219 |
-
if (!\is_resource($this->content) || 0 !== fseek($this->content, 0, \SEEK_END)) {
|
220 |
-
return false;
|
221 |
-
}
|
222 |
-
|
223 |
-
$size = ftell($this->content);
|
224 |
-
|
225 |
-
if (\SEEK_CUR === $whence) {
|
226 |
-
$offset += $this->offset;
|
227 |
-
}
|
228 |
-
|
229 |
-
if (\SEEK_END === $whence || $size < $offset) {
|
230 |
-
foreach ($this->client->stream([$this->response]) as $chunk) {
|
231 |
-
try {
|
232 |
-
if ($chunk->isFirst()) {
|
233 |
-
$this->response->getStatusCode(); // ignore 3/4/5xx
|
234 |
-
}
|
235 |
-
|
236 |
-
// Chunks are buffered in $this->content already
|
237 |
-
$size += \strlen($chunk->getContent());
|
238 |
-
|
239 |
-
if (\SEEK_END !== $whence && $offset <= $size) {
|
240 |
-
break;
|
241 |
-
}
|
242 |
-
} catch (ExceptionInterface $e) {
|
243 |
-
trigger_error($e->getMessage(), \E_USER_WARNING);
|
244 |
-
|
245 |
-
return false;
|
246 |
-
}
|
247 |
-
}
|
248 |
-
|
249 |
-
if (\SEEK_END === $whence) {
|
250 |
-
$offset += $size;
|
251 |
-
}
|
252 |
-
}
|
253 |
-
|
254 |
-
if (0 <= $offset && $offset <= $size) {
|
255 |
-
$this->eof = false;
|
256 |
-
$this->offset = $offset;
|
257 |
-
|
258 |
-
return true;
|
259 |
-
}
|
260 |
-
|
261 |
-
return false;
|
262 |
-
}
|
263 |
-
|
264 |
-
public function stream_cast(int $castAs)
|
265 |
-
{
|
266 |
-
if (\STREAM_CAST_FOR_SELECT === $castAs) {
|
267 |
-
$this->response->getHeaders(false);
|
268 |
-
|
269 |
-
return (\is_callable($this->handle) ? ($this->handle)() : $this->handle) ?? false;
|
270 |
-
}
|
271 |
-
|
272 |
-
return false;
|
273 |
-
}
|
274 |
-
|
275 |
-
public function stream_stat(): array
|
276 |
-
{
|
277 |
-
try {
|
278 |
-
$headers = $this->response->getHeaders(false);
|
279 |
-
} catch (ExceptionInterface $e) {
|
280 |
-
trigger_error($e->getMessage(), \E_USER_WARNING);
|
281 |
-
$headers = [];
|
282 |
-
}
|
283 |
-
|
284 |
-
return [
|
285 |
-
'dev' => 0,
|
286 |
-
'ino' => 0,
|
287 |
-
'mode' => 33060,
|
288 |
-
'nlink' => 0,
|
289 |
-
'uid' => 0,
|
290 |
-
'gid' => 0,
|
291 |
-
'rdev' => 0,
|
292 |
-
'size' => (int) ($headers['content-length'][0] ?? -1),
|
293 |
-
'atime' => 0,
|
294 |
-
'mtime' => strtotime($headers['last-modified'][0] ?? '') ?: 0,
|
295 |
-
'ctime' => 0,
|
296 |
-
'blksize' => 0,
|
297 |
-
'blocks' => 0,
|
298 |
-
];
|
299 |
-
}
|
300 |
-
|
301 |
-
private function __construct()
|
302 |
-
{
|
303 |
-
}
|
304 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/StreamableInterface.php
DELETED
@@ -1,35 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
15 |
-
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
16 |
-
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
17 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
21 |
-
*/
|
22 |
-
interface StreamableInterface
|
23 |
-
{
|
24 |
-
/**
|
25 |
-
* Casts the response to a PHP stream resource.
|
26 |
-
*
|
27 |
-
* @return resource
|
28 |
-
*
|
29 |
-
* @throws TransportExceptionInterface When a network error occurs
|
30 |
-
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
|
31 |
-
* @throws ClientExceptionInterface On a 4xx when $throw is true
|
32 |
-
* @throws ServerExceptionInterface On a 5xx when $throw is true
|
33 |
-
*/
|
34 |
-
public function toStream(bool $throw = true);
|
35 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/TraceableResponse.php
DELETED
@@ -1,219 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Chunk\ErrorChunk;
|
15 |
-
use Symfony\Component\HttpClient\Exception\ClientException;
|
16 |
-
use Symfony\Component\HttpClient\Exception\RedirectionException;
|
17 |
-
use Symfony\Component\HttpClient\Exception\ServerException;
|
18 |
-
use Symfony\Component\HttpClient\TraceableHttpClient;
|
19 |
-
use Symfony\Component\Stopwatch\StopwatchEvent;
|
20 |
-
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
21 |
-
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
22 |
-
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
23 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
24 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
25 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
29 |
-
*
|
30 |
-
* @internal
|
31 |
-
*/
|
32 |
-
class TraceableResponse implements ResponseInterface, StreamableInterface
|
33 |
-
{
|
34 |
-
private $client;
|
35 |
-
private $response;
|
36 |
-
private $content;
|
37 |
-
private $event;
|
38 |
-
|
39 |
-
public function __construct(HttpClientInterface $client, ResponseInterface $response, &$content, StopwatchEvent $event = null)
|
40 |
-
{
|
41 |
-
$this->client = $client;
|
42 |
-
$this->response = $response;
|
43 |
-
$this->content = &$content;
|
44 |
-
$this->event = $event;
|
45 |
-
}
|
46 |
-
|
47 |
-
public function __sleep(): array
|
48 |
-
{
|
49 |
-
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
50 |
-
}
|
51 |
-
|
52 |
-
public function __wakeup()
|
53 |
-
{
|
54 |
-
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
55 |
-
}
|
56 |
-
|
57 |
-
public function __destruct()
|
58 |
-
{
|
59 |
-
try {
|
60 |
-
$this->response->__destruct();
|
61 |
-
} finally {
|
62 |
-
if ($this->event && $this->event->isStarted()) {
|
63 |
-
$this->event->stop();
|
64 |
-
}
|
65 |
-
}
|
66 |
-
}
|
67 |
-
|
68 |
-
public function getStatusCode(): int
|
69 |
-
{
|
70 |
-
try {
|
71 |
-
return $this->response->getStatusCode();
|
72 |
-
} finally {
|
73 |
-
if ($this->event && $this->event->isStarted()) {
|
74 |
-
$this->event->lap();
|
75 |
-
}
|
76 |
-
}
|
77 |
-
}
|
78 |
-
|
79 |
-
public function getHeaders(bool $throw = true): array
|
80 |
-
{
|
81 |
-
try {
|
82 |
-
return $this->response->getHeaders($throw);
|
83 |
-
} finally {
|
84 |
-
if ($this->event && $this->event->isStarted()) {
|
85 |
-
$this->event->lap();
|
86 |
-
}
|
87 |
-
}
|
88 |
-
}
|
89 |
-
|
90 |
-
public function getContent(bool $throw = true): string
|
91 |
-
{
|
92 |
-
try {
|
93 |
-
if (false === $this->content) {
|
94 |
-
return $this->response->getContent($throw);
|
95 |
-
}
|
96 |
-
|
97 |
-
return $this->content = $this->response->getContent(false);
|
98 |
-
} finally {
|
99 |
-
if ($this->event && $this->event->isStarted()) {
|
100 |
-
$this->event->stop();
|
101 |
-
}
|
102 |
-
if ($throw) {
|
103 |
-
$this->checkStatusCode($this->response->getStatusCode());
|
104 |
-
}
|
105 |
-
}
|
106 |
-
}
|
107 |
-
|
108 |
-
public function toArray(bool $throw = true): array
|
109 |
-
{
|
110 |
-
try {
|
111 |
-
if (false === $this->content) {
|
112 |
-
return $this->response->toArray($throw);
|
113 |
-
}
|
114 |
-
|
115 |
-
return $this->content = $this->response->toArray(false);
|
116 |
-
} finally {
|
117 |
-
if ($this->event && $this->event->isStarted()) {
|
118 |
-
$this->event->stop();
|
119 |
-
}
|
120 |
-
if ($throw) {
|
121 |
-
$this->checkStatusCode($this->response->getStatusCode());
|
122 |
-
}
|
123 |
-
}
|
124 |
-
}
|
125 |
-
|
126 |
-
public function cancel(): void
|
127 |
-
{
|
128 |
-
$this->response->cancel();
|
129 |
-
|
130 |
-
if ($this->event && $this->event->isStarted()) {
|
131 |
-
$this->event->stop();
|
132 |
-
}
|
133 |
-
}
|
134 |
-
|
135 |
-
public function getInfo(string $type = null)
|
136 |
-
{
|
137 |
-
return $this->response->getInfo($type);
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* Casts the response to a PHP stream resource.
|
142 |
-
*
|
143 |
-
* @return resource
|
144 |
-
*
|
145 |
-
* @throws TransportExceptionInterface When a network error occurs
|
146 |
-
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
|
147 |
-
* @throws ClientExceptionInterface On a 4xx when $throw is true
|
148 |
-
* @throws ServerExceptionInterface On a 5xx when $throw is true
|
149 |
-
*/
|
150 |
-
public function toStream(bool $throw = true)
|
151 |
-
{
|
152 |
-
if ($throw) {
|
153 |
-
// Ensure headers arrived
|
154 |
-
$this->response->getHeaders(true);
|
155 |
-
}
|
156 |
-
|
157 |
-
if ($this->response instanceof StreamableInterface) {
|
158 |
-
return $this->response->toStream(false);
|
159 |
-
}
|
160 |
-
|
161 |
-
return StreamWrapper::createResource($this->response, $this->client);
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* @internal
|
166 |
-
*/
|
167 |
-
public static function stream(HttpClientInterface $client, iterable $responses, ?float $timeout): \Generator
|
168 |
-
{
|
169 |
-
$wrappedResponses = [];
|
170 |
-
$traceableMap = new \SplObjectStorage();
|
171 |
-
|
172 |
-
foreach ($responses as $r) {
|
173 |
-
if (!$r instanceof self) {
|
174 |
-
throw new \TypeError(sprintf('"%s::stream()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.', TraceableHttpClient::class, get_debug_type($r)));
|
175 |
-
}
|
176 |
-
|
177 |
-
$traceableMap[$r->response] = $r;
|
178 |
-
$wrappedResponses[] = $r->response;
|
179 |
-
if ($r->event && !$r->event->isStarted()) {
|
180 |
-
$r->event->start();
|
181 |
-
}
|
182 |
-
}
|
183 |
-
|
184 |
-
foreach ($client->stream($wrappedResponses, $timeout) as $r => $chunk) {
|
185 |
-
if ($traceableMap[$r]->event && $traceableMap[$r]->event->isStarted()) {
|
186 |
-
try {
|
187 |
-
if ($chunk->isTimeout() || !$chunk->isLast()) {
|
188 |
-
$traceableMap[$r]->event->lap();
|
189 |
-
} else {
|
190 |
-
$traceableMap[$r]->event->stop();
|
191 |
-
}
|
192 |
-
} catch (TransportExceptionInterface $e) {
|
193 |
-
$traceableMap[$r]->event->stop();
|
194 |
-
if ($chunk instanceof ErrorChunk) {
|
195 |
-
$chunk->didThrow(false);
|
196 |
-
} else {
|
197 |
-
$chunk = new ErrorChunk($chunk->getOffset(), $e);
|
198 |
-
}
|
199 |
-
}
|
200 |
-
}
|
201 |
-
yield $traceableMap[$r] => $chunk;
|
202 |
-
}
|
203 |
-
}
|
204 |
-
|
205 |
-
private function checkStatusCode(int $code)
|
206 |
-
{
|
207 |
-
if (500 <= $code) {
|
208 |
-
throw new ServerException($this);
|
209 |
-
}
|
210 |
-
|
211 |
-
if (400 <= $code) {
|
212 |
-
throw new ClientException($this);
|
213 |
-
}
|
214 |
-
|
215 |
-
if (300 <= $code) {
|
216 |
-
throw new RedirectionException($this);
|
217 |
-
}
|
218 |
-
}
|
219 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Response/TransportResponseTrait.php
DELETED
@@ -1,312 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Response;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Chunk\DataChunk;
|
15 |
-
use Symfony\Component\HttpClient\Chunk\ErrorChunk;
|
16 |
-
use Symfony\Component\HttpClient\Chunk\FirstChunk;
|
17 |
-
use Symfony\Component\HttpClient\Chunk\LastChunk;
|
18 |
-
use Symfony\Component\HttpClient\Exception\TransportException;
|
19 |
-
use Symfony\Component\HttpClient\Internal\ClientState;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Implements common logic for transport-level response classes.
|
23 |
-
*
|
24 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
25 |
-
*
|
26 |
-
* @internal
|
27 |
-
*/
|
28 |
-
trait TransportResponseTrait
|
29 |
-
{
|
30 |
-
private $canary;
|
31 |
-
private $headers = [];
|
32 |
-
private $info = [
|
33 |
-
'response_headers' => [],
|
34 |
-
'http_code' => 0,
|
35 |
-
'error' => null,
|
36 |
-
'canceled' => false,
|
37 |
-
];
|
38 |
-
|
39 |
-
/** @var object|resource */
|
40 |
-
private $handle;
|
41 |
-
private $id;
|
42 |
-
private $timeout = 0;
|
43 |
-
private $inflate;
|
44 |
-
private $finalInfo;
|
45 |
-
private $logger;
|
46 |
-
|
47 |
-
/**
|
48 |
-
* {@inheritdoc}
|
49 |
-
*/
|
50 |
-
public function getStatusCode(): int
|
51 |
-
{
|
52 |
-
if ($this->initializer) {
|
53 |
-
self::initialize($this);
|
54 |
-
}
|
55 |
-
|
56 |
-
return $this->info['http_code'];
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* {@inheritdoc}
|
61 |
-
*/
|
62 |
-
public function getHeaders(bool $throw = true): array
|
63 |
-
{
|
64 |
-
if ($this->initializer) {
|
65 |
-
self::initialize($this);
|
66 |
-
}
|
67 |
-
|
68 |
-
if ($throw) {
|
69 |
-
$this->checkStatusCode();
|
70 |
-
}
|
71 |
-
|
72 |
-
return $this->headers;
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* {@inheritdoc}
|
77 |
-
*/
|
78 |
-
public function cancel(): void
|
79 |
-
{
|
80 |
-
$this->info['canceled'] = true;
|
81 |
-
$this->info['error'] = 'Response has been canceled.';
|
82 |
-
$this->close();
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Closes the response and all its network handles.
|
87 |
-
*/
|
88 |
-
protected function close(): void
|
89 |
-
{
|
90 |
-
$this->canary->cancel();
|
91 |
-
$this->inflate = null;
|
92 |
-
}
|
93 |
-
|
94 |
-
/**
|
95 |
-
* Adds pending responses to the activity list.
|
96 |
-
*/
|
97 |
-
abstract protected static function schedule(self $response, array &$runningResponses): void;
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Performs all pending non-blocking operations.
|
101 |
-
*/
|
102 |
-
abstract protected static function perform(ClientState $multi, array &$responses): void;
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Waits for network activity.
|
106 |
-
*/
|
107 |
-
abstract protected static function select(ClientState $multi, float $timeout): int;
|
108 |
-
|
109 |
-
private static function addResponseHeaders(array $responseHeaders, array &$info, array &$headers, string &$debug = ''): void
|
110 |
-
{
|
111 |
-
foreach ($responseHeaders as $h) {
|
112 |
-
if (11 <= \strlen($h) && '/' === $h[4] && preg_match('#^HTTP/\d+(?:\.\d+)? (\d\d\d)(?: |$)#', $h, $m)) {
|
113 |
-
if ($headers) {
|
114 |
-
$debug .= "< \r\n";
|
115 |
-
$headers = [];
|
116 |
-
}
|
117 |
-
$info['http_code'] = (int) $m[1];
|
118 |
-
} elseif (2 === \count($m = explode(':', $h, 2))) {
|
119 |
-
$headers[strtolower($m[0])][] = ltrim($m[1]);
|
120 |
-
}
|
121 |
-
|
122 |
-
$debug .= "< {$h}\r\n";
|
123 |
-
$info['response_headers'][] = $h;
|
124 |
-
}
|
125 |
-
|
126 |
-
$debug .= "< \r\n";
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* Ensures the request is always sent and that the response code was checked.
|
131 |
-
*/
|
132 |
-
private function doDestruct()
|
133 |
-
{
|
134 |
-
$this->shouldBuffer = true;
|
135 |
-
|
136 |
-
if ($this->initializer && null === $this->info['error']) {
|
137 |
-
self::initialize($this);
|
138 |
-
$this->checkStatusCode();
|
139 |
-
}
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* Implements an event loop based on a buffer activity queue.
|
144 |
-
*
|
145 |
-
* @param iterable<array-key, self> $responses
|
146 |
-
*
|
147 |
-
* @internal
|
148 |
-
*/
|
149 |
-
public static function stream(iterable $responses, float $timeout = null): \Generator
|
150 |
-
{
|
151 |
-
$runningResponses = [];
|
152 |
-
|
153 |
-
foreach ($responses as $response) {
|
154 |
-
self::schedule($response, $runningResponses);
|
155 |
-
}
|
156 |
-
|
157 |
-
$lastActivity = microtime(true);
|
158 |
-
$elapsedTimeout = 0;
|
159 |
-
|
160 |
-
if ($fromLastTimeout = 0.0 === $timeout && '-0' === (string) $timeout) {
|
161 |
-
$timeout = null;
|
162 |
-
} elseif ($fromLastTimeout = 0 > $timeout) {
|
163 |
-
$timeout = -$timeout;
|
164 |
-
}
|
165 |
-
|
166 |
-
while (true) {
|
167 |
-
$hasActivity = false;
|
168 |
-
$timeoutMax = 0;
|
169 |
-
$timeoutMin = $timeout ?? \INF;
|
170 |
-
|
171 |
-
/** @var ClientState $multi */
|
172 |
-
foreach ($runningResponses as $i => [$multi]) {
|
173 |
-
$responses = &$runningResponses[$i][1];
|
174 |
-
self::perform($multi, $responses);
|
175 |
-
|
176 |
-
foreach ($responses as $j => $response) {
|
177 |
-
$timeoutMax = $timeout ?? max($timeoutMax, $response->timeout);
|
178 |
-
$timeoutMin = min($timeoutMin, $response->timeout, 1);
|
179 |
-
$chunk = false;
|
180 |
-
|
181 |
-
if ($fromLastTimeout && null !== $multi->lastTimeout) {
|
182 |
-
$elapsedTimeout = microtime(true) - $multi->lastTimeout;
|
183 |
-
}
|
184 |
-
|
185 |
-
if (isset($multi->handlesActivity[$j])) {
|
186 |
-
$multi->lastTimeout = null;
|
187 |
-
} elseif (!isset($multi->openHandles[$j])) {
|
188 |
-
unset($responses[$j]);
|
189 |
-
continue;
|
190 |
-
} elseif ($elapsedTimeout >= $timeoutMax) {
|
191 |
-
$multi->handlesActivity[$j] = [new ErrorChunk($response->offset, sprintf('Idle timeout reached for "%s".', $response->getInfo('url')))];
|
192 |
-
$multi->lastTimeout ?? $multi->lastTimeout = $lastActivity;
|
193 |
-
} else {
|
194 |
-
continue;
|
195 |
-
}
|
196 |
-
|
197 |
-
while ($multi->handlesActivity[$j] ?? false) {
|
198 |
-
$hasActivity = true;
|
199 |
-
$elapsedTimeout = 0;
|
200 |
-
|
201 |
-
if (\is_string($chunk = array_shift($multi->handlesActivity[$j]))) {
|
202 |
-
if (null !== $response->inflate && false === $chunk = @inflate_add($response->inflate, $chunk)) {
|
203 |
-
$multi->handlesActivity[$j] = [null, new TransportException(sprintf('Error while processing content unencoding for "%s".', $response->getInfo('url')))];
|
204 |
-
continue;
|
205 |
-
}
|
206 |
-
|
207 |
-
if ('' !== $chunk && null !== $response->content && \strlen($chunk) !== fwrite($response->content, $chunk)) {
|
208 |
-
$multi->handlesActivity[$j] = [null, new TransportException(sprintf('Failed writing %d bytes to the response buffer.', \strlen($chunk)))];
|
209 |
-
continue;
|
210 |
-
}
|
211 |
-
|
212 |
-
$chunkLen = \strlen($chunk);
|
213 |
-
$chunk = new DataChunk($response->offset, $chunk);
|
214 |
-
$response->offset += $chunkLen;
|
215 |
-
} elseif (null === $chunk) {
|
216 |
-
$e = $multi->handlesActivity[$j][0];
|
217 |
-
unset($responses[$j], $multi->handlesActivity[$j]);
|
218 |
-
$response->close();
|
219 |
-
|
220 |
-
if (null !== $e) {
|
221 |
-
$response->info['error'] = $e->getMessage();
|
222 |
-
|
223 |
-
if ($e instanceof \Error) {
|
224 |
-
throw $e;
|
225 |
-
}
|
226 |
-
|
227 |
-
$chunk = new ErrorChunk($response->offset, $e);
|
228 |
-
} else {
|
229 |
-
if (0 === $response->offset && null === $response->content) {
|
230 |
-
$response->content = fopen('php://memory', 'w+');
|
231 |
-
}
|
232 |
-
|
233 |
-
$chunk = new LastChunk($response->offset);
|
234 |
-
}
|
235 |
-
} elseif ($chunk instanceof ErrorChunk) {
|
236 |
-
unset($responses[$j]);
|
237 |
-
$elapsedTimeout = $timeoutMax;
|
238 |
-
} elseif ($chunk instanceof FirstChunk) {
|
239 |
-
if ($response->logger) {
|
240 |
-
$info = $response->getInfo();
|
241 |
-
$response->logger->info(sprintf('Response: "%s %s"', $info['http_code'], $info['url']));
|
242 |
-
}
|
243 |
-
|
244 |
-
$response->inflate = \extension_loaded('zlib') && $response->inflate && 'gzip' === ($response->headers['content-encoding'][0] ?? null) ? inflate_init(\ZLIB_ENCODING_GZIP) : null;
|
245 |
-
|
246 |
-
if ($response->shouldBuffer instanceof \Closure) {
|
247 |
-
try {
|
248 |
-
$response->shouldBuffer = ($response->shouldBuffer)($response->headers);
|
249 |
-
|
250 |
-
if (null !== $response->info['error']) {
|
251 |
-
throw new TransportException($response->info['error']);
|
252 |
-
}
|
253 |
-
} catch (\Throwable $e) {
|
254 |
-
$response->close();
|
255 |
-
$multi->handlesActivity[$j] = [null, $e];
|
256 |
-
}
|
257 |
-
}
|
258 |
-
|
259 |
-
if (true === $response->shouldBuffer) {
|
260 |
-
$response->content = fopen('php://temp', 'w+');
|
261 |
-
} elseif (\is_resource($response->shouldBuffer)) {
|
262 |
-
$response->content = $response->shouldBuffer;
|
263 |
-
}
|
264 |
-
$response->shouldBuffer = null;
|
265 |
-
|
266 |
-
yield $response => $chunk;
|
267 |
-
|
268 |
-
if ($response->initializer && null === $response->info['error']) {
|
269 |
-
// Ensure the HTTP status code is always checked
|
270 |
-
$response->getHeaders(true);
|
271 |
-
}
|
272 |
-
|
273 |
-
continue;
|
274 |
-
}
|
275 |
-
|
276 |
-
yield $response => $chunk;
|
277 |
-
}
|
278 |
-
|
279 |
-
unset($multi->handlesActivity[$j]);
|
280 |
-
|
281 |
-
if ($chunk instanceof ErrorChunk && !$chunk->didThrow()) {
|
282 |
-
// Ensure transport exceptions are always thrown
|
283 |
-
$chunk->getContent();
|
284 |
-
}
|
285 |
-
}
|
286 |
-
|
287 |
-
if (!$responses) {
|
288 |
-
unset($runningResponses[$i]);
|
289 |
-
}
|
290 |
-
|
291 |
-
// Prevent memory leaks
|
292 |
-
$multi->handlesActivity = $multi->handlesActivity ?: [];
|
293 |
-
$multi->openHandles = $multi->openHandles ?: [];
|
294 |
-
}
|
295 |
-
|
296 |
-
if (!$runningResponses) {
|
297 |
-
break;
|
298 |
-
}
|
299 |
-
|
300 |
-
if ($hasActivity) {
|
301 |
-
$lastActivity = microtime(true);
|
302 |
-
continue;
|
303 |
-
}
|
304 |
-
|
305 |
-
if (-1 === self::select($multi, min($timeoutMin, $timeoutMax - $elapsedTimeout))) {
|
306 |
-
usleep(min(500, 1E6 * $timeoutMin));
|
307 |
-
}
|
308 |
-
|
309 |
-
$elapsedTimeout = microtime(true) - $lastActivity;
|
310 |
-
}
|
311 |
-
}
|
312 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Retry/GenericRetryStrategy.php
DELETED
@@ -1,115 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Retry;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
15 |
-
use Symfony\Component\HttpClient\Response\AsyncContext;
|
16 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Decides to retry the request when HTTP status codes belong to the given list of codes.
|
20 |
-
*
|
21 |
-
* @author Jérémy Derussé <jeremy@derusse.com>
|
22 |
-
*/
|
23 |
-
class GenericRetryStrategy implements RetryStrategyInterface
|
24 |
-
{
|
25 |
-
public const IDEMPOTENT_METHODS = ['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS', 'TRACE'];
|
26 |
-
public const DEFAULT_RETRY_STATUS_CODES = [
|
27 |
-
0 => self::IDEMPOTENT_METHODS, // for transport exceptions
|
28 |
-
423,
|
29 |
-
425,
|
30 |
-
429,
|
31 |
-
500 => self::IDEMPOTENT_METHODS,
|
32 |
-
502,
|
33 |
-
503,
|
34 |
-
504 => self::IDEMPOTENT_METHODS,
|
35 |
-
507 => self::IDEMPOTENT_METHODS,
|
36 |
-
510 => self::IDEMPOTENT_METHODS,
|
37 |
-
];
|
38 |
-
|
39 |
-
private $statusCodes;
|
40 |
-
private $delayMs;
|
41 |
-
private $multiplier;
|
42 |
-
private $maxDelayMs;
|
43 |
-
private $jitter;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @param array $statusCodes List of HTTP status codes that trigger a retry
|
47 |
-
* @param int $delayMs Amount of time to delay (or the initial value when multiplier is used)
|
48 |
-
* @param float $multiplier Multiplier to apply to the delay each time a retry occurs
|
49 |
-
* @param int $maxDelayMs Maximum delay to allow (0 means no maximum)
|
50 |
-
* @param float $jitter Probability of randomness int delay (0 = none, 1 = 100% random)
|
51 |
-
*/
|
52 |
-
public function __construct(array $statusCodes = self::DEFAULT_RETRY_STATUS_CODES, int $delayMs = 1000, float $multiplier = 2.0, int $maxDelayMs = 0, float $jitter = 0.1)
|
53 |
-
{
|
54 |
-
$this->statusCodes = $statusCodes;
|
55 |
-
|
56 |
-
if ($delayMs < 0) {
|
57 |
-
throw new InvalidArgumentException(sprintf('Delay must be greater than or equal to zero: "%s" given.', $delayMs));
|
58 |
-
}
|
59 |
-
$this->delayMs = $delayMs;
|
60 |
-
|
61 |
-
if ($multiplier < 1) {
|
62 |
-
throw new InvalidArgumentException(sprintf('Multiplier must be greater than or equal to one: "%s" given.', $multiplier));
|
63 |
-
}
|
64 |
-
$this->multiplier = $multiplier;
|
65 |
-
|
66 |
-
if ($maxDelayMs < 0) {
|
67 |
-
throw new InvalidArgumentException(sprintf('Max delay must be greater than or equal to zero: "%s" given.', $maxDelayMs));
|
68 |
-
}
|
69 |
-
$this->maxDelayMs = $maxDelayMs;
|
70 |
-
|
71 |
-
if ($jitter < 0 || $jitter > 1) {
|
72 |
-
throw new InvalidArgumentException(sprintf('Jitter must be between 0 and 1: "%s" given.', $jitter));
|
73 |
-
}
|
74 |
-
$this->jitter = $jitter;
|
75 |
-
}
|
76 |
-
|
77 |
-
public function shouldRetry(AsyncContext $context, ?string $responseContent, ?TransportExceptionInterface $exception): ?bool
|
78 |
-
{
|
79 |
-
$statusCode = $context->getStatusCode();
|
80 |
-
if (\in_array($statusCode, $this->statusCodes, true)) {
|
81 |
-
return true;
|
82 |
-
}
|
83 |
-
if (isset($this->statusCodes[$statusCode]) && \is_array($this->statusCodes[$statusCode])) {
|
84 |
-
return \in_array($context->getInfo('http_method'), $this->statusCodes[$statusCode], true);
|
85 |
-
}
|
86 |
-
if (null === $exception) {
|
87 |
-
return false;
|
88 |
-
}
|
89 |
-
|
90 |
-
if (\in_array(0, $this->statusCodes, true)) {
|
91 |
-
return true;
|
92 |
-
}
|
93 |
-
if (isset($this->statusCodes[0]) && \is_array($this->statusCodes[0])) {
|
94 |
-
return \in_array($context->getInfo('http_method'), $this->statusCodes[0], true);
|
95 |
-
}
|
96 |
-
|
97 |
-
return false;
|
98 |
-
}
|
99 |
-
|
100 |
-
public function getDelay(AsyncContext $context, ?string $responseContent, ?TransportExceptionInterface $exception): int
|
101 |
-
{
|
102 |
-
$delay = $this->delayMs * $this->multiplier ** $context->getInfo('retry_count');
|
103 |
-
|
104 |
-
if ($this->jitter > 0) {
|
105 |
-
$randomness = $delay * $this->jitter;
|
106 |
-
$delay = $delay + random_int(-$randomness, +$randomness);
|
107 |
-
}
|
108 |
-
|
109 |
-
if ($delay > $this->maxDelayMs && 0 !== $this->maxDelayMs) {
|
110 |
-
return $this->maxDelayMs;
|
111 |
-
}
|
112 |
-
|
113 |
-
return (int) $delay;
|
114 |
-
}
|
115 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/Retry/RetryStrategyInterface.php
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient\Retry;
|
13 |
-
|
14 |
-
use Symfony\Component\HttpClient\Response\AsyncContext;
|
15 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @author Jérémy Derussé <jeremy@derusse.com>
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
*/
|
21 |
-
interface RetryStrategyInterface
|
22 |
-
{
|
23 |
-
/**
|
24 |
-
* Returns whether the request should be retried.
|
25 |
-
*
|
26 |
-
* @param ?string $responseContent Null is passed when the body did not arrive yet
|
27 |
-
*
|
28 |
-
* @return bool|null Returns null to signal that the body is required to take a decision
|
29 |
-
*/
|
30 |
-
public function shouldRetry(AsyncContext $context, ?string $responseContent, ?TransportExceptionInterface $exception): ?bool;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Returns the time to wait in milliseconds.
|
34 |
-
*/
|
35 |
-
public function getDelay(AsyncContext $context, ?string $responseContent, ?TransportExceptionInterface $exception): int;
|
36 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/RetryableHttpClient.php
DELETED
@@ -1,169 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerInterface;
|
15 |
-
use Psr\Log\NullLogger;
|
16 |
-
use Symfony\Component\HttpClient\Response\AsyncContext;
|
17 |
-
use Symfony\Component\HttpClient\Response\AsyncResponse;
|
18 |
-
use Symfony\Component\HttpClient\Retry\GenericRetryStrategy;
|
19 |
-
use Symfony\Component\HttpClient\Retry\RetryStrategyInterface;
|
20 |
-
use Symfony\Contracts\HttpClient\ChunkInterface;
|
21 |
-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
22 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
23 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
24 |
-
use Symfony\Contracts\Service\ResetInterface;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Automatically retries failing HTTP requests.
|
28 |
-
*
|
29 |
-
* @author Jérémy Derussé <jeremy@derusse.com>
|
30 |
-
*/
|
31 |
-
class RetryableHttpClient implements HttpClientInterface, ResetInterface
|
32 |
-
{
|
33 |
-
use AsyncDecoratorTrait;
|
34 |
-
|
35 |
-
private $strategy;
|
36 |
-
private $maxRetries;
|
37 |
-
private $logger;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* @param int $maxRetries The maximum number of times to retry
|
41 |
-
*/
|
42 |
-
public function __construct(HttpClientInterface $client, RetryStrategyInterface $strategy = null, int $maxRetries = 3, LoggerInterface $logger = null)
|
43 |
-
{
|
44 |
-
$this->client = $client;
|
45 |
-
$this->strategy = $strategy ?? new GenericRetryStrategy();
|
46 |
-
$this->maxRetries = $maxRetries;
|
47 |
-
$this->logger = $logger ?? new NullLogger();
|
48 |
-
}
|
49 |
-
|
50 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
51 |
-
{
|
52 |
-
if ($this->maxRetries <= 0) {
|
53 |
-
return new AsyncResponse($this->client, $method, $url, $options);
|
54 |
-
}
|
55 |
-
|
56 |
-
$retryCount = 0;
|
57 |
-
$content = '';
|
58 |
-
$firstChunk = null;
|
59 |
-
|
60 |
-
return new AsyncResponse($this->client, $method, $url, $options, function (ChunkInterface $chunk, AsyncContext $context) use ($method, $url, $options, &$retryCount, &$content, &$firstChunk) {
|
61 |
-
$exception = null;
|
62 |
-
try {
|
63 |
-
if ($chunk->isTimeout() || null !== $chunk->getInformationalStatus() || $context->getInfo('canceled')) {
|
64 |
-
yield $chunk;
|
65 |
-
|
66 |
-
return;
|
67 |
-
}
|
68 |
-
} catch (TransportExceptionInterface $exception) {
|
69 |
-
// catch TransportExceptionInterface to send it to the strategy
|
70 |
-
}
|
71 |
-
if (null !== $exception) {
|
72 |
-
// always retry request that fail to resolve DNS
|
73 |
-
if ('' !== $context->getInfo('primary_ip')) {
|
74 |
-
$shouldRetry = $this->strategy->shouldRetry($context, null, $exception);
|
75 |
-
if (null === $shouldRetry) {
|
76 |
-
throw new \LogicException(sprintf('The "%s::shouldRetry()" method must not return null when called with an exception.', \get_class($this->strategy)));
|
77 |
-
}
|
78 |
-
|
79 |
-
if (false === $shouldRetry) {
|
80 |
-
yield from $this->passthru($context, $firstChunk, $content, $chunk);
|
81 |
-
|
82 |
-
return;
|
83 |
-
}
|
84 |
-
}
|
85 |
-
} elseif ($chunk->isFirst()) {
|
86 |
-
if (false === $shouldRetry = $this->strategy->shouldRetry($context, null, null)) {
|
87 |
-
yield from $this->passthru($context, $firstChunk, $content, $chunk);
|
88 |
-
|
89 |
-
return;
|
90 |
-
}
|
91 |
-
|
92 |
-
// Body is needed to decide
|
93 |
-
if (null === $shouldRetry) {
|
94 |
-
$firstChunk = $chunk;
|
95 |
-
$content = '';
|
96 |
-
|
97 |
-
return;
|
98 |
-
}
|
99 |
-
} else {
|
100 |
-
if (!$chunk->isLast()) {
|
101 |
-
$content .= $chunk->getContent();
|
102 |
-
|
103 |
-
return;
|
104 |
-
}
|
105 |
-
|
106 |
-
if (null === $shouldRetry = $this->strategy->shouldRetry($context, $content, null)) {
|
107 |
-
throw new \LogicException(sprintf('The "%s::shouldRetry()" method must not return null when called with a body.', \get_class($this->strategy)));
|
108 |
-
}
|
109 |
-
|
110 |
-
if (false === $shouldRetry) {
|
111 |
-
yield from $this->passthru($context, $firstChunk, $content, $chunk);
|
112 |
-
|
113 |
-
return;
|
114 |
-
}
|
115 |
-
}
|
116 |
-
|
117 |
-
$context->getResponse()->cancel();
|
118 |
-
|
119 |
-
$delay = $this->getDelayFromHeader($context->getHeaders()) ?? $this->strategy->getDelay($context, !$exception && $chunk->isLast() ? $content : null, $exception);
|
120 |
-
++$retryCount;
|
121 |
-
|
122 |
-
$this->logger->info('Try #{count} after {delay}ms'.($exception ? ': '.$exception->getMessage() : ', status code: '.$context->getStatusCode()), [
|
123 |
-
'count' => $retryCount,
|
124 |
-
'delay' => $delay,
|
125 |
-
]);
|
126 |
-
|
127 |
-
$context->setInfo('retry_count', $retryCount);
|
128 |
-
$context->replaceRequest($method, $url, $options);
|
129 |
-
$context->pause($delay / 1000);
|
130 |
-
|
131 |
-
if ($retryCount >= $this->maxRetries) {
|
132 |
-
$context->passthru();
|
133 |
-
}
|
134 |
-
});
|
135 |
-
}
|
136 |
-
|
137 |
-
private function getDelayFromHeader(array $headers): ?int
|
138 |
-
{
|
139 |
-
if (null !== $after = $headers['retry-after'][0] ?? null) {
|
140 |
-
if (is_numeric($after)) {
|
141 |
-
return (int) $after * 1000;
|
142 |
-
}
|
143 |
-
|
144 |
-
if (false !== $time = strtotime($after)) {
|
145 |
-
return max(0, $time - time()) * 1000;
|
146 |
-
}
|
147 |
-
}
|
148 |
-
|
149 |
-
return null;
|
150 |
-
}
|
151 |
-
|
152 |
-
private function passthru(AsyncContext $context, ?ChunkInterface $firstChunk, string &$content, ChunkInterface $lastChunk): \Generator
|
153 |
-
{
|
154 |
-
$context->passthru();
|
155 |
-
|
156 |
-
if (null !== $firstChunk) {
|
157 |
-
yield $firstChunk;
|
158 |
-
}
|
159 |
-
|
160 |
-
if ('' !== $content) {
|
161 |
-
$chunk = $context->createChunk($content);
|
162 |
-
$content = '';
|
163 |
-
|
164 |
-
yield $chunk;
|
165 |
-
}
|
166 |
-
|
167 |
-
yield $lastChunk;
|
168 |
-
}
|
169 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/ScopingHttpClient.php
DELETED
@@ -1,131 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerAwareInterface;
|
15 |
-
use Psr\Log\LoggerInterface;
|
16 |
-
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
17 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
18 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
19 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
20 |
-
use Symfony\Contracts\Service\ResetInterface;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Auto-configure the default options based on the requested URL.
|
24 |
-
*
|
25 |
-
* @author Anthony Martin <anthony.martin@sensiolabs.com>
|
26 |
-
*/
|
27 |
-
class ScopingHttpClient implements HttpClientInterface, ResetInterface, LoggerAwareInterface
|
28 |
-
{
|
29 |
-
use HttpClientTrait;
|
30 |
-
|
31 |
-
private $client;
|
32 |
-
private $defaultOptionsByRegexp;
|
33 |
-
private $defaultRegexp;
|
34 |
-
|
35 |
-
public function __construct(HttpClientInterface $client, array $defaultOptionsByRegexp, string $defaultRegexp = null)
|
36 |
-
{
|
37 |
-
$this->client = $client;
|
38 |
-
$this->defaultOptionsByRegexp = $defaultOptionsByRegexp;
|
39 |
-
$this->defaultRegexp = $defaultRegexp;
|
40 |
-
|
41 |
-
if (null !== $defaultRegexp && !isset($defaultOptionsByRegexp[$defaultRegexp])) {
|
42 |
-
throw new InvalidArgumentException(sprintf('No options are mapped to the provided "%s" default regexp.', $defaultRegexp));
|
43 |
-
}
|
44 |
-
}
|
45 |
-
|
46 |
-
public static function forBaseUri(HttpClientInterface $client, string $baseUri, array $defaultOptions = [], string $regexp = null): self
|
47 |
-
{
|
48 |
-
if (null === $regexp) {
|
49 |
-
$regexp = preg_quote(implode('', self::resolveUrl(self::parseUrl('.'), self::parseUrl($baseUri))));
|
50 |
-
}
|
51 |
-
|
52 |
-
$defaultOptions['base_uri'] = $baseUri;
|
53 |
-
|
54 |
-
return new self($client, [$regexp => $defaultOptions], $regexp);
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* {@inheritdoc}
|
59 |
-
*/
|
60 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
61 |
-
{
|
62 |
-
$e = null;
|
63 |
-
$url = self::parseUrl($url, $options['query'] ?? []);
|
64 |
-
|
65 |
-
if (\is_string($options['base_uri'] ?? null)) {
|
66 |
-
$options['base_uri'] = self::parseUrl($options['base_uri']);
|
67 |
-
}
|
68 |
-
|
69 |
-
try {
|
70 |
-
$url = implode('', self::resolveUrl($url, $options['base_uri'] ?? null));
|
71 |
-
} catch (InvalidArgumentException $e) {
|
72 |
-
if (null === $this->defaultRegexp) {
|
73 |
-
throw $e;
|
74 |
-
}
|
75 |
-
|
76 |
-
$defaultOptions = $this->defaultOptionsByRegexp[$this->defaultRegexp];
|
77 |
-
$options = self::mergeDefaultOptions($options, $defaultOptions, true);
|
78 |
-
if (\is_string($options['base_uri'] ?? null)) {
|
79 |
-
$options['base_uri'] = self::parseUrl($options['base_uri']);
|
80 |
-
}
|
81 |
-
$url = implode('', self::resolveUrl($url, $options['base_uri'] ?? null, $defaultOptions['query'] ?? []));
|
82 |
-
}
|
83 |
-
|
84 |
-
foreach ($this->defaultOptionsByRegexp as $regexp => $defaultOptions) {
|
85 |
-
if (preg_match("{{$regexp}}A", $url)) {
|
86 |
-
if (null === $e || $regexp !== $this->defaultRegexp) {
|
87 |
-
$options = self::mergeDefaultOptions($options, $defaultOptions, true);
|
88 |
-
}
|
89 |
-
break;
|
90 |
-
}
|
91 |
-
}
|
92 |
-
|
93 |
-
return $this->client->request($method, $url, $options);
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* {@inheritdoc}
|
98 |
-
*/
|
99 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
100 |
-
{
|
101 |
-
return $this->client->stream($responses, $timeout);
|
102 |
-
}
|
103 |
-
|
104 |
-
public function reset()
|
105 |
-
{
|
106 |
-
if ($this->client instanceof ResetInterface) {
|
107 |
-
$this->client->reset();
|
108 |
-
}
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* {@inheritdoc}
|
113 |
-
*/
|
114 |
-
public function setLogger(LoggerInterface $logger): void
|
115 |
-
{
|
116 |
-
if ($this->client instanceof LoggerAwareInterface) {
|
117 |
-
$this->client->setLogger($logger);
|
118 |
-
}
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* {@inheritdoc}
|
123 |
-
*/
|
124 |
-
public function withOptions(array $options): self
|
125 |
-
{
|
126 |
-
$clone = clone $this;
|
127 |
-
$clone->client = $this->client->withOptions($options);
|
128 |
-
|
129 |
-
return $clone;
|
130 |
-
}
|
131 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/TraceableHttpClient.php
DELETED
@@ -1,120 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Component\HttpClient;
|
13 |
-
|
14 |
-
use Psr\Log\LoggerAwareInterface;
|
15 |
-
use Psr\Log\LoggerInterface;
|
16 |
-
use Symfony\Component\HttpClient\Response\ResponseStream;
|
17 |
-
use Symfony\Component\HttpClient\Response\TraceableResponse;
|
18 |
-
use Symfony\Component\Stopwatch\Stopwatch;
|
19 |
-
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
20 |
-
use Symfony\Contracts\HttpClient\ResponseInterface;
|
21 |
-
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
22 |
-
use Symfony\Contracts\Service\ResetInterface;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @author Jérémy Romey <jeremy@free-agent.fr>
|
26 |
-
*/
|
27 |
-
final class TraceableHttpClient implements HttpClientInterface, ResetInterface, LoggerAwareInterface
|
28 |
-
{
|
29 |
-
private $client;
|
30 |
-
private $stopwatch;
|
31 |
-
private $tracedRequests;
|
32 |
-
|
33 |
-
public function __construct(HttpClientInterface $client, Stopwatch $stopwatch = null)
|
34 |
-
{
|
35 |
-
$this->client = $client;
|
36 |
-
$this->stopwatch = $stopwatch;
|
37 |
-
$this->tracedRequests = new \ArrayObject();
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* {@inheritdoc}
|
42 |
-
*/
|
43 |
-
public function request(string $method, string $url, array $options = []): ResponseInterface
|
44 |
-
{
|
45 |
-
$content = null;
|
46 |
-
$traceInfo = [];
|
47 |
-
$this->tracedRequests[] = [
|
48 |
-
'method' => $method,
|
49 |
-
'url' => $url,
|
50 |
-
'options' => $options,
|
51 |
-
'info' => &$traceInfo,
|
52 |
-
'content' => &$content,
|
53 |
-
];
|
54 |
-
$onProgress = $options['on_progress'] ?? null;
|
55 |
-
|
56 |
-
if (false === ($options['extra']['trace_content'] ?? true)) {
|
57 |
-
unset($content);
|
58 |
-
$content = false;
|
59 |
-
}
|
60 |
-
|
61 |
-
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use (&$traceInfo, $onProgress) {
|
62 |
-
$traceInfo = $info;
|
63 |
-
|
64 |
-
if (null !== $onProgress) {
|
65 |
-
$onProgress($dlNow, $dlSize, $info);
|
66 |
-
}
|
67 |
-
};
|
68 |
-
|
69 |
-
return new TraceableResponse($this->client, $this->client->request($method, $url, $options), $content, null === $this->stopwatch ? null : $this->stopwatch->start("$method $url", 'http_client'));
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* {@inheritdoc}
|
74 |
-
*/
|
75 |
-
public function stream($responses, float $timeout = null): ResponseStreamInterface
|
76 |
-
{
|
77 |
-
if ($responses instanceof TraceableResponse) {
|
78 |
-
$responses = [$responses];
|
79 |
-
} elseif (!is_iterable($responses)) {
|
80 |
-
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
|
81 |
-
}
|
82 |
-
|
83 |
-
return new ResponseStream(TraceableResponse::stream($this->client, $responses, $timeout));
|
84 |
-
}
|
85 |
-
|
86 |
-
public function getTracedRequests(): array
|
87 |
-
{
|
88 |
-
return $this->tracedRequests->getArrayCopy();
|
89 |
-
}
|
90 |
-
|
91 |
-
public function reset()
|
92 |
-
{
|
93 |
-
if ($this->client instanceof ResetInterface) {
|
94 |
-
$this->client->reset();
|
95 |
-
}
|
96 |
-
|
97 |
-
$this->tracedRequests->exchangeArray([]);
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* {@inheritdoc}
|
102 |
-
*/
|
103 |
-
public function setLogger(LoggerInterface $logger): void
|
104 |
-
{
|
105 |
-
if ($this->client instanceof LoggerAwareInterface) {
|
106 |
-
$this->client->setLogger($logger);
|
107 |
-
}
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* {@inheritdoc}
|
112 |
-
*/
|
113 |
-
public function withOptions(array $options): self
|
114 |
-
{
|
115 |
-
$clone = clone $this;
|
116 |
-
$clone->client = $this->client->withOptions($options);
|
117 |
-
|
118 |
-
return $clone;
|
119 |
-
}
|
120 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/http-client/composer.json
DELETED
@@ -1,53 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "symfony/http-client",
|
3 |
-
"type": "library",
|
4 |
-
"description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
|
5 |
-
"homepage": "https://symfony.com",
|
6 |
-
"license": "MIT",
|
7 |
-
"authors": [
|
8 |
-
{
|
9 |
-
"name": "Nicolas Grekas",
|
10 |
-
"email": "p@tchwork.com"
|
11 |
-
},
|
12 |
-
{
|
13 |
-
"name": "Symfony Community",
|
14 |
-
"homepage": "https://symfony.com/contributors"
|
15 |
-
}
|
16 |
-
],
|
17 |
-
"provide": {
|
18 |
-
"php-http/async-client-implementation": "*",
|
19 |
-
"php-http/client-implementation": "*",
|
20 |
-
"psr/http-client-implementation": "1.0",
|
21 |
-
"symfony/http-client-implementation": "2.4"
|
22 |
-
},
|
23 |
-
"require": {
|
24 |
-
"php": ">=7.2.5",
|
25 |
-
"psr/log": "^1|^2|^3",
|
26 |
-
"symfony/deprecation-contracts": "^2.1|^3",
|
27 |
-
"symfony/http-client-contracts": "^2.4",
|
28 |
-
"symfony/polyfill-php73": "^1.11",
|
29 |
-
"symfony/polyfill-php80": "^1.16",
|
30 |
-
"symfony/service-contracts": "^1.0|^2|^3"
|
31 |
-
},
|
32 |
-
"require-dev": {
|
33 |
-
"amphp/amp": "^2.5",
|
34 |
-
"amphp/http-client": "^4.2.1",
|
35 |
-
"amphp/http-tunnel": "^1.0",
|
36 |
-
"amphp/socket": "^1.1",
|
37 |
-
"guzzlehttp/promises": "^1.4",
|
38 |
-
"nyholm/psr7": "^1.0",
|
39 |
-
"php-http/httplug": "^1.0|^2.0",
|
40 |
-
"psr/http-client": "^1.0",
|
41 |
-
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
|
42 |
-
"symfony/http-kernel": "^4.4.13|^5.1.5|^6.0",
|
43 |
-
"symfony/process": "^4.4|^5.0|^6.0",
|
44 |
-
"symfony/stopwatch": "^4.4|^5.0|^6.0"
|
45 |
-
},
|
46 |
-
"autoload": {
|
47 |
-
"psr-4": { "Symfony\\Component\\HttpClient\\": "" },
|
48 |
-
"exclude-from-classmap": [
|
49 |
-
"/Tests/"
|
50 |
-
]
|
51 |
-
},
|
52 |
-
"minimum-stability": "dev"
|
53 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/.gitignore
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
vendor/
|
2 |
-
composer.lock
|
3 |
-
phpunit.xml
|
|
|
|
|
|
src/vendor/symfony/service-contracts/Attribute/Required.php
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service\Attribute;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* A required dependency.
|
16 |
-
*
|
17 |
-
* This attribute indicates that a property holds a required dependency. The annotated property or method should be
|
18 |
-
* considered during the instantiation process of the containing class.
|
19 |
-
*
|
20 |
-
* @author Alexander M. Turek <me@derrabus.de>
|
21 |
-
*/
|
22 |
-
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
|
23 |
-
final class Required
|
24 |
-
{
|
25 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/Attribute/SubscribedService.php
DELETED
@@ -1,33 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service\Attribute;
|
13 |
-
|
14 |
-
use Symfony\Contracts\Service\ServiceSubscriberTrait;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Use with {@see ServiceSubscriberTrait} to mark a method's return type
|
18 |
-
* as a subscribed service.
|
19 |
-
*
|
20 |
-
* @author Kevin Bond <kevinbond@gmail.com>
|
21 |
-
*/
|
22 |
-
#[\Attribute(\Attribute::TARGET_METHOD)]
|
23 |
-
final class SubscribedService
|
24 |
-
{
|
25 |
-
/**
|
26 |
-
* @param string|null $key The key to use for the service
|
27 |
-
* If null, use "ClassName::methodName"
|
28 |
-
*/
|
29 |
-
public function __construct(
|
30 |
-
public ?string $key = null
|
31 |
-
) {
|
32 |
-
}
|
33 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/CHANGELOG.md
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
CHANGELOG
|
2 |
-
=========
|
3 |
-
|
4 |
-
The changelog is maintained for all Symfony contracts at the following URL:
|
5 |
-
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/README.md
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
Symfony Service Contracts
|
2 |
-
=========================
|
3 |
-
|
4 |
-
A set of abstractions extracted out of the Symfony components.
|
5 |
-
|
6 |
-
Can be used to build on semantics that the Symfony components proved useful - and
|
7 |
-
that already have battle tested implementations.
|
8 |
-
|
9 |
-
See https://github.com/symfony/contracts/blob/main/README.md for more information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/ResetInterface.php
DELETED
@@ -1,30 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Provides a way to reset an object to its initial state.
|
16 |
-
*
|
17 |
-
* When calling the "reset()" method on an object, it should be put back to its
|
18 |
-
* initial state. This usually means clearing any internal buffers and forwarding
|
19 |
-
* the call to internal dependencies. All properties of the object should be put
|
20 |
-
* back to the same state it had when it was first ready to use.
|
21 |
-
*
|
22 |
-
* This method could be called, for example, to recycle objects that are used as
|
23 |
-
* services, so that they can be used to handle several requests in the same
|
24 |
-
* process loop (note that we advise making your services stateless instead of
|
25 |
-
* implementing this interface when possible.)
|
26 |
-
*/
|
27 |
-
interface ResetInterface
|
28 |
-
{
|
29 |
-
public function reset();
|
30 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/ServiceLocatorTrait.php
DELETED
@@ -1,128 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service;
|
13 |
-
|
14 |
-
use Psr\Container\ContainerExceptionInterface;
|
15 |
-
use Psr\Container\NotFoundExceptionInterface;
|
16 |
-
|
17 |
-
// Help opcache.preload discover always-needed symbols
|
18 |
-
class_exists(ContainerExceptionInterface::class);
|
19 |
-
class_exists(NotFoundExceptionInterface::class);
|
20 |
-
|
21 |
-
/**
|
22 |
-
* A trait to help implement ServiceProviderInterface.
|
23 |
-
*
|
24 |
-
* @author Robin Chalas <robin.chalas@gmail.com>
|
25 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
26 |
-
*/
|
27 |
-
trait ServiceLocatorTrait
|
28 |
-
{
|
29 |
-
private $factories;
|
30 |
-
private $loading = [];
|
31 |
-
private $providedTypes;
|
32 |
-
|
33 |
-
/**
|
34 |
-
* @param callable[] $factories
|
35 |
-
*/
|
36 |
-
public function __construct(array $factories)
|
37 |
-
{
|
38 |
-
$this->factories = $factories;
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* {@inheritdoc}
|
43 |
-
*
|
44 |
-
* @return bool
|
45 |
-
*/
|
46 |
-
public function has(string $id)
|
47 |
-
{
|
48 |
-
return isset($this->factories[$id]);
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* {@inheritdoc}
|
53 |
-
*
|
54 |
-
* @return mixed
|
55 |
-
*/
|
56 |
-
public function get(string $id)
|
57 |
-
{
|
58 |
-
if (!isset($this->factories[$id])) {
|
59 |
-
throw $this->createNotFoundException($id);
|
60 |
-
}
|
61 |
-
|
62 |
-
if (isset($this->loading[$id])) {
|
63 |
-
$ids = array_values($this->loading);
|
64 |
-
$ids = \array_slice($this->loading, array_search($id, $ids));
|
65 |
-
$ids[] = $id;
|
66 |
-
|
67 |
-
throw $this->createCircularReferenceException($id, $ids);
|
68 |
-
}
|
69 |
-
|
70 |
-
$this->loading[$id] = $id;
|
71 |
-
try {
|
72 |
-
return $this->factories[$id]($this);
|
73 |
-
} finally {
|
74 |
-
unset($this->loading[$id]);
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* {@inheritdoc}
|
80 |
-
*/
|
81 |
-
public function getProvidedServices(): array
|
82 |
-
{
|
83 |
-
if (null === $this->providedTypes) {
|
84 |
-
$this->providedTypes = [];
|
85 |
-
|
86 |
-
foreach ($this->factories as $name => $factory) {
|
87 |
-
if (!\is_callable($factory)) {
|
88 |
-
$this->providedTypes[$name] = '?';
|
89 |
-
} else {
|
90 |
-
$type = (new \ReflectionFunction($factory))->getReturnType();
|
91 |
-
|
92 |
-
$this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?';
|
93 |
-
}
|
94 |
-
}
|
95 |
-
}
|
96 |
-
|
97 |
-
return $this->providedTypes;
|
98 |
-
}
|
99 |
-
|
100 |
-
private function createNotFoundException(string $id): NotFoundExceptionInterface
|
101 |
-
{
|
102 |
-
if (!$alternatives = array_keys($this->factories)) {
|
103 |
-
$message = 'is empty...';
|
104 |
-
} else {
|
105 |
-
$last = array_pop($alternatives);
|
106 |
-
if ($alternatives) {
|
107 |
-
$message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last);
|
108 |
-
} else {
|
109 |
-
$message = sprintf('only knows about the "%s" service.', $last);
|
110 |
-
}
|
111 |
-
}
|
112 |
-
|
113 |
-
if ($this->loading) {
|
114 |
-
$message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message);
|
115 |
-
} else {
|
116 |
-
$message = sprintf('Service "%s" not found: the current service locator %s', $id, $message);
|
117 |
-
}
|
118 |
-
|
119 |
-
return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface {
|
120 |
-
};
|
121 |
-
}
|
122 |
-
|
123 |
-
private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface
|
124 |
-
{
|
125 |
-
return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface {
|
126 |
-
};
|
127 |
-
}
|
128 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/ServiceProviderInterface.php
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service;
|
13 |
-
|
14 |
-
use Psr\Container\ContainerInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* A ServiceProviderInterface exposes the identifiers and the types of services provided by a container.
|
18 |
-
*
|
19 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
20 |
-
* @author Mateusz Sip <mateusz.sip@gmail.com>
|
21 |
-
*/
|
22 |
-
interface ServiceProviderInterface extends ContainerInterface
|
23 |
-
{
|
24 |
-
/**
|
25 |
-
* Returns an associative array of service types keyed by the identifiers provided by the current container.
|
26 |
-
*
|
27 |
-
* Examples:
|
28 |
-
*
|
29 |
-
* * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface
|
30 |
-
* * ['foo' => '?'] means the container provides service name "foo" of unspecified type
|
31 |
-
* * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null
|
32 |
-
*
|
33 |
-
* @return string[] The provided service types, keyed by service names
|
34 |
-
*/
|
35 |
-
public function getProvidedServices(): array;
|
36 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/ServiceSubscriberInterface.php
DELETED
@@ -1,53 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
|
16 |
-
*
|
17 |
-
* The getSubscribedServices method returns an array of service types required by such instances,
|
18 |
-
* optionally keyed by the service names used internally. Service types that start with an interrogation
|
19 |
-
* mark "?" are optional, while the other ones are mandatory service dependencies.
|
20 |
-
*
|
21 |
-
* The injected service locators SHOULD NOT allow access to any other services not specified by the method.
|
22 |
-
*
|
23 |
-
* It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
|
24 |
-
* This interface does not dictate any injection method for these service locators, although constructor
|
25 |
-
* injection is recommended.
|
26 |
-
*
|
27 |
-
* @author Nicolas Grekas <p@tchwork.com>
|
28 |
-
*/
|
29 |
-
interface ServiceSubscriberInterface
|
30 |
-
{
|
31 |
-
/**
|
32 |
-
* Returns an array of service types required by such instances, optionally keyed by the service names used internally.
|
33 |
-
*
|
34 |
-
* For mandatory dependencies:
|
35 |
-
*
|
36 |
-
* * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name
|
37 |
-
* internally to fetch a service which must implement Psr\Log\LoggerInterface.
|
38 |
-
* * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name
|
39 |
-
* internally to fetch an iterable of Psr\Log\LoggerInterface instances.
|
40 |
-
* * ['Psr\Log\LoggerInterface'] is a shortcut for
|
41 |
-
* * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface']
|
42 |
-
*
|
43 |
-
* otherwise:
|
44 |
-
*
|
45 |
-
* * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency
|
46 |
-
* * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency
|
47 |
-
* * ['?Psr\Log\LoggerInterface'] is a shortcut for
|
48 |
-
* * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface']
|
49 |
-
*
|
50 |
-
* @return string[] The required service types, optionally keyed by service names
|
51 |
-
*/
|
52 |
-
public static function getSubscribedServices();
|
53 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/ServiceSubscriberTrait.php
DELETED
@@ -1,115 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service;
|
13 |
-
|
14 |
-
use Psr\Container\ContainerInterface;
|
15 |
-
use Symfony\Contracts\Service\Attribute\SubscribedService;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Implementation of ServiceSubscriberInterface that determines subscribed services from
|
19 |
-
* method return types. Service ids are available as "ClassName::methodName".
|
20 |
-
*
|
21 |
-
* @author Kevin Bond <kevinbond@gmail.com>
|
22 |
-
*/
|
23 |
-
trait ServiceSubscriberTrait
|
24 |
-
{
|
25 |
-
/** @var ContainerInterface */
|
26 |
-
protected $container;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* {@inheritdoc}
|
30 |
-
*/
|
31 |
-
public static function getSubscribedServices(): array
|
32 |
-
{
|
33 |
-
static $services;
|
34 |
-
|
35 |
-
if (null !== $services) {
|
36 |
-
return $services;
|
37 |
-
}
|
38 |
-
|
39 |
-
$services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];
|
40 |
-
$attributeOptIn = false;
|
41 |
-
|
42 |
-
if (\PHP_VERSION_ID >= 80000) {
|
43 |
-
foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
|
44 |
-
if (self::class !== $method->getDeclaringClass()->name) {
|
45 |
-
continue;
|
46 |
-
}
|
47 |
-
|
48 |
-
if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) {
|
49 |
-
continue;
|
50 |
-
}
|
51 |
-
|
52 |
-
if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
|
53 |
-
throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
|
54 |
-
}
|
55 |
-
|
56 |
-
if (!$returnType = $method->getReturnType()) {
|
57 |
-
throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
|
58 |
-
}
|
59 |
-
|
60 |
-
$serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
|
61 |
-
|
62 |
-
if ($returnType->allowsNull()) {
|
63 |
-
$serviceId = '?'.$serviceId;
|
64 |
-
}
|
65 |
-
|
66 |
-
$services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId;
|
67 |
-
$attributeOptIn = true;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
-
if (!$attributeOptIn) {
|
72 |
-
foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
|
73 |
-
if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
|
74 |
-
continue;
|
75 |
-
}
|
76 |
-
|
77 |
-
if (self::class !== $method->getDeclaringClass()->name) {
|
78 |
-
continue;
|
79 |
-
}
|
80 |
-
|
81 |
-
if (!($returnType = $method->getReturnType()) instanceof \ReflectionNamedType) {
|
82 |
-
continue;
|
83 |
-
}
|
84 |
-
|
85 |
-
if ($returnType->isBuiltin()) {
|
86 |
-
continue;
|
87 |
-
}
|
88 |
-
|
89 |
-
if (\PHP_VERSION_ID >= 80000) {
|
90 |
-
trigger_deprecation('symfony/service-contracts', '2.5', 'Using "%s" in "%s" without using the "%s" attribute on any method is deprecated.', ServiceSubscriberTrait::class, self::class, SubscribedService::class);
|
91 |
-
}
|
92 |
-
|
93 |
-
$services[self::class.'::'.$method->name] = '?'.($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType);
|
94 |
-
}
|
95 |
-
}
|
96 |
-
|
97 |
-
return $services;
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* @required
|
102 |
-
*
|
103 |
-
* @return ContainerInterface|null
|
104 |
-
*/
|
105 |
-
public function setContainer(ContainerInterface $container)
|
106 |
-
{
|
107 |
-
$this->container = $container;
|
108 |
-
|
109 |
-
if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) {
|
110 |
-
return parent::setContainer($container);
|
111 |
-
}
|
112 |
-
|
113 |
-
return null;
|
114 |
-
}
|
115 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php
DELETED
@@ -1,95 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
* This file is part of the Symfony package.
|
5 |
-
*
|
6 |
-
* (c) Fabien Potencier <fabien@symfony.com>
|
7 |
-
*
|
8 |
-
* For the full copyright and license information, please view the LICENSE
|
9 |
-
* file that was distributed with this source code.
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace Symfony\Contracts\Service\Test;
|
13 |
-
|
14 |
-
use PHPUnit\Framework\TestCase;
|
15 |
-
use Psr\Container\ContainerInterface;
|
16 |
-
use Symfony\Contracts\Service\ServiceLocatorTrait;
|
17 |
-
|
18 |
-
abstract class ServiceLocatorTest extends TestCase
|
19 |
-
{
|
20 |
-
/**
|
21 |
-
* @return ContainerInterface
|
22 |
-
*/
|
23 |
-
protected function getServiceLocator(array $factories)
|
24 |
-
{
|
25 |
-
return new class($factories) implements ContainerInterface {
|
26 |
-
use ServiceLocatorTrait;
|
27 |
-
};
|
28 |
-
}
|
29 |
-
|
30 |
-
public function testHas()
|
31 |
-
{
|
32 |
-
$locator = $this->getServiceLocator([
|
33 |
-
'foo' => function () { return 'bar'; },
|
34 |
-
'bar' => function () { return 'baz'; },
|
35 |
-
function () { return 'dummy'; },
|
36 |
-
]);
|
37 |
-
|
38 |
-
$this->assertTrue($locator->has('foo'));
|
39 |
-
$this->assertTrue($locator->has('bar'));
|
40 |
-
$this->assertFalse($locator->has('dummy'));
|
41 |
-
}
|
42 |
-
|
43 |
-
public function testGet()
|
44 |
-
{
|
45 |
-
$locator = $this->getServiceLocator([
|
46 |
-
'foo' => function () { return 'bar'; },
|
47 |
-
'bar' => function () { return 'baz'; },
|
48 |
-
]);
|
49 |
-
|
50 |
-
$this->assertSame('bar', $locator->get('foo'));
|
51 |
-
$this->assertSame('baz', $locator->get('bar'));
|
52 |
-
}
|
53 |
-
|
54 |
-
public function testGetDoesNotMemoize()
|
55 |
-
{
|
56 |
-
$i = 0;
|
57 |
-
$locator = $this->getServiceLocator([
|
58 |
-
'foo' => function () use (&$i) {
|
59 |
-
++$i;
|
60 |
-
|
61 |
-
return 'bar';
|
62 |
-
},
|
63 |
-
]);
|
64 |
-
|
65 |
-
$this->assertSame('bar', $locator->get('foo'));
|
66 |
-
$this->assertSame('bar', $locator->get('foo'));
|
67 |
-
$this->assertSame(2, $i);
|
68 |
-
}
|
69 |
-
|
70 |
-
public function testThrowsOnUndefinedInternalService()
|
71 |
-
{
|
72 |
-
if (!$this->getExpectedException()) {
|
73 |
-
$this->expectException(\Psr\Container\NotFoundExceptionInterface::class);
|
74 |
-
$this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.');
|
75 |
-
}
|
76 |
-
$locator = $this->getServiceLocator([
|
77 |
-
'foo' => function () use (&$locator) { return $locator->get('bar'); },
|
78 |
-
]);
|
79 |
-
|
80 |
-
$locator->get('foo');
|
81 |
-
}
|
82 |
-
|
83 |
-
public function testThrowsOnCircularReference()
|
84 |
-
{
|
85 |
-
$this->expectException(\Psr\Container\ContainerExceptionInterface::class);
|
86 |
-
$this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".');
|
87 |
-
$locator = $this->getServiceLocator([
|
88 |
-
'foo' => function () use (&$locator) { return $locator->get('bar'); },
|
89 |
-
'bar' => function () use (&$locator) { return $locator->get('baz'); },
|
90 |
-
'baz' => function () use (&$locator) { return $locator->get('bar'); },
|
91 |
-
]);
|
92 |
-
|
93 |
-
$locator->get('foo');
|
94 |
-
}
|
95 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/vendor/symfony/service-contracts/composer.json
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "symfony/service-contracts",
|
3 |
-
"type": "library",
|
4 |
-
"description": "Generic abstractions related to writing services",
|
5 |
-
"keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
|
6 |
-
"homepage": "https://symfony.com",
|
7 |
-
"license": "MIT",
|
8 |
-
"authors": [
|
9 |
-
{
|
10 |
-
"name": "Nicolas Grekas",
|
11 |
-
"email": "p@tchwork.com"
|
12 |
-
},
|
13 |
-
{
|
14 |
-
"name": "Symfony Community",
|
15 |
-
"homepage": "https://symfony.com/contributors"
|
16 |
-
}
|
17 |
-
],
|
18 |
-
"require": {
|
19 |
-
"php": ">=7.2.5",
|
20 |
-
"psr/container": "^1.1",
|
21 |
-
"symfony/deprecation-contracts": "^2.1|^3"
|
22 |
-
},
|
23 |
-
"conflict": {
|
24 |
-
"ext-psr": "<1.1|>=2"
|
25 |
-
},
|
26 |
-
"suggest": {
|
27 |
-
"symfony/service-implementation": ""
|
28 |
-
},
|
29 |
-
"autoload": {
|
30 |
-
"psr-4": { "Symfony\\Contracts\\Service\\": "" }
|
31 |
-
},
|
32 |
-
"minimum-stability": "dev",
|
33 |
-
"extra": {
|
34 |
-
"branch-alias": {
|
35 |
-
"dev-main": "2.5-dev"
|
36 |
-
},
|
37 |
-
"thanks": {
|
38 |
-
"name": "symfony/contracts",
|
39 |
-
"url": "https://github.com/symfony/contracts"
|
40 |
-
}
|
41 |
-
}
|
42 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|