Version Description
- 11-10-2018 =
IMPORTANT This version requires PHP 5.6 or higher. If you are using an older PHP version, please read this article: PHP & Mollie API v2.
- New - Now supports Klarna Pay later and Klara Slice it, read more
- New - Implemented support for the new Orders API
- New - Tested with and updated for WooCommerce 3.5 beta compatibility
New - EPS, GiroPay: implemented support for SEPA first payments (recurring payments)
Fix - Fixed issue with Guzzle and PhpScoper
Fix - WooCommerce emails: make sure "Payment completed by..." message is only shown once per email
Fix - WooCommerce Subscriptions: add support for "Accept Manual Renewals". This enables Bank Transfer and PayPal in checkout for subscription products.
Fix - Mollie payment gateways weren't always shows when cart was empty.
Fix - Fix for "Link expired" message after refresh methods in WooCommerce settings
Fix - Stricter check for valid API key when individual gateways are loaded
Fix - Added new action hook in Mollie_WC_Gateway_Abstract::getReturnRedirectUrlForOrder()
Fix - Improve log messages for orderNeedsPayment check, old messages where confusing to merchants
Fix - Update VVV giftcard logo filename
Release Info
Developer | davdebcom |
Plugin | Mollie Payments for WooCommerce |
Version | 5.0.1 |
Comparing to | |
See all releases |
Code changes from version 5.0.0 to 5.0.1
- includes/mollie-api-php/composer.json +74 -74
- includes/mollie-api-php/composer.lock +5 -5
- includes/mollie-api-php/examples/01-new-payment.php +29 -13
- includes/mollie-api-php/examples/02-webhook-verification.php +11 -8
- includes/mollie-api-php/examples/03-return-page.php +12 -10
- includes/mollie-api-php/examples/04-ideal-payment.php +37 -14
- includes/mollie-api-php/examples/05-payments-history.php +30 -16
- includes/mollie-api-php/examples/06-list-activated-methods.php +4 -6
- includes/mollie-api-php/examples/07-refund-payment.php +23 -13
- includes/mollie-api-php/examples/08-oauth-list-profiles.php +11 -8
- includes/mollie-api-php/examples/09-oauth-list-settlements.php +18 -20
- includes/mollie-api-php/examples/10-oauth-new-payment.php +34 -21
- includes/mollie-api-php/examples/11-new-customer.php +11 -7
- includes/mollie-api-php/examples/12-new-customer-payment.php +29 -17
- includes/mollie-api-php/examples/13-customer-payments-history.php +21 -14
- includes/mollie-api-php/examples/14-recurring-first-payment.php +23 -16
- includes/mollie-api-php/examples/15-recurring-payment.php +24 -17
- includes/mollie-api-php/examples/16-recurring-subscription.php +19 -14
- includes/mollie-api-php/examples/17-cancel-subscription.php +4 -6
- includes/mollie-api-php/examples/18-update-customer.php +6 -7
- includes/mollie-api-php/examples/19-update-profile.php +10 -10
- includes/mollie-api-php/examples/20-list-invoices.php +15 -15
- includes/mollie-api-php/examples/22-create-mandate-subscription.php +27 -16
- includes/mollie-api-php/examples/23-delete-customer.php +4 -4
- includes/mollie-api-php/examples/24-revoke-mandate.php +7 -4
- includes/mollie-api-php/examples/25-update-subscription.php +10 -8
- includes/mollie-api-php/examples/26-new-order.php +86 -6
- includes/mollie-api-php/examples/27-handle-order-status-change.php +4 -4
- includes/mollie-api-php/examples/28-cancel-order.php +3 -4
- includes/mollie-api-php/examples/29-list-orders.php +16 -13
- includes/mollie-api-php/examples/30-cancel-order-line.php +14 -5
- includes/mollie-api-php/examples/31-ship-order-completely.php +6 -5
- includes/mollie-api-php/examples/32-ship-order-partially.php +20 -6
- includes/mollie-api-php/examples/33-get-shipment.php +6 -5
- includes/mollie-api-php/examples/34-list-order-shipments.php +5 -4
- includes/mollie-api-php/examples/35-refund-order-completely.php +5 -4
- includes/mollie-api-php/examples/36-refund-order-partially.php +14 -5
- includes/mollie-api-php/examples/37-update-shipment-tracking.php +13 -6
- includes/mollie-api-php/examples/38-retrieve-capture.php +6 -4
- includes/mollie-api-php/examples/39-list-payment-captures.php +5 -4
- includes/mollie-api-php/examples/initialize.php +5 -6
- includes/mollie-api-php/examples/initialize_with_oauth.php +6 -6
- includes/mollie-api-php/examples/orders/.gitignore +1 -0
- includes/mollie-api-php/src/CompatibilityChecker.php +20 -8
- includes/mollie-api-php/src/Endpoints/CustomerEndpoint.php +10 -3
- includes/mollie-api-php/src/Endpoints/CustomerPaymentsEndpoint.php +13 -6
- includes/mollie-api-php/src/Endpoints/EndpointAbstract.php +75 -30
- includes/mollie-api-php/src/Endpoints/InvoiceEndpoint.php +11 -5
- includes/mollie-api-php/src/Endpoints/MandateEndpoint.php +19 -8
- includes/mollie-api-php/src/Endpoints/MethodEndpoint.php +10 -4
- includes/mollie-api-php/src/Endpoints/OrderEndpoint.php +14 -5
- includes/mollie-api-php/src/Endpoints/OrderLineEndpoint.php +18 -7
- includes/mollie-api-php/src/Endpoints/OrderRefundEndpoint.php +8 -4
- includes/mollie-api-php/src/Endpoints/OrganizationEndpoint.php +11 -4
- includes/mollie-api-php/src/Endpoints/PaymentCaptureEndpoint.php +9 -4
- includes/mollie-api-php/src/Endpoints/PaymentChargebackEndpoint.php +9 -4
- includes/mollie-api-php/src/Endpoints/PaymentEndpoint.php +24 -10
- includes/mollie-api-php/src/Endpoints/PaymentRefundEndpoint.php +9 -4
- includes/mollie-api-php/src/Endpoints/PermissionEndpoint.php +8 -3
- includes/mollie-api-php/src/Endpoints/ProfileEndpoint.php +14 -5
- includes/mollie-api-php/src/Endpoints/RefundEndpoint.php +7 -3
- includes/mollie-api-php/src/Endpoints/SettlementsEndpoint.php +12 -5
- includes/mollie-api-php/src/Endpoints/ShipmentEndpoint.php +15 -6
- includes/mollie-api-php/src/Endpoints/SubscriptionEndpoint.php +19 -8
- includes/mollie-api-php/src/Exceptions/ApiException.php +10 -2
- includes/mollie-api-php/src/Exceptions/IncompatiblePlatform.php +1 -1
- includes/mollie-api-php/src/MollieApiClient.php +138 -57
- includes/mollie-api-php/src/Resources/BaseCollection.php +4 -1
- includes/mollie-api-php/src/Resources/BaseResource.php +4 -2
- includes/mollie-api-php/src/Resources/Capture.php +10 -1
- includes/mollie-api-php/src/Resources/CaptureCollection.php +3 -2
- includes/mollie-api-php/src/Resources/Chargeback.php +7 -1
- includes/mollie-api-php/src/Resources/ChargebackCollection.php +4 -3
- includes/mollie-api-php/src/Resources/CursorCollection.php +24 -10
- includes/mollie-api-php/src/Resources/Customer.php +42 -9
- includes/mollie-api-php/src/Resources/CustomerCollection.php +4 -3
- includes/mollie-api-php/src/Resources/Invoice.php +21 -5
- includes/mollie-api-php/src/Resources/InvoiceCollection.php +4 -3
- includes/mollie-api-php/src/Resources/Issuer.php +5 -2
- includes/mollie-api-php/src/Resources/IssuerCollection.php +2 -2
- includes/mollie-api-php/src/Resources/Mandate.php +33 -8
- includes/mollie-api-php/src/Resources/MandateCollection.php +4 -3
- includes/mollie-api-php/src/Resources/Method.php +9 -3
- includes/mollie-api-php/src/Resources/MethodCollection.php +1 -1
- includes/mollie-api-php/src/Resources/Order.php +64 -15
- includes/mollie-api-php/src/Resources/OrderCollection.php +3 -2
- includes/mollie-api-php/src/Resources/OrderLine.php +47 -15
- includes/mollie-api-php/src/Resources/OrderLineCollection.php +2 -1
- includes/mollie-api-php/src/Resources/Organization.php +6 -1
- includes/mollie-api-php/src/Resources/OrganizationCollection.php +3 -2
- includes/mollie-api-php/src/Resources/Payment.php +145 -31
- includes/mollie-api-php/src/Resources/PaymentCollection.php +3 -2
- includes/mollie-api-php/src/Resources/Permission.php +5 -1
- includes/mollie-api-php/src/Resources/PermissionCollection.php +1 -1
- includes/mollie-api-php/src/Resources/Profile.php +66 -24
- includes/mollie-api-php/src/Resources/ProfileCollection.php +5 -3
- includes/mollie-api-php/src/Resources/Refund.php +26 -6
- includes/mollie-api-php/src/Resources/RefundCollection.php +3 -2
- includes/mollie-api-php/src/Resources/ResourceFactory.php +4 -2
- includes/mollie-api-php/src/Resources/Settlement.php +43 -18
- includes/mollie-api-php/src/Resources/SettlementCollection.php +4 -3
- includes/mollie-api-php/src/Resources/Shipment.php +30 -6
- includes/mollie-api-php/src/Resources/ShipmentCollection.php +1 -1
- includes/mollie-api-php/src/Resources/Subscription.php +60 -13
- includes/mollie-api-php/src/Resources/SubscriptionCollection.php +5 -3
- includes/mollie-api-php/src/Types/InvoiceStatus.php +3 -1
- includes/mollie-api-php/src/Types/MandateMethod.php +1 -1
- includes/mollie-api-php/src/Types/MandateStatus.php +2 -2
- includes/mollie-api-php/src/Types/OrderLineStatus.php +6 -0
- includes/mollie-api-php/src/Types/OrderStatus.php +7 -0
- includes/mollie-api-php/src/Types/PaymentMethod.php +17 -0
- includes/mollie-api-php/src/Types/PaymentStatus.php +6 -0
- includes/mollie-api-php/src/Types/ProfileStatus.php +3 -1
- includes/mollie-api-php/src/Types/RefundStatus.php +3 -0
- includes/mollie-api-php/src/Types/SettlementStatus.php +3 -0
- includes/mollie-api-php/src/Types/SubscriptionStatus.php +5 -7
- includes/mollie-api-php/vendor/autoload.php +1 -1
- includes/mollie-api-php/vendor/composer-autoload.php +0 -7
- includes/mollie-api-php/vendor/composer/autoload_psr4.php +5 -5
- includes/mollie-api-php/vendor/composer/autoload_real.php +7 -7
- includes/mollie-api-php/vendor/composer/autoload_static.php +24 -18
- includes/mollie-api-php/vendor/composer/ca-bundle/composer.json +10 -10
- includes/mollie-api-php/vendor/composer/ca-bundle/src/CaBundle.php +120 -72
- includes/mollie-api-php/vendor/composer/installed.json +5 -5
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/composer.json +13 -23
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Client.php +144 -69
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/ClientInterface.php +13 -8
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +119 -50
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +14 -6
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +22 -15
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +15 -10
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +97 -37
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php +15 -7
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php +2 -5
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php +12 -6
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php +2 -5
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +74 -22
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php +6 -4
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php +2 -5
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +2 -5
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php +2 -5
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +272 -132
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php +5 -4
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php +15 -9
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +73 -34
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php +38 -13
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php +89 -52
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php +20 -11
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +280 -124
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/HandlerStack.php +60 -26
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/MessageFormatter.php +114 -85
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Middleware.php +88 -55
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/Pool.php +37 -20
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php +32 -12
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php +122 -45
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/RequestOptions.php +29 -2
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php +48 -20
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/TransferStats.php +23 -7
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/UriTemplate.php +77 -31
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/functions.php +92 -53
- includes/mollie-api-php/vendor/guzzlehttp/guzzle/src/functions_include.php +1 -3
- includes/mollie-api-php/vendor/guzzlehttp/promises/composer.json +9 -13
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/AggregateException.php +6 -4
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/CancellationException.php +2 -3
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/Coroutine.php +28 -12
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/EachPromise.php +77 -38
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/FulfilledPromise.php +23 -10
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/Promise.php +81 -32
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/PromiseInterface.php +13 -4
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/PromisorInterface.php +1 -2
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/RejectedPromise.php +23 -10
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/RejectionException.php +11 -4
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/TaskQueue.php +14 -10
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/TaskQueueInterface.php +3 -2
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/functions.php +140 -70
- includes/mollie-api-php/vendor/guzzlehttp/promises/src/functions_include.php +1 -3
- includes/mollie-api-php/vendor/guzzlehttp/psr7/composer.json +10 -20
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/AppendStream.php +58 -21
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/BufferStream.php +37 -15
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/CachingStream.php +41 -18
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/DroppingStream.php +12 -6
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/FnStream.php +49 -24
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/InflateStream.php +15 -11
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/LazyOpenStream.php +7 -3
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/LimitStream.php +41 -14
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/MessageTrait.php +51 -18
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/MultipartStream.php +45 -15
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/NoSeekStream.php +7 -5
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/PumpStream.php +39 -14
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/Request.php +45 -15
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/Response.php +81 -7
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/ServerRequest.php +101 -32
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/Stream.php +84 -27
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php +28 -7
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/StreamWrapper.php +52 -13
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/UploadedFile.php +111 -39
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/Uri.php +205 -58
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/UriNormalizer.php +55 -18
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/UriResolver.php +54 -25
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/functions.php +324 -110
- includes/mollie-api-php/vendor/guzzlehttp/psr7/src/functions_include.php +1 -3
- includes/mollie-api-php/vendor/psr/http-message/composer.json +6 -13
- includes/mollie-api-php/vendor/psr/http-message/src/MessageInterface.php +12 -2
- includes/mollie-api-php/vendor/psr/http-message/src/RequestInterface.php +8 -3
- includes/mollie-api-php/vendor/psr/http-message/src/ResponseInterface.php +4 -2
- includes/mollie-api-php/vendor/psr/http-message/src/ServerRequestInterface.php +14 -2
- includes/mollie-api-php/vendor/psr/http-message/src/StreamInterface.php +16 -2
- includes/mollie-api-php/vendor/psr/http-message/src/UploadedFileInterface.php +6 -1
- includes/mollie-api-php/vendor/psr/http-message/src/UriInterface.php +16 -2
- includes/mollie/wc/plugin.php +1 -1
- mollie-payments-for-woocommerce.php +1 -1
- readme.txt +6 -4
@@ -1,76 +1,76 @@
|
|
1 |
{
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
}
|
47 |
-
],
|
48 |
-
"require": {
|
49 |
-
"php": ">=5.6",
|
50 |
-
"ext-curl": "*",
|
51 |
-
"ext-json": "*",
|
52 |
-
"ext-openssl": "*",
|
53 |
-
"composer\/ca-bundle": "^1.1",
|
54 |
-
"guzzlehttp\/guzzle": "^6.3"
|
55 |
-
},
|
56 |
-
"require-dev": {
|
57 |
-
"eloquent\/liberator": "^2.0",
|
58 |
-
"phpunit\/phpunit": "^5.7 || ^6.5 || ^7.1"
|
59 |
-
},
|
60 |
-
"suggest": {
|
61 |
-
"mollie\/oauth2-mollie-php": "Use OAuth to authenticate with the Mollie API. This is needed for some endpoints. Visit https:\/\/docs.mollie.com\/ for more information."
|
62 |
-
},
|
63 |
-
"config": {
|
64 |
-
"sort-packages": true
|
65 |
-
},
|
66 |
-
"autoload": {
|
67 |
-
"psr-4": {
|
68 |
-
"Mollie\\Api\\": "src\/"
|
69 |
-
}
|
70 |
-
},
|
71 |
-
"autoload-dev": {
|
72 |
-
"psr-4": {
|
73 |
-
"_PhpScoper5bbb1f4b001f3\\Tests\\": "tests"
|
74 |
-
}
|
75 |
}
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
{
|
2 |
+
"name": "mollie/mollie-api-php",
|
3 |
+
"description": "Mollie API client library for PHP. Mollie is a European Payment Service provider and offers international payment methods such as Mastercard, VISA, American Express and PayPal, and local payment methods such as iDEAL, Bancontact, SOFORT Banking, SEPA direct debit, Belfius Direct Net, KBC Payment Button and various gift cards such as Podiumcadeaukaart and fashioncheque.",
|
4 |
+
"keywords": [
|
5 |
+
"mollie",
|
6 |
+
"payment",
|
7 |
+
"service",
|
8 |
+
"ideal",
|
9 |
+
"creditcard",
|
10 |
+
"mistercash",
|
11 |
+
"bancontact",
|
12 |
+
"sofort",
|
13 |
+
"sofortbanking",
|
14 |
+
"sepa",
|
15 |
+
"bitcoin",
|
16 |
+
"paypal",
|
17 |
+
"paysafecard",
|
18 |
+
"podiumcadeaukaart",
|
19 |
+
"banktransfer",
|
20 |
+
"direct debit",
|
21 |
+
"belfius",
|
22 |
+
"belfius direct net",
|
23 |
+
"refunds",
|
24 |
+
"api",
|
25 |
+
"payments",
|
26 |
+
"gateway",
|
27 |
+
"subscriptions",
|
28 |
+
"recurring",
|
29 |
+
"charges",
|
30 |
+
"kbc",
|
31 |
+
"cbc",
|
32 |
+
"gift cards",
|
33 |
+
"intersolve",
|
34 |
+
"fashioncheque",
|
35 |
+
"inghomepay",
|
36 |
+
"klarna",
|
37 |
+
"paylater",
|
38 |
+
"sliceit"
|
39 |
+
],
|
40 |
+
"homepage": "https://www.mollie.com/en/developers",
|
41 |
+
"license": "BSD-2-Clause",
|
42 |
+
"authors": [
|
43 |
+
{
|
44 |
+
"name": "Mollie B.V.",
|
45 |
+
"email": "info@mollie.com"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
+
],
|
48 |
+
"require": {
|
49 |
+
"php": ">=5.6",
|
50 |
+
"ext-curl": "*",
|
51 |
+
"ext-json": "*",
|
52 |
+
"ext-openssl": "*",
|
53 |
+
"composer/ca-bundle": "^1.1",
|
54 |
+
"guzzlehttp/guzzle": "^6.3"
|
55 |
+
},
|
56 |
+
"require-dev": {
|
57 |
+
"eloquent/liberator": "^2.0",
|
58 |
+
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.1"
|
59 |
+
},
|
60 |
+
"suggest": {
|
61 |
+
"mollie/oauth2-mollie-php": "Use OAuth to authenticate with the Mollie API. This is needed for some endpoints. Visit https://docs.mollie.com/ for more information."
|
62 |
+
},
|
63 |
+
"config": {
|
64 |
+
"sort-packages": true
|
65 |
+
},
|
66 |
+
"autoload": {
|
67 |
+
"psr-4": {
|
68 |
+
"Mollie\\Api\\": "src/"
|
69 |
+
}
|
70 |
+
},
|
71 |
+
"autoload-dev": {
|
72 |
+
"psr-4": {
|
73 |
+
"Tests\\": "tests"
|
74 |
+
}
|
75 |
+
}
|
76 |
+
}
|
@@ -38,7 +38,7 @@
|
|
38 |
},
|
39 |
"autoload": {
|
40 |
"psr-4": {
|
41 |
-
"
|
42 |
}
|
43 |
},
|
44 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -100,7 +100,7 @@
|
|
100 |
"src/functions_include.php"
|
101 |
],
|
102 |
"psr-4": {
|
103 |
-
"
|
104 |
}
|
105 |
},
|
106 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -155,7 +155,7 @@
|
|
155 |
},
|
156 |
"autoload": {
|
157 |
"psr-4": {
|
158 |
-
"
|
159 |
},
|
160 |
"files": [
|
161 |
"src/functions_include.php"
|
@@ -210,7 +210,7 @@
|
|
210 |
},
|
211 |
"autoload": {
|
212 |
"psr-4": {
|
213 |
-
"
|
214 |
},
|
215 |
"files": [
|
216 |
"src/functions_include.php"
|
@@ -268,7 +268,7 @@
|
|
268 |
},
|
269 |
"autoload": {
|
270 |
"psr-4": {
|
271 |
-
"
|
272 |
}
|
273 |
},
|
274 |
"notification-url": "https://packagist.org/downloads/",
|
38 |
},
|
39 |
"autoload": {
|
40 |
"psr-4": {
|
41 |
+
"Composer\\CaBundle\\": "src"
|
42 |
}
|
43 |
},
|
44 |
"notification-url": "https://packagist.org/downloads/",
|
100 |
"src/functions_include.php"
|
101 |
],
|
102 |
"psr-4": {
|
103 |
+
"GuzzleHttp\\": "src/"
|
104 |
}
|
105 |
},
|
106 |
"notification-url": "https://packagist.org/downloads/",
|
155 |
},
|
156 |
"autoload": {
|
157 |
"psr-4": {
|
158 |
+
"GuzzleHttp\\Promise\\": "src/"
|
159 |
},
|
160 |
"files": [
|
161 |
"src/functions_include.php"
|
210 |
},
|
211 |
"autoload": {
|
212 |
"psr-4": {
|
213 |
+
"GuzzleHttp\\Psr7\\": "src/"
|
214 |
},
|
215 |
"files": [
|
216 |
"src/functions_include.php"
|
268 |
},
|
269 |
"autoload": {
|
270 |
"psr-4": {
|
271 |
+
"Psr\\Http\\Message\\": "src/"
|
272 |
}
|
273 |
},
|
274 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* How to prepare a new payment with the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key.
|
@@ -12,17 +10,20 @@ try {
|
|
12 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
13 |
*/
|
14 |
require "./initialize.php";
|
|
|
15 |
/*
|
16 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
17 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
18 |
*/
|
19 |
-
$orderId =
|
|
|
20 |
/*
|
21 |
* Determine the url parts to these example files.
|
22 |
*/
|
23 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
24 |
$hostname = $_SERVER['HTTP_HOST'];
|
25 |
-
$path =
|
|
|
26 |
/*
|
27 |
* Payment parameters:
|
28 |
* amount Amount in EUROs. This example creates a € 10,- payment.
|
@@ -31,25 +32,40 @@ try {
|
|
31 |
* webhookUrl Webhook location, used to report when the payment changes state.
|
32 |
* metadata Custom metadata that is stored with the payment.
|
33 |
*/
|
34 |
-
$payment = $mollie->payments->create([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
/*
|
36 |
* In this example we store the order with its payment status in a database.
|
37 |
*/
|
38 |
-
|
|
|
39 |
/*
|
40 |
* Send the customer off to complete the payment.
|
41 |
* This request should always be a GET, thus we enforce 303 http response code
|
42 |
*/
|
43 |
-
|
44 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
45 |
-
echo "API call failed: " .
|
46 |
}
|
|
|
47 |
/*
|
48 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
49 |
*/
|
50 |
function database_write($orderId, $status)
|
51 |
{
|
52 |
-
$orderId =
|
53 |
-
$database =
|
54 |
-
|
|
|
55 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* How to prepare a new payment with the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key.
|
10 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
11 |
*/
|
12 |
require "./initialize.php";
|
13 |
+
|
14 |
/*
|
15 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
16 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
17 |
*/
|
18 |
+
$orderId = time();
|
19 |
+
|
20 |
/*
|
21 |
* Determine the url parts to these example files.
|
22 |
*/
|
23 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
24 |
$hostname = $_SERVER['HTTP_HOST'];
|
25 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
26 |
+
|
27 |
/*
|
28 |
* Payment parameters:
|
29 |
* amount Amount in EUROs. This example creates a € 10,- payment.
|
32 |
* webhookUrl Webhook location, used to report when the payment changes state.
|
33 |
* metadata Custom metadata that is stored with the payment.
|
34 |
*/
|
35 |
+
$payment = $mollie->payments->create([
|
36 |
+
"amount" => [
|
37 |
+
"currency" => "EUR",
|
38 |
+
"value" => "10.00" // You must send the correct number of decimals, thus we enforce the use of strings
|
39 |
+
],
|
40 |
+
"description" => "Order #{$orderId}",
|
41 |
+
"redirectUrl" => "{$protocol}://{$hostname}{$path}/03-return-page.php?order_id={$orderId}",
|
42 |
+
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
43 |
+
"metadata" => [
|
44 |
+
"order_id" => $orderId,
|
45 |
+
],
|
46 |
+
]);
|
47 |
+
|
48 |
/*
|
49 |
* In this example we store the order with its payment status in a database.
|
50 |
*/
|
51 |
+
database_write($orderId, $payment->status);
|
52 |
+
|
53 |
/*
|
54 |
* Send the customer off to complete the payment.
|
55 |
* This request should always be a GET, thus we enforce 303 http response code
|
56 |
*/
|
57 |
+
header("Location: " . $payment->getCheckoutUrl(), true, 303);
|
58 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
59 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
60 |
}
|
61 |
+
|
62 |
/*
|
63 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
64 |
*/
|
65 |
function database_write($orderId, $status)
|
66 |
{
|
67 |
+
$orderId = intval($orderId);
|
68 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
69 |
+
|
70 |
+
file_put_contents($database, $status);
|
71 |
}
|
@@ -1,12 +1,10 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 2 - How to verify Mollie API Payments in a webhook.
|
7 |
*
|
8 |
* See: https://docs.mollie.com/guides/webhooks
|
9 |
*/
|
|
|
10 |
try {
|
11 |
/*
|
12 |
* Initialize the Mollie API library with your API key.
|
@@ -14,15 +12,18 @@ try {
|
|
14 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
15 |
*/
|
16 |
require "./initialize.php";
|
|
|
17 |
/*
|
18 |
* Retrieve the payment's current state.
|
19 |
*/
|
20 |
$payment = $mollie->payments->get($_POST["id"]);
|
21 |
$orderId = $payment->metadata->order_id;
|
|
|
22 |
/*
|
23 |
* Update the order in the database.
|
24 |
*/
|
25 |
-
|
|
|
26 |
if ($payment->isPaid() && !$payment->hasRefunds() && !$payment->hasChargebacks()) {
|
27 |
/*
|
28 |
* The payment is paid and isn't refunded or charged back.
|
@@ -60,14 +61,16 @@ try {
|
|
60 |
*/
|
61 |
}
|
62 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
63 |
-
echo "API call failed: " .
|
64 |
}
|
|
|
65 |
/*
|
66 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
67 |
*/
|
68 |
function database_write($orderId, $status)
|
69 |
{
|
70 |
-
$orderId =
|
71 |
-
$database =
|
72 |
-
|
|
|
73 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 2 - How to verify Mollie API Payments in a webhook.
|
4 |
*
|
5 |
* See: https://docs.mollie.com/guides/webhooks
|
6 |
*/
|
7 |
+
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key.
|
12 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
13 |
*/
|
14 |
require "./initialize.php";
|
15 |
+
|
16 |
/*
|
17 |
* Retrieve the payment's current state.
|
18 |
*/
|
19 |
$payment = $mollie->payments->get($_POST["id"]);
|
20 |
$orderId = $payment->metadata->order_id;
|
21 |
+
|
22 |
/*
|
23 |
* Update the order in the database.
|
24 |
*/
|
25 |
+
database_write($orderId, $payment->status);
|
26 |
+
|
27 |
if ($payment->isPaid() && !$payment->hasRefunds() && !$payment->hasChargebacks()) {
|
28 |
/*
|
29 |
* The payment is paid and isn't refunded or charged back.
|
61 |
*/
|
62 |
}
|
63 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
64 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
65 |
}
|
66 |
+
|
67 |
/*
|
68 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
69 |
*/
|
70 |
function database_write($orderId, $status)
|
71 |
{
|
72 |
+
$orderId = intval($orderId);
|
73 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
74 |
+
|
75 |
+
file_put_contents($database, $status);
|
76 |
}
|
@@ -1,33 +1,35 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 3 - How to show a return page to the customer.
|
7 |
*
|
8 |
* In this example we retrieve the order stored in the database.
|
9 |
* Here, it's unnecessary to use the Mollie API Client.
|
10 |
*/
|
11 |
-
$status =
|
|
|
12 |
/*
|
13 |
* Determine the url parts to these example files.
|
14 |
*/
|
15 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
16 |
$hostname = $_SERVER['HTTP_HOST'];
|
17 |
-
$path =
|
18 |
-
|
|
|
19 |
echo "<p>";
|
20 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/01-new-payment.php">Create payment with example 1</a><br>';
|
21 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/04-ideal-payment.php">Create iDEAL payment with example 4</a><br>';
|
22 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/05-payments-history.php">List payments with example 5</a><br>';
|
23 |
echo "</p>";
|
|
|
24 |
/*
|
25 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
26 |
*/
|
27 |
function database_read($orderId)
|
28 |
{
|
29 |
-
$orderId =
|
30 |
-
$database =
|
31 |
-
|
|
|
|
|
32 |
return $status ? $status : "unknown order";
|
33 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 3 - How to show a return page to the customer.
|
4 |
*
|
5 |
* In this example we retrieve the order stored in the database.
|
6 |
* Here, it's unnecessary to use the Mollie API Client.
|
7 |
*/
|
8 |
+
$status = database_read($_GET["order_id"]);
|
9 |
+
|
10 |
/*
|
11 |
* Determine the url parts to these example files.
|
12 |
*/
|
13 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
14 |
$hostname = $_SERVER['HTTP_HOST'];
|
15 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
16 |
+
|
17 |
+
echo "<p>Your payment status is '" . htmlspecialchars($status) . "'.</p>";
|
18 |
echo "<p>";
|
19 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/01-new-payment.php">Create payment with example 1</a><br>';
|
20 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/04-ideal-payment.php">Create iDEAL payment with example 4</a><br>';
|
21 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/05-payments-history.php">List payments with example 5</a><br>';
|
22 |
echo "</p>";
|
23 |
+
|
24 |
/*
|
25 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
26 |
*/
|
27 |
function database_read($orderId)
|
28 |
{
|
29 |
+
$orderId = intval($orderId);
|
30 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
31 |
+
|
32 |
+
$status = @file_get_contents($database);
|
33 |
+
|
34 |
return $status ? $status : "unknown order";
|
35 |
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 4 - How to prepare an iDEAL payment with the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key.
|
@@ -12,30 +10,37 @@ try {
|
|
12 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
13 |
*/
|
14 |
require "./initialize.php";
|
|
|
15 |
/*
|
16 |
* First, let the customer pick the bank in a simple HTML form. This step is actually optional.
|
17 |
*/
|
18 |
if ($_SERVER["REQUEST_METHOD"] != "POST") {
|
19 |
$method = $mollie->methods->get(\Mollie\Api\Types\PaymentMethod::IDEAL, ["include" => "issuers"]);
|
|
|
20 |
echo '<form method="post">Select your bank: <select name="issuer">';
|
|
|
21 |
foreach ($method->issuers() as $issuer) {
|
22 |
-
echo '<option value=' .
|
23 |
}
|
|
|
24 |
echo '<option value="">or select later</option>';
|
25 |
echo '</select><button>OK</button></form>';
|
26 |
exit;
|
27 |
}
|
|
|
28 |
/*
|
29 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
30 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
31 |
*/
|
32 |
-
$orderId =
|
|
|
33 |
/*
|
34 |
* Determine the url parts to these example files.
|
35 |
*/
|
36 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
37 |
$hostname = $_SERVER['HTTP_HOST'];
|
38 |
-
$path =
|
|
|
39 |
/*
|
40 |
* Payment parameters:
|
41 |
* amount Amount in EUROs. This example creates a € 27.50 payment.
|
@@ -46,25 +51,43 @@ try {
|
|
46 |
* metadata Custom metadata that is stored with the payment.
|
47 |
* issuer The customer's bank. If empty the customer can select it later.
|
48 |
*/
|
49 |
-
$payment = $mollie->payments->create([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
/*
|
51 |
* In this example we store the order with its payment status in a database.
|
52 |
*/
|
53 |
-
|
|
|
54 |
/*
|
55 |
* Send the customer off to complete the payment.
|
56 |
* This request should always be a GET, thus we enforce 303 http response code
|
57 |
*/
|
58 |
-
|
59 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
60 |
-
echo "API call failed: " .
|
61 |
}
|
|
|
62 |
/*
|
63 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
64 |
*/
|
65 |
function database_write($orderId, $status)
|
66 |
{
|
67 |
-
$orderId =
|
68 |
-
$database =
|
69 |
-
|
|
|
70 |
}
|
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 4 - How to prepare an iDEAL payment with the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key.
|
10 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
11 |
*/
|
12 |
require "./initialize.php";
|
13 |
+
|
14 |
/*
|
15 |
* First, let the customer pick the bank in a simple HTML form. This step is actually optional.
|
16 |
*/
|
17 |
if ($_SERVER["REQUEST_METHOD"] != "POST") {
|
18 |
$method = $mollie->methods->get(\Mollie\Api\Types\PaymentMethod::IDEAL, ["include" => "issuers"]);
|
19 |
+
|
20 |
echo '<form method="post">Select your bank: <select name="issuer">';
|
21 |
+
|
22 |
foreach ($method->issuers() as $issuer) {
|
23 |
+
echo '<option value=' . htmlspecialchars($issuer->id) . '>' . htmlspecialchars($issuer->name) . '</option>';
|
24 |
}
|
25 |
+
|
26 |
echo '<option value="">or select later</option>';
|
27 |
echo '</select><button>OK</button></form>';
|
28 |
exit;
|
29 |
}
|
30 |
+
|
31 |
/*
|
32 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
33 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
34 |
*/
|
35 |
+
$orderId = time();
|
36 |
+
|
37 |
/*
|
38 |
* Determine the url parts to these example files.
|
39 |
*/
|
40 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
41 |
$hostname = $_SERVER['HTTP_HOST'];
|
42 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
43 |
+
|
44 |
/*
|
45 |
* Payment parameters:
|
46 |
* amount Amount in EUROs. This example creates a € 27.50 payment.
|
51 |
* metadata Custom metadata that is stored with the payment.
|
52 |
* issuer The customer's bank. If empty the customer can select it later.
|
53 |
*/
|
54 |
+
$payment = $mollie->payments->create([
|
55 |
+
"amount" => [
|
56 |
+
"currency" => "EUR",
|
57 |
+
"value" => "27.50" // You must send the correct number of decimals, thus we enforce the use of strings
|
58 |
+
],
|
59 |
+
"method" => \Mollie\Api\Types\PaymentMethod::IDEAL,
|
60 |
+
"description" => "Order #{$orderId}",
|
61 |
+
"redirectUrl" => "{$protocol}://{$hostname}{$path}/03-return-page.php?order_id={$orderId}",
|
62 |
+
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
63 |
+
"metadata" => [
|
64 |
+
"order_id" => $orderId,
|
65 |
+
],
|
66 |
+
"issuer" => !empty($_POST["issuer"]) ? $_POST["issuer"] : null
|
67 |
+
]);
|
68 |
+
|
69 |
/*
|
70 |
* In this example we store the order with its payment status in a database.
|
71 |
*/
|
72 |
+
database_write($order_id, $payment->status);
|
73 |
+
|
74 |
/*
|
75 |
* Send the customer off to complete the payment.
|
76 |
* This request should always be a GET, thus we enforce 303 http response code
|
77 |
*/
|
78 |
+
header("Location: " . $payment->getCheckoutUrl(), true, 303);
|
79 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
80 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
81 |
}
|
82 |
+
|
83 |
/*
|
84 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
85 |
*/
|
86 |
function database_write($orderId, $status)
|
87 |
{
|
88 |
+
$orderId = intval($orderId);
|
89 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
90 |
+
|
91 |
+
file_put_contents($database, $status);
|
92 |
}
|
93 |
+
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 5 - How to retrieve your payments history.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key.
|
@@ -12,60 +10,76 @@ try {
|
|
12 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
13 |
*/
|
14 |
require "./initialize.php";
|
|
|
15 |
/*
|
16 |
* Determine the url parts to these example files.
|
17 |
*/
|
18 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
19 |
$hostname = $_SERVER['HTTP_HOST'];
|
20 |
-
$path =
|
|
|
21 |
/*
|
22 |
* Get the all payments for this API key ordered by newest.
|
23 |
*/
|
24 |
$payments = $mollie->payments->page();
|
|
|
25 |
echo "<ul>";
|
26 |
foreach ($payments as $payment) {
|
27 |
echo "<li>";
|
28 |
-
echo "<strong style='font-family: monospace'>" .
|
29 |
-
echo
|
30 |
-
echo
|
31 |
-
|
|
|
|
|
32 |
if ($payment->hasRefunds()) {
|
33 |
echo "Payment has been (partially) refunded.<br />";
|
34 |
}
|
|
|
35 |
if ($payment->hasChargebacks()) {
|
36 |
echo "Payment has been charged back.<br />";
|
37 |
}
|
|
|
38 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
39 |
-
echo " (<a href=\"{$protocol}://{$hostname}{$path}/07-refund-payment.php?payment_id=" .
|
40 |
}
|
|
|
41 |
echo "</li>";
|
42 |
}
|
43 |
echo "</ul>";
|
|
|
44 |
/**
|
45 |
* Get the next set of Payments if applicable
|
46 |
*/
|
47 |
$nextPayments = $payments->next();
|
|
|
48 |
if (!empty($nextPayments)) {
|
49 |
echo "<ul>";
|
50 |
foreach ($nextPayments as $payment) {
|
51 |
echo "<li>";
|
52 |
-
echo "<strong style='font-family: monospace'>" .
|
53 |
-
echo
|
54 |
-
echo
|
55 |
-
|
|
|
|
|
56 |
if ($payment->hasRefunds()) {
|
57 |
echo "Payment has been (partially) refunded.<br />";
|
58 |
}
|
|
|
59 |
if ($payment->hasChargebacks()) {
|
60 |
echo "Payment has been charged back.<br />";
|
61 |
}
|
|
|
62 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
63 |
-
echo " (<a href=\"{$protocol}://{$hostname}{$path}/07-refund-payment.php?payment_id=" .
|
64 |
}
|
|
|
65 |
echo "</li>";
|
66 |
}
|
67 |
echo "</ul>";
|
68 |
}
|
|
|
69 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
70 |
-
echo "API call failed: " .
|
71 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 5 - How to retrieve your payments history.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key.
|
10 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
11 |
*/
|
12 |
require "./initialize.php";
|
13 |
+
|
14 |
/*
|
15 |
* Determine the url parts to these example files.
|
16 |
*/
|
17 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
18 |
$hostname = $_SERVER['HTTP_HOST'];
|
19 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
20 |
+
|
21 |
/*
|
22 |
* Get the all payments for this API key ordered by newest.
|
23 |
*/
|
24 |
$payments = $mollie->payments->page();
|
25 |
+
|
26 |
echo "<ul>";
|
27 |
foreach ($payments as $payment) {
|
28 |
echo "<li>";
|
29 |
+
echo "<strong style='font-family: monospace'>" . htmlspecialchars($payment->id) . "</strong><br />";
|
30 |
+
echo htmlspecialchars($payment->description) . "<br />";
|
31 |
+
echo htmlspecialchars($payment->amount->currency) . " " . htmlspecialchars($payment->amount->value) . "<br />";
|
32 |
+
|
33 |
+
echo "Status: " . htmlspecialchars($payment->status) . "<br />";
|
34 |
+
|
35 |
if ($payment->hasRefunds()) {
|
36 |
echo "Payment has been (partially) refunded.<br />";
|
37 |
}
|
38 |
+
|
39 |
if ($payment->hasChargebacks()) {
|
40 |
echo "Payment has been charged back.<br />";
|
41 |
}
|
42 |
+
|
43 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
44 |
+
echo " (<a href=\"{$protocol}://{$hostname}{$path}/07-refund-payment.php?payment_id=" . htmlspecialchars($payment->id) . "\">refund</a>)";
|
45 |
}
|
46 |
+
|
47 |
echo "</li>";
|
48 |
}
|
49 |
echo "</ul>";
|
50 |
+
|
51 |
/**
|
52 |
* Get the next set of Payments if applicable
|
53 |
*/
|
54 |
$nextPayments = $payments->next();
|
55 |
+
|
56 |
if (!empty($nextPayments)) {
|
57 |
echo "<ul>";
|
58 |
foreach ($nextPayments as $payment) {
|
59 |
echo "<li>";
|
60 |
+
echo "<strong style='font-family: monospace'>" . htmlspecialchars($payment->id) . "</strong><br />";
|
61 |
+
echo htmlspecialchars($payment->description) . "<br />";
|
62 |
+
echo htmlspecialchars($payment->amount->currency) . " " . htmlspecialchars($payment->amount->value) . "<br />";
|
63 |
+
|
64 |
+
echo "Status: " . htmlspecialchars($payment->status) . "<br />";
|
65 |
+
|
66 |
if ($payment->hasRefunds()) {
|
67 |
echo "Payment has been (partially) refunded.<br />";
|
68 |
}
|
69 |
+
|
70 |
if ($payment->hasChargebacks()) {
|
71 |
echo "Payment has been charged back.<br />";
|
72 |
}
|
73 |
+
|
74 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
75 |
+
echo " (<a href=\"{$protocol}://{$hostname}{$path}/07-refund-payment.php?payment_id=" . htmlspecialchars($payment->id) . "\">refund</a>)";
|
76 |
}
|
77 |
+
|
78 |
echo "</li>";
|
79 |
}
|
80 |
echo "</ul>";
|
81 |
}
|
82 |
+
|
83 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
84 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
85 |
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 6 - How to get the currently activated payment methods.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key.
|
@@ -18,10 +16,10 @@ try {
|
|
18 |
$methods = $mollie->methods->all();
|
19 |
foreach ($methods as $method) {
|
20 |
echo '<div style="line-height:40px; vertical-align:top">';
|
21 |
-
echo '<img src="' .
|
22 |
-
echo
|
23 |
echo '</div>';
|
24 |
}
|
25 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
26 |
-
echo "API call failed: " .
|
27 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 6 - How to get the currently activated payment methods.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key.
|
16 |
$methods = $mollie->methods->all();
|
17 |
foreach ($methods as $method) {
|
18 |
echo '<div style="line-height:40px; vertical-align:top">';
|
19 |
+
echo '<img src="' . htmlspecialchars($method->image->size1x) . '" srcset="' . htmlspecialchars($method->image->size2x) . ' 2x"> ';
|
20 |
+
echo htmlspecialchars($method->description) . ' (' . htmlspecialchars($method->id) . ')';
|
21 |
echo '</div>';
|
22 |
}
|
23 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
24 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
25 |
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 7 - How to refund a payment programmatically
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key.
|
@@ -12,50 +10,62 @@ try {
|
|
12 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
13 |
*/
|
14 |
require "./initialize.php";
|
|
|
15 |
/*
|
16 |
* Determine the url parts to these example files.
|
17 |
*/
|
18 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
19 |
$hostname = $_SERVER['HTTP_HOST'];
|
20 |
-
$path =
|
|
|
21 |
if (isset($_GET['payment_id'])) {
|
22 |
/*
|
23 |
* Retrieve the payment you want to refund from the API.
|
24 |
*/
|
25 |
$paymentId = $_GET['payment_id'];
|
26 |
$payment = $mollie->payments->get($paymentId);
|
|
|
27 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
28 |
/*
|
29 |
* Refund € 2,00 of the payment.
|
30 |
*
|
31 |
* https://docs.mollie.com/reference/v2/refunds-api/create-refund
|
32 |
*/
|
33 |
-
$refund = $payment->refund([
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
} else {
|
36 |
-
echo "Payment {$paymentId} can not be refunded.",
|
37 |
}
|
|
|
38 |
/*
|
39 |
* Retrieve all refunds on a payment.
|
40 |
*/
|
41 |
echo "<ul>";
|
42 |
foreach ($payment->refunds() as $refund) {
|
43 |
echo "<li>";
|
44 |
-
echo "<strong style='font-family: monospace'>" .
|
45 |
-
echo
|
46 |
-
echo
|
47 |
-
echo "Status: " .
|
48 |
echo "</li>";
|
49 |
}
|
50 |
echo "</ul>";
|
51 |
}
|
|
|
52 |
echo "Refund payment: ";
|
53 |
echo "<form method='get'><input name='payment_id' value='tr_xxx'/><input type='submit' /></form>";
|
|
|
54 |
echo "<p>";
|
55 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/01-new-payment.php">Create payment with example 1</a><br>';
|
56 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/04-ideal-payment.php">Create iDEAL payment with example 4</a><br>';
|
57 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/05-payments-history.php">List payments with example 5</a><br>';
|
58 |
echo "</p>";
|
59 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
60 |
-
echo "API call failed: " .
|
61 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 7 - How to refund a payment programmatically
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key.
|
10 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
11 |
*/
|
12 |
require "./initialize.php";
|
13 |
+
|
14 |
/*
|
15 |
* Determine the url parts to these example files.
|
16 |
*/
|
17 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
18 |
$hostname = $_SERVER['HTTP_HOST'];
|
19 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
20 |
+
|
21 |
if (isset($_GET['payment_id'])) {
|
22 |
/*
|
23 |
* Retrieve the payment you want to refund from the API.
|
24 |
*/
|
25 |
$paymentId = $_GET['payment_id'];
|
26 |
$payment = $mollie->payments->get($paymentId);
|
27 |
+
|
28 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
29 |
/*
|
30 |
* Refund € 2,00 of the payment.
|
31 |
*
|
32 |
* https://docs.mollie.com/reference/v2/refunds-api/create-refund
|
33 |
*/
|
34 |
+
$refund = $payment->refund([
|
35 |
+
"amount" => [
|
36 |
+
"currency" => "EUR",
|
37 |
+
"value" => "2.00" // You must send the correct number of decimals, thus we enforce the use of strings
|
38 |
+
]
|
39 |
+
]);
|
40 |
+
|
41 |
+
echo "{$refund->amount->currency} {$refund->amount->value} of payment {$paymentId} refunded.", PHP_EOL;
|
42 |
} else {
|
43 |
+
echo "Payment {$paymentId} can not be refunded.", PHP_EOL;
|
44 |
}
|
45 |
+
|
46 |
/*
|
47 |
* Retrieve all refunds on a payment.
|
48 |
*/
|
49 |
echo "<ul>";
|
50 |
foreach ($payment->refunds() as $refund) {
|
51 |
echo "<li>";
|
52 |
+
echo "<strong style='font-family: monospace'>" . htmlspecialchars($refund->id) . "</strong><br />";
|
53 |
+
echo htmlspecialchars($refund->description) . "<br />";
|
54 |
+
echo htmlspecialchars($refund->amount->currency) . " " . htmlspecialchars($refund->amount->value) . "<br />";
|
55 |
+
echo "Status: " . htmlspecialchars($refund->status);
|
56 |
echo "</li>";
|
57 |
}
|
58 |
echo "</ul>";
|
59 |
}
|
60 |
+
|
61 |
echo "Refund payment: ";
|
62 |
echo "<form method='get'><input name='payment_id' value='tr_xxx'/><input type='submit' /></form>";
|
63 |
+
|
64 |
echo "<p>";
|
65 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/01-new-payment.php">Create payment with example 1</a><br>';
|
66 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/04-ideal-payment.php">Create iDEAL payment with example 4</a><br>';
|
67 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/05-payments-history.php">List payments with example 5</a><br>';
|
68 |
echo "</p>";
|
69 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
70 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
71 |
}
|
@@ -1,11 +1,9 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 8 - Using OAuth access token to list profiles of an account.
|
7 |
*/
|
8 |
-
try
|
|
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your OAuth access token.
|
11 |
*/
|
@@ -14,11 +12,16 @@ try {
|
|
14 |
* Get the all the profiles for this account.
|
15 |
*/
|
16 |
$profiles = $mollie->profiles->page();
|
17 |
-
foreach ($profiles as $profile)
|
|
|
18 |
echo '<div style="line-height:40px; vertical-align:top">';
|
19 |
-
echo
|
|
|
|
|
20 |
echo '</div>';
|
21 |
}
|
22 |
-
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
23 |
-
echo "API call failed: " . \htmlspecialchars($e->getMessage());
|
24 |
}
|
|
|
|
|
|
|
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 8 - Using OAuth access token to list profiles of an account.
|
4 |
*/
|
5 |
+
try
|
6 |
+
{
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your OAuth access token.
|
9 |
*/
|
12 |
* Get the all the profiles for this account.
|
13 |
*/
|
14 |
$profiles = $mollie->profiles->page();
|
15 |
+
foreach ($profiles as $profile)
|
16 |
+
{
|
17 |
echo '<div style="line-height:40px; vertical-align:top">';
|
18 |
+
echo htmlspecialchars($profile->name) .
|
19 |
+
' - ' . htmlspecialchars($profile->website) .
|
20 |
+
' (' . htmlspecialchars($profile->id) . ')';
|
21 |
echo '</div>';
|
22 |
}
|
|
|
|
|
23 |
}
|
24 |
+
catch (\Mollie\Api\Exceptions\ApiException $e)
|
25 |
+
{
|
26 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
27 |
+
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 9 - Using OAuth access token to list settlements of an account.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your OAuth access token.
|
@@ -16,39 +14,39 @@ try {
|
|
16 |
$settlements = $mollie->settlements->page();
|
17 |
echo '<ul>';
|
18 |
foreach ($settlements as $settlement) {
|
19 |
-
echo '<li><b>Settlement ' .
|
20 |
echo '<table border="1"><tr><th>Month</th><th>Description</th><th>Count</th><th>Net</th><th>VAT</th><th>Gross</th></tr>';
|
21 |
// Convert from stdClass to array
|
22 |
-
$settlement_periods =
|
23 |
foreach ($settlement_periods as $year => $months) {
|
24 |
foreach ($months as $month => $monthly_settlement) {
|
25 |
foreach ($monthly_settlement['revenue'] as $revenue) {
|
26 |
echo '<tr>';
|
27 |
-
echo '<td>' .
|
28 |
-
echo '<td>' .
|
29 |
-
echo '<td align="right">' .
|
30 |
-
echo '<td align="right">' .
|
31 |
-
echo '<td align="right">' .
|
32 |
-
echo '<td align="right">' .
|
33 |
echo '</tr>';
|
34 |
}
|
35 |
foreach ($monthly_settlement['costs'] as $revenue) {
|
36 |
echo '<tr>';
|
37 |
-
echo '<td>' .
|
38 |
-
echo '<td>' .
|
39 |
-
echo '<td align="right">' .
|
40 |
-
echo '<td align="right">' .
|
41 |
-
echo '<td align="right">' .
|
42 |
-
echo '<td align="right">' .
|
43 |
echo '</tr>';
|
44 |
}
|
45 |
}
|
46 |
}
|
47 |
-
echo '<tr><th colspan="5" align="right">TOTAL</th><th align="right">' .
|
48 |
echo '</table>';
|
49 |
echo '</li>';
|
50 |
}
|
51 |
echo '</ul>';
|
52 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
53 |
-
echo "API call failed: " .
|
54 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 9 - Using OAuth access token to list settlements of an account.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your OAuth access token.
|
14 |
$settlements = $mollie->settlements->page();
|
15 |
echo '<ul>';
|
16 |
foreach ($settlements as $settlement) {
|
17 |
+
echo '<li><b>Settlement ' . htmlspecialchars($settlement->reference) . ':</b> (' . htmlspecialchars($settlement->createdAt) . ')';
|
18 |
echo '<table border="1"><tr><th>Month</th><th>Description</th><th>Count</th><th>Net</th><th>VAT</th><th>Gross</th></tr>';
|
19 |
// Convert from stdClass to array
|
20 |
+
$settlement_periods = json_decode(json_encode($settlement->periods), TRUE);
|
21 |
foreach ($settlement_periods as $year => $months) {
|
22 |
foreach ($months as $month => $monthly_settlement) {
|
23 |
foreach ($monthly_settlement['revenue'] as $revenue) {
|
24 |
echo '<tr>';
|
25 |
+
echo '<td>' . htmlspecialchars($year . '-' . $month) . '</td>';
|
26 |
+
echo '<td>' . htmlspecialchars($revenue['description']) . '</td>';
|
27 |
+
echo '<td align="right">' . htmlspecialchars($revenue['count']) . ' x</td>';
|
28 |
+
echo '<td align="right">' . htmlspecialchars($revenue['amountNet']['value'] ? $revenue['amountNet']['value'] . " " . $revenue['amountNet']['currency'] : '-') . '</td>';
|
29 |
+
echo '<td align="right">' . htmlspecialchars($revenue['amountVat']['value'] ? $revenue['amountVat']['value'] . " " . $revenue['amountVat']['currency'] : '-') . '</td>';
|
30 |
+
echo '<td align="right">' . htmlspecialchars($revenue['amountGross']['value'] ? $revenue['amountGross']['value'] . " " . $revenue['amountGross']['currency'] : '-') . '</td>';
|
31 |
echo '</tr>';
|
32 |
}
|
33 |
foreach ($monthly_settlement['costs'] as $revenue) {
|
34 |
echo '<tr>';
|
35 |
+
echo '<td>' . htmlspecialchars($year . '-' . $month) . '</td>';
|
36 |
+
echo '<td>' . htmlspecialchars($revenue['description']) . '</td>';
|
37 |
+
echo '<td align="right">' . htmlspecialchars($revenue['count']) . ' x</td>';
|
38 |
+
echo '<td align="right">' . htmlspecialchars($revenue['amountNet']['value'] ? $revenue['amountNet']['value'] . " " . $revenue['amountNet']['currency'] : '-') . '</td>';
|
39 |
+
echo '<td align="right">' . htmlspecialchars($revenue['amountVat']['value'] ? $revenue['amountVat']['value'] . " " . $revenue['amountVat']['currency'] : '-') . '</td>';
|
40 |
+
echo '<td align="right">' . htmlspecialchars($revenue['amountGross']['value'] ? $revenue['amountGross']['value'] . " " . $revenue['amountGross']['currency'] : '-') . '</td>';
|
41 |
echo '</tr>';
|
42 |
}
|
43 |
}
|
44 |
}
|
45 |
+
echo '<tr><th colspan="5" align="right">TOTAL</th><th align="right">' . htmlspecialchars($settlement->amount->value . " " . $settlement->amount->currency) . '</th></tr>';
|
46 |
echo '</table>';
|
47 |
echo '</li>';
|
48 |
}
|
49 |
echo '</ul>';
|
50 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
51 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
52 |
+
}
|
@@ -1,11 +1,9 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 10 - Using OAuth access token to prepare a new payment.
|
7 |
*/
|
8 |
-
try
|
|
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your OAuth access token.
|
11 |
*/
|
@@ -14,19 +12,19 @@ try {
|
|
14 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
15 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
16 |
*/
|
17 |
-
$orderId =
|
18 |
/*
|
19 |
* Determine the url parts to these example files.
|
20 |
*/
|
21 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
22 |
-
$hostname = $_SERVER['HTTP_HOST']
|
23 |
-
$path
|
24 |
/*
|
25 |
* Since unlike an API key the OAuth access token does NOT belong to a profile, we need to retrieve a profile
|
26 |
* so we can specify the profileId-parameter when creating a payment below.
|
27 |
*/
|
28 |
$profiles = $mollie->profiles->page();
|
29 |
-
$profile
|
30 |
/*
|
31 |
* Payment parameters:
|
32 |
* amount Amount in EUROs. This example creates a € 10,- payment.
|
@@ -35,29 +33,44 @@ try {
|
|
35 |
* webhookUrl Webhook location, used to report when the payment changes state.
|
36 |
* metadata Custom metadata that is stored with the payment.
|
37 |
*/
|
38 |
-
$payment = $mollie->payments->create(array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
/*
|
40 |
* In this example we store the order with its payment status in a database.
|
41 |
*/
|
42 |
-
|
43 |
/*
|
44 |
* Send the customer off to complete the payment.
|
45 |
* This request should always be a GET, thus we enforce 303 http response code
|
46 |
*/
|
47 |
-
if (
|
48 |
-
|
|
|
49 |
return;
|
50 |
}
|
51 |
-
|
52 |
-
}
|
53 |
-
|
|
|
|
|
54 |
}
|
55 |
/*
|
56 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
57 |
*/
|
58 |
-
function database_write($orderId, $status)
|
59 |
{
|
60 |
-
$orderId =
|
61 |
-
$database =
|
62 |
-
|
63 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 10 - Using OAuth access token to prepare a new payment.
|
4 |
*/
|
5 |
+
try
|
6 |
+
{
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your OAuth access token.
|
9 |
*/
|
12 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
13 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
14 |
*/
|
15 |
+
$orderId = time();
|
16 |
/*
|
17 |
* Determine the url parts to these example files.
|
18 |
*/
|
19 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
20 |
+
$hostname = $_SERVER['HTTP_HOST'] ? : "my.app";
|
21 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
22 |
/*
|
23 |
* Since unlike an API key the OAuth access token does NOT belong to a profile, we need to retrieve a profile
|
24 |
* so we can specify the profileId-parameter when creating a payment below.
|
25 |
*/
|
26 |
$profiles = $mollie->profiles->page();
|
27 |
+
$profile = reset($profiles);
|
28 |
/*
|
29 |
* Payment parameters:
|
30 |
* amount Amount in EUROs. This example creates a € 10,- payment.
|
33 |
* webhookUrl Webhook location, used to report when the payment changes state.
|
34 |
* metadata Custom metadata that is stored with the payment.
|
35 |
*/
|
36 |
+
$payment = $mollie->payments->create(array(
|
37 |
+
"amount" => [
|
38 |
+
"value" => "10.00",
|
39 |
+
"currency" => "EUR"
|
40 |
+
],
|
41 |
+
"description" => "My first API payment",
|
42 |
+
"redirectUrl" => "{$protocol}://{$hostname}{$path}/03-return-page.php?order_id={$orderId}",
|
43 |
+
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
44 |
+
"metadata" => array(
|
45 |
+
"order_id" => $orderId,
|
46 |
+
),
|
47 |
+
"profileId" => $profile->id // This is specifically necessary for payment resources via OAuth access.
|
48 |
+
));
|
49 |
/*
|
50 |
* In this example we store the order with its payment status in a database.
|
51 |
*/
|
52 |
+
database_write($orderId, $payment->status);
|
53 |
/*
|
54 |
* Send the customer off to complete the payment.
|
55 |
* This request should always be a GET, thus we enforce 303 http response code
|
56 |
*/
|
57 |
+
if (PHP_SAPI === "cli")
|
58 |
+
{
|
59 |
+
echo "Redirect to: " . $payment->getCheckoutUrl() . PHP_EOL;
|
60 |
return;
|
61 |
}
|
62 |
+
header("Location: " . $payment->getCheckoutUrl(), true, 303);
|
63 |
+
}
|
64 |
+
catch (\Mollie\Api\Exceptions\ApiException $e)
|
65 |
+
{
|
66 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
67 |
}
|
68 |
/*
|
69 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
70 |
*/
|
71 |
+
function database_write ($orderId, $status)
|
72 |
{
|
73 |
+
$orderId = intval($orderId);
|
74 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
75 |
+
file_put_contents($database, $status);
|
76 |
+
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 11 - How to create a new customer in the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
@@ -15,8 +13,14 @@ try {
|
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/customers-api/create-customer
|
17 |
*/
|
18 |
-
$customer = $mollie->customers->create([
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
21 |
-
echo "API call failed: " .
|
22 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 11 - How to create a new customer in the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
13 |
*
|
14 |
* See: https://docs.mollie.com/reference/v2/customers-api/create-customer
|
15 |
*/
|
16 |
+
$customer = $mollie->customers->create([
|
17 |
+
"name" => "Luke Skywalker",
|
18 |
+
"email" => "luke@example.org",
|
19 |
+
"metadata" => array(
|
20 |
+
"isJedi" => TRUE,
|
21 |
+
),
|
22 |
+
]);
|
23 |
+
echo "<p>New customer created " . htmlspecialchars($customer->id) . " (" . htmlspecialchars($customer->name) . ").</p>";
|
24 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
25 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
26 |
+
}
|
@@ -1,60 +1,72 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 12 - How to create a new customer in the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "initialize.php";
|
|
|
13 |
/*
|
14 |
* Retrieve the last created customer for this example.
|
15 |
* If no customers are created yet, run example 11.
|
16 |
*/
|
17 |
$customer = $mollie->customers->page(null, 1)[0];
|
|
|
18 |
/*
|
19 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
20 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
21 |
*/
|
22 |
-
$orderId =
|
|
|
23 |
/*
|
24 |
* Determine the url parts to these example files.
|
25 |
*/
|
26 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
27 |
$hostname = $_SERVER['HTTP_HOST'];
|
28 |
-
$path =
|
|
|
29 |
/*
|
30 |
* Customer Payment creation parameters.
|
31 |
*
|
32 |
* Linking customers to payments has a few benefits, see:
|
33 |
* https://docs.mollie.com/reference/v2/customers-api/create-customer-payment
|
34 |
*/
|
35 |
-
$payment = $customer->createPayment([
|
36 |
-
"
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
/*
|
41 |
* In this example we store the order with its payment status in a database.
|
42 |
*/
|
43 |
-
|
|
|
44 |
/*
|
45 |
* Send the customer off to complete the payment.
|
46 |
* This request should always be a GET, thus we enforce 303 http response code
|
47 |
*/
|
48 |
-
|
49 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
50 |
-
echo "API call failed: " .
|
51 |
}
|
|
|
52 |
/*
|
53 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
54 |
*/
|
55 |
function database_write($orderId, $status)
|
56 |
{
|
57 |
-
$orderId =
|
58 |
-
$database =
|
59 |
-
|
60 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 12 - How to create a new customer in the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Retrieve the last created customer for this example.
|
14 |
* If no customers are created yet, run example 11.
|
15 |
*/
|
16 |
$customer = $mollie->customers->page(null, 1)[0];
|
17 |
+
|
18 |
/*
|
19 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
20 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
21 |
*/
|
22 |
+
$orderId = time();
|
23 |
+
|
24 |
/*
|
25 |
* Determine the url parts to these example files.
|
26 |
*/
|
27 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
28 |
$hostname = $_SERVER['HTTP_HOST'];
|
29 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
30 |
+
|
31 |
/*
|
32 |
* Customer Payment creation parameters.
|
33 |
*
|
34 |
* Linking customers to payments has a few benefits, see:
|
35 |
* https://docs.mollie.com/reference/v2/customers-api/create-customer-payment
|
36 |
*/
|
37 |
+
$payment = $customer->createPayment([
|
38 |
+
"amount" => [
|
39 |
+
"value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings
|
40 |
+
"currency" => "EUR"
|
41 |
+
],
|
42 |
+
"description" => "Order #{$orderId}",
|
43 |
+
"redirectUrl" => "{$protocol}://{$hostname}{$path}/03-return-page.php?order_id={$orderId}",
|
44 |
+
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
45 |
+
"metadata" => [
|
46 |
+
"order_id" => $orderId,
|
47 |
+
]
|
48 |
+
]);
|
49 |
+
|
50 |
/*
|
51 |
* In this example we store the order with its payment status in a database.
|
52 |
*/
|
53 |
+
database_write($orderId, $payment->status);
|
54 |
+
|
55 |
/*
|
56 |
* Send the customer off to complete the payment.
|
57 |
* This request should always be a GET, thus we enforce 303 http response code
|
58 |
*/
|
59 |
+
header("Location: " . $payment->getCheckoutUrl(), true, 303);
|
60 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
61 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
62 |
}
|
63 |
+
|
64 |
/*
|
65 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
66 |
*/
|
67 |
function database_write($orderId, $status)
|
68 |
{
|
69 |
+
$orderId = intval($orderId);
|
70 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
71 |
+
file_put_contents($database, $status);
|
72 |
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 13 - How to retrieve your customers' payments history.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key.
|
@@ -12,40 +10,49 @@ try {
|
|
12 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
13 |
*/
|
14 |
require "initialize.php";
|
|
|
15 |
/*
|
16 |
-
|
17 |
-
|
18 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
19 |
$hostname = $_SERVER['HTTP_HOST'];
|
20 |
-
$path =
|
|
|
21 |
/*
|
22 |
* Retrieve the last created customer for this example.
|
23 |
* If no customers are created yet, run example 11.
|
24 |
*/
|
25 |
$customer = $mollie->customers->page(null, 1)[0];
|
|
|
26 |
/*
|
27 |
* Get the all payments for this API key ordered by newest.
|
28 |
*/
|
29 |
$payments = $customer->payments();
|
|
|
30 |
echo "<ul>";
|
31 |
foreach ($payments as $payment) {
|
32 |
echo "<li>";
|
33 |
-
echo "<strong style='font-family: monospace'>" .
|
34 |
-
echo
|
35 |
-
echo
|
36 |
-
|
|
|
|
|
37 |
if ($payment->hasRefunds()) {
|
38 |
echo "Payment has been (partially) refunded.<br />";
|
39 |
}
|
|
|
40 |
if ($payment->hasChargebacks()) {
|
41 |
echo "Payment has been charged back.<br />";
|
42 |
}
|
|
|
43 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
44 |
-
echo " (<a href=\"{$protocol}://{$hostname}{$path}/07-refund-payment.php?payment_id=" .
|
45 |
}
|
|
|
46 |
echo "</li>";
|
47 |
}
|
48 |
echo "</ul>";
|
49 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
50 |
-
echo "API call failed: " .
|
51 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 13 - How to retrieve your customers' payments history.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key.
|
10 |
* See: https://www.mollie.com/dashboard/developers/api-keys
|
11 |
*/
|
12 |
require "initialize.php";
|
13 |
+
|
14 |
/*
|
15 |
+
* Determine the url parts to these example files.
|
16 |
+
*/
|
17 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
18 |
$hostname = $_SERVER['HTTP_HOST'];
|
19 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
20 |
+
|
21 |
/*
|
22 |
* Retrieve the last created customer for this example.
|
23 |
* If no customers are created yet, run example 11.
|
24 |
*/
|
25 |
$customer = $mollie->customers->page(null, 1)[0];
|
26 |
+
|
27 |
/*
|
28 |
* Get the all payments for this API key ordered by newest.
|
29 |
*/
|
30 |
$payments = $customer->payments();
|
31 |
+
|
32 |
echo "<ul>";
|
33 |
foreach ($payments as $payment) {
|
34 |
echo "<li>";
|
35 |
+
echo "<strong style='font-family: monospace'>" . htmlspecialchars($payment->id) . "</strong><br />";
|
36 |
+
echo htmlspecialchars($payment->description) . "<br />";
|
37 |
+
echo htmlspecialchars($payment->amount->currency) . " " . htmlspecialchars($payment->amount->value) . "<br />";
|
38 |
+
|
39 |
+
echo "Status: " . htmlspecialchars($payment->status) . "<br />";
|
40 |
+
|
41 |
if ($payment->hasRefunds()) {
|
42 |
echo "Payment has been (partially) refunded.<br />";
|
43 |
}
|
44 |
+
|
45 |
if ($payment->hasChargebacks()) {
|
46 |
echo "Payment has been charged back.<br />";
|
47 |
}
|
48 |
+
|
49 |
if ($payment->canBeRefunded() && $payment->amountRemaining->currency === 'EUR' && $payment->amountRemaining->value >= '2.00') {
|
50 |
+
echo " (<a href=\"{$protocol}://{$hostname}{$path}/07-refund-payment.php?payment_id=" . htmlspecialchars($payment->id) . "\">refund</a>)";
|
51 |
}
|
52 |
+
|
53 |
echo "</li>";
|
54 |
}
|
55 |
echo "</ul>";
|
56 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
57 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
58 |
+
}
|
@@ -1,31 +1,33 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 14 - How to create a first payment to allow recurring payments later.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "initialize.php";
|
|
|
13 |
/*
|
14 |
* Retrieve the last created customer for this example.
|
15 |
* If no customers are created yet, run example 11.
|
16 |
*/
|
17 |
$customer = $mollie->customers->page(null, 1)[0];
|
|
|
18 |
/*
|
19 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
20 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
21 |
*/
|
22 |
-
$orderId =
|
|
|
23 |
/*
|
24 |
* Determine the url parts to these example files.
|
25 |
*/
|
26 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
27 |
$hostname = $_SERVER['HTTP_HOST'];
|
28 |
-
$path =
|
|
|
29 |
/*
|
30 |
* Customer Payment creation parameters.
|
31 |
*
|
@@ -33,21 +35,25 @@ try {
|
|
33 |
*/
|
34 |
$payment = $customer->createPayment([
|
35 |
"amount" => [
|
36 |
-
"value" => "10.00",
|
37 |
-
|
38 |
-
"currency" => "EUR",
|
39 |
],
|
40 |
"description" => "First payment - Order #{$orderId}",
|
41 |
"redirectUrl" => "{$protocol}://{$hostname}{$path}/03-return-page.php?order_id={$orderId}",
|
42 |
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
43 |
-
"metadata" => [
|
|
|
|
|
|
|
44 |
// Flag this payment as a first payment to allow recurring payments later.
|
45 |
"sequenceType" => \Mollie\Api\Types\SequenceType::SEQUENCETYPE_FIRST,
|
46 |
]);
|
|
|
47 |
/*
|
48 |
* In this example we store the order with its payment status in a database.
|
49 |
*/
|
50 |
-
|
|
|
51 |
/*
|
52 |
* Send the customer off to complete the payment.
|
53 |
* This request should always be a GET, thus we enforce 303 http response code
|
@@ -55,16 +61,17 @@ try {
|
|
55 |
* After completion, the customer will have a pending or valid mandate that can be
|
56 |
* used for recurring payments and subscriptions.
|
57 |
*/
|
58 |
-
|
59 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
60 |
-
echo "API call failed: " .
|
61 |
}
|
|
|
62 |
/*
|
63 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
64 |
*/
|
65 |
function database_write($orderId, $status)
|
66 |
{
|
67 |
-
$orderId =
|
68 |
-
$database =
|
69 |
-
|
70 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 14 - How to create a first payment to allow recurring payments later.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Retrieve the last created customer for this example.
|
14 |
* If no customers are created yet, run example 11.
|
15 |
*/
|
16 |
$customer = $mollie->customers->page(null, 1)[0];
|
17 |
+
|
18 |
/*
|
19 |
* Generate a unique order id for this example. It is important to include this unique attribute
|
20 |
* in the redirectUrl (below) so a proper return page can be shown to the customer.
|
21 |
*/
|
22 |
+
$orderId = time();
|
23 |
+
|
24 |
/*
|
25 |
* Determine the url parts to these example files.
|
26 |
*/
|
27 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
28 |
$hostname = $_SERVER['HTTP_HOST'];
|
29 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
30 |
+
|
31 |
/*
|
32 |
* Customer Payment creation parameters.
|
33 |
*
|
35 |
*/
|
36 |
$payment = $customer->createPayment([
|
37 |
"amount" => [
|
38 |
+
"value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings
|
39 |
+
"currency" => "EUR"
|
|
|
40 |
],
|
41 |
"description" => "First payment - Order #{$orderId}",
|
42 |
"redirectUrl" => "{$protocol}://{$hostname}{$path}/03-return-page.php?order_id={$orderId}",
|
43 |
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
44 |
+
"metadata" => [
|
45 |
+
"order_id" => $orderId,
|
46 |
+
],
|
47 |
+
|
48 |
// Flag this payment as a first payment to allow recurring payments later.
|
49 |
"sequenceType" => \Mollie\Api\Types\SequenceType::SEQUENCETYPE_FIRST,
|
50 |
]);
|
51 |
+
|
52 |
/*
|
53 |
* In this example we store the order with its payment status in a database.
|
54 |
*/
|
55 |
+
database_write($orderId, $payment->status);
|
56 |
+
|
57 |
/*
|
58 |
* Send the customer off to complete the payment.
|
59 |
* This request should always be a GET, thus we enforce 303 http response code
|
61 |
* After completion, the customer will have a pending or valid mandate that can be
|
62 |
* used for recurring payments and subscriptions.
|
63 |
*/
|
64 |
+
header("Location: " . $payment->getCheckoutUrl(), true, 303);
|
65 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
66 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
67 |
}
|
68 |
+
|
69 |
/*
|
70 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
71 |
*/
|
72 |
function database_write($orderId, $status)
|
73 |
{
|
74 |
+
$orderId = intval($orderId);
|
75 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
76 |
+
file_put_contents($database, $status);
|
77 |
}
|
@@ -1,30 +1,32 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 15 - How to create an on-demand recurring payment.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "initialize.php";
|
|
|
13 |
/*
|
14 |
* Retrieve the last created customer for this example.
|
15 |
* If no customers are created yet, run example 11.
|
16 |
*/
|
17 |
$customer = $mollie->customers->page(null, 1)[0];
|
|
|
18 |
/*
|
19 |
* Generate a unique order id for this example.
|
20 |
*/
|
21 |
-
$orderId =
|
|
|
22 |
/*
|
23 |
* Determine the url parts to these example files.
|
24 |
*/
|
25 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
26 |
$hostname = $_SERVER['HTTP_HOST'];
|
27 |
-
$path =
|
|
|
28 |
/*
|
29 |
* Customer Payment creation parameters.
|
30 |
*
|
@@ -32,35 +34,40 @@ try {
|
|
32 |
*/
|
33 |
$payment = $customer->createPayment([
|
34 |
"amount" => [
|
35 |
-
"value" => "10.00",
|
36 |
-
|
37 |
-
"currency" => "EUR",
|
38 |
],
|
39 |
"description" => "On-demand payment - Order #{$orderId}",
|
40 |
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
41 |
-
"metadata" => [
|
|
|
|
|
|
|
42 |
// Flag this payment as a recurring payment.
|
43 |
"sequenceType" => \Mollie\Api\Types\SequenceType::SEQUENCETYPE_RECURRING,
|
44 |
]);
|
|
|
45 |
/*
|
46 |
* In this example we store the order with its payment status in a database.
|
47 |
*/
|
48 |
-
|
|
|
49 |
/*
|
50 |
* The payment will be either pending or paid immediately. The customer
|
51 |
* does not have to perform any payment steps.
|
52 |
*/
|
53 |
-
echo "<p>Selected mandate is '" .
|
54 |
-
echo "<p>The payment status is '" .
|
55 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
56 |
-
echo "API call failed: " .
|
57 |
}
|
|
|
58 |
/*
|
59 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
60 |
*/
|
61 |
function database_write($orderId, $status)
|
62 |
{
|
63 |
-
$orderId =
|
64 |
-
$database =
|
65 |
-
|
66 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 15 - How to create an on-demand recurring payment.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Retrieve the last created customer for this example.
|
14 |
* If no customers are created yet, run example 11.
|
15 |
*/
|
16 |
$customer = $mollie->customers->page(null, 1)[0];
|
17 |
+
|
18 |
/*
|
19 |
* Generate a unique order id for this example.
|
20 |
*/
|
21 |
+
$orderId = time();
|
22 |
+
|
23 |
/*
|
24 |
* Determine the url parts to these example files.
|
25 |
*/
|
26 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
27 |
$hostname = $_SERVER['HTTP_HOST'];
|
28 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
29 |
+
|
30 |
/*
|
31 |
* Customer Payment creation parameters.
|
32 |
*
|
34 |
*/
|
35 |
$payment = $customer->createPayment([
|
36 |
"amount" => [
|
37 |
+
"value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings
|
38 |
+
"currency" => "EUR"
|
|
|
39 |
],
|
40 |
"description" => "On-demand payment - Order #{$orderId}",
|
41 |
"webhookUrl" => "{$protocol}://{$hostname}{$path}/02-webhook-verification.php",
|
42 |
+
"metadata" => [
|
43 |
+
"order_id" => $orderId,
|
44 |
+
],
|
45 |
+
|
46 |
// Flag this payment as a recurring payment.
|
47 |
"sequenceType" => \Mollie\Api\Types\SequenceType::SEQUENCETYPE_RECURRING,
|
48 |
]);
|
49 |
+
|
50 |
/*
|
51 |
* In this example we store the order with its payment status in a database.
|
52 |
*/
|
53 |
+
database_write($orderId, $payment->status);
|
54 |
+
|
55 |
/*
|
56 |
* The payment will be either pending or paid immediately. The customer
|
57 |
* does not have to perform any payment steps.
|
58 |
*/
|
59 |
+
echo "<p>Selected mandate is '" . htmlspecialchars($payment->mandateId) . "' (" . htmlspecialchars($payment->method) . ").</p>\n";
|
60 |
+
echo "<p>The payment status is '" . htmlspecialchars($payment->status) . "'.</p>\n";
|
61 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
62 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
63 |
}
|
64 |
+
|
65 |
/*
|
66 |
* NOTE: This example uses a text file as a database. Please use a real database like MySQL in production code.
|
67 |
*/
|
68 |
function database_write($orderId, $status)
|
69 |
{
|
70 |
+
$orderId = intval($orderId);
|
71 |
+
$database = dirname(__FILE__) . "/orders/order-{$orderId}.txt";
|
72 |
+
file_put_contents($database, $status);
|
73 |
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 16 - How to create a regular subscription.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
@@ -13,9 +11,10 @@ try {
|
|
13 |
/*
|
14 |
* Determine the url parts to these example files.
|
15 |
*/
|
16 |
-
$protocol = isset($_SERVER['HTTPS']) &&
|
17 |
$hostname = $_SERVER['HTTP_HOST'];
|
18 |
-
$path =
|
|
|
19 |
/**
|
20 |
* Retrieve the last created customer for this example.
|
21 |
* If no customers are created yet, run example 11.
|
@@ -25,26 +24,32 @@ try {
|
|
25 |
* Generate a unique subscription id for this example. It is important to include this unique attribute
|
26 |
* in the webhookUrl (below) so new payments can be associated with this subscription.
|
27 |
*/
|
28 |
-
$subscriptionId =
|
29 |
/*
|
30 |
* Customer Subscription creation parameters.
|
31 |
*
|
32 |
* See: https://www.mollie.com/nl/docs/reference/subscriptions/create
|
33 |
*/
|
34 |
-
$subscription = $customer->createSubscription([
|
35 |
-
"
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
/*
|
40 |
* The subscription will be either pending or active depending on whether the customer has
|
41 |
* a pending or valid mandate. If the customer has no mandates an error is returned. You
|
42 |
* should then set up a "first payment" for the customer (example 14).
|
43 |
*/
|
44 |
-
echo "<p>The subscription status is '" .
|
45 |
echo "<p>";
|
46 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/17-cancel-subscription.php?subscription_id=' . $subscription->id . '">18-cancel-subscription</a><br>';
|
47 |
echo "</p>";
|
48 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
49 |
-
echo "API call failed: " .
|
50 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 16 - How to create a regular subscription.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
/*
|
12 |
* Determine the url parts to these example files.
|
13 |
*/
|
14 |
+
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
|
15 |
$hostname = $_SERVER['HTTP_HOST'];
|
16 |
+
$path = dirname(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']);
|
17 |
+
|
18 |
/**
|
19 |
* Retrieve the last created customer for this example.
|
20 |
* If no customers are created yet, run example 11.
|
24 |
* Generate a unique subscription id for this example. It is important to include this unique attribute
|
25 |
* in the webhookUrl (below) so new payments can be associated with this subscription.
|
26 |
*/
|
27 |
+
$subscriptionId = time();
|
28 |
/*
|
29 |
* Customer Subscription creation parameters.
|
30 |
*
|
31 |
* See: https://www.mollie.com/nl/docs/reference/subscriptions/create
|
32 |
*/
|
33 |
+
$subscription = $customer->createSubscription([
|
34 |
+
"amount" => [
|
35 |
+
"value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings
|
36 |
+
"currency" => "EUR"
|
37 |
+
],
|
38 |
+
"times" => 12,
|
39 |
+
"interval" => "1 month",
|
40 |
+
"description" => "Subscription #{$subscriptionId}",
|
41 |
+
"method" => NULL,
|
42 |
+
"webhookUrl" => "https://example.com/webhook.php?subscription_id={$subscriptionId}",
|
43 |
+
]);
|
44 |
/*
|
45 |
* The subscription will be either pending or active depending on whether the customer has
|
46 |
* a pending or valid mandate. If the customer has no mandates an error is returned. You
|
47 |
* should then set up a "first payment" for the customer (example 14).
|
48 |
*/
|
49 |
+
echo "<p>The subscription status is '" . htmlspecialchars($subscription->status) . "'.</p>\n";
|
50 |
echo "<p>";
|
51 |
echo '<a href="' . $protocol . '://' . $hostname . $path . '/17-cancel-subscription.php?subscription_id=' . $subscription->id . '">18-cancel-subscription</a><br>';
|
52 |
echo "</p>";
|
53 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
54 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
55 |
+
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 17 - How to cancel a subscription.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
@@ -29,7 +27,7 @@ try {
|
|
29 |
/*
|
30 |
* The subscription status should now be canceled
|
31 |
*/
|
32 |
-
echo "<p>The subscription status is now: '" .
|
33 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
34 |
-
echo "API call failed: " .
|
35 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 17 - How to cancel a subscription.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
27 |
/*
|
28 |
* The subscription status should now be canceled
|
29 |
*/
|
30 |
+
echo "<p>The subscription status is now: '" . htmlspecialchars($canceledSubscription->status) . "'.</p>\n";
|
31 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
32 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
33 |
+
}
|
@@ -1,10 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 18 - Updating an existing customer via the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
@@ -22,9 +20,10 @@ try {
|
|
22 |
$customer->name = "Luke Sky";
|
23 |
$customer->email = "luke@example.org";
|
24 |
$customer->locale = "en_US";
|
25 |
-
$customer->metadata->isJedi =
|
26 |
$customer->update();
|
27 |
-
|
|
|
28 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
29 |
-
echo "API call failed: " .
|
30 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 18 - Updating an existing customer via the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
20 |
$customer->name = "Luke Sky";
|
21 |
$customer->email = "luke@example.org";
|
22 |
$customer->locale = "en_US";
|
23 |
+
$customer->metadata->isJedi = TRUE;
|
24 |
$customer->update();
|
25 |
+
|
26 |
+
echo "<p>Customer updated: " . htmlspecialchars($customer->name) . "</p>";
|
27 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
28 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
29 |
+
}
|
@@ -1,11 +1,9 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 19 - Updating an existing profile via the Mollie API.
|
7 |
*/
|
8 |
-
try
|
|
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
@@ -19,13 +17,15 @@ try {
|
|
19 |
*
|
20 |
* @See https://docs.mollie.com/reference/v2/profiles-api/update-profile
|
21 |
*/
|
22 |
-
$profile->name
|
23 |
$profile->website = 'www.mollie.com';
|
24 |
-
$profile->email
|
25 |
-
$profile->phone
|
26 |
$profile->categoryCode = 5399;
|
27 |
$profile->update();
|
28 |
-
echo "<p>Profile updated: " .
|
29 |
-
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
30 |
-
echo "<p>API call failed: " . \htmlspecialchars($e->getMessage()) . "</p>";
|
31 |
}
|
|
|
|
|
|
|
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 19 - Updating an existing profile via the Mollie API.
|
4 |
*/
|
5 |
+
try
|
6 |
+
{
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
17 |
*
|
18 |
* @See https://docs.mollie.com/reference/v2/profiles-api/update-profile
|
19 |
*/
|
20 |
+
$profile->name = "Mollie B.V.";
|
21 |
$profile->website = 'www.mollie.com';
|
22 |
+
$profile->email = 'info@mollie.com';
|
23 |
+
$profile->phone = '0612345670';
|
24 |
$profile->categoryCode = 5399;
|
25 |
$profile->update();
|
26 |
+
echo "<p>Profile updated: " . htmlspecialchars($profile->name) . "</p>";
|
|
|
|
|
27 |
}
|
28 |
+
catch (\Mollie\Api\Exceptions\ApiException $e)
|
29 |
+
{
|
30 |
+
echo "<p>API call failed: " . htmlspecialchars($e->getMessage()) . "</p>";
|
31 |
+
}
|
@@ -1,37 +1,37 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 22 - Create a customer, mandate and subscription via the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "initialize_with_oauth.php";
|
|
|
13 |
/*
|
14 |
-
|
15 |
-
|
16 |
$invoices = $mollie->invoices->all();
|
17 |
foreach ($invoices as $invoice) {
|
18 |
-
echo '<li><b>Invoice ' .
|
19 |
echo '<br>Status: <b>' . $invoice->status;
|
20 |
echo '<table border="1"><tr><th>Period</th><th>Description</th><th>Count</th><th>VAT Percentage</th><th>Amount</th></tr>';
|
21 |
foreach ($invoice->lines as $line) {
|
22 |
echo '<tr>';
|
23 |
-
echo '<td>' .
|
24 |
-
echo '<td>' .
|
25 |
-
echo '<td align="right">' .
|
26 |
-
echo '<td align="right">' .
|
27 |
-
echo '<td align="right">' .
|
28 |
echo '</tr>';
|
29 |
}
|
30 |
-
echo '<tr><th colspan="5" align="right">Gross Total</th><th align="right">' .
|
31 |
echo '</table>';
|
32 |
-
echo '<a href="'
|
33 |
echo '</li>';
|
34 |
}
|
|
|
35 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
36 |
-
echo "API call failed: " .
|
37 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 22 - Create a customer, mandate and subscription via the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "initialize_with_oauth.php";
|
11 |
+
|
12 |
/*
|
13 |
+
* Get all the activated methods for this API key.
|
14 |
+
*/
|
15 |
$invoices = $mollie->invoices->all();
|
16 |
foreach ($invoices as $invoice) {
|
17 |
+
echo '<li><b>Invoice ' . htmlspecialchars($invoice->reference) . ':</b> (' . htmlspecialchars($invoice->issuedAt) . ')';
|
18 |
echo '<br>Status: <b>' . $invoice->status;
|
19 |
echo '<table border="1"><tr><th>Period</th><th>Description</th><th>Count</th><th>VAT Percentage</th><th>Amount</th></tr>';
|
20 |
foreach ($invoice->lines as $line) {
|
21 |
echo '<tr>';
|
22 |
+
echo '<td>' . htmlspecialchars($line->period) . '</td>';
|
23 |
+
echo '<td>' . htmlspecialchars($line->description) . '</td>';
|
24 |
+
echo '<td align="right">' . htmlspecialchars($line->count) . '</td>';
|
25 |
+
echo '<td align="right">' . htmlspecialchars($line->vatPercentage) . '</td>';
|
26 |
+
echo '<td align="right">' . htmlspecialchars($line->amount->currency . " " . $line->amount->value) . '</td>';
|
27 |
echo '</tr>';
|
28 |
}
|
29 |
+
echo '<tr><th colspan="5" align="right">Gross Total</th><th align="right">' . htmlspecialchars($invoice->grossAmount->value . " " . $invoice->grossAmount->currency) . '</th></tr>';
|
30 |
echo '</table>';
|
31 |
+
echo '<a href="'. $invoice->_links->pdf->href .'" target="_blank">Click here to open PDF</a>';
|
32 |
echo '</li>';
|
33 |
}
|
34 |
+
|
35 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
36 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
37 |
+
}
|
@@ -1,44 +1,55 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 22 - Create a customer, mandate and subscription via the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "initialize.php";
|
|
|
13 |
/*
|
14 |
* Customer creation parameters.
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/customers-api/create-customer
|
17 |
*/
|
18 |
-
$customer = $mollie->customers->create([
|
|
|
|
|
|
|
|
|
19 |
echo "<p>Customer created with id " . $customer->id . "</p>";
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
echo "<p>Mandate created with id " . $mandate->id . "</p>";
|
|
|
22 |
/*
|
23 |
* Generate a unique subscription id for this example. It is important to include this unique attribute
|
24 |
* in the webhookUrl (below) so new payments can be associated with this subscription.
|
25 |
*/
|
26 |
-
$subscriptionId =
|
|
|
27 |
$subscription = $customer->createSubscription([
|
28 |
"amount" => [
|
29 |
-
"value" => "10.00",
|
30 |
-
|
31 |
-
"currency" => "EUR",
|
32 |
],
|
33 |
-
"times" => 12,
|
34 |
-
|
35 |
-
"interval" => "1 months",
|
36 |
-
// every month
|
37 |
"description" => "Subscription #{$subscriptionId}",
|
38 |
"webhookUrl" => "https://example.com/webhook.php?subscription_id={$subscriptionId}",
|
39 |
-
"metadata" => [
|
|
|
|
|
40 |
]);
|
|
|
41 |
echo "<p>Subscription created with id " . $subscription->id . "</p>";
|
42 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
43 |
-
echo "API call failed: " .
|
44 |
-
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 22 - Create a customer, mandate and subscription via the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Customer creation parameters.
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/customers-api/create-customer
|
16 |
*/
|
17 |
+
$customer = $mollie->customers->create([
|
18 |
+
"name" => 'Example name',
|
19 |
+
"email" => 'info@example.com',
|
20 |
+
]);
|
21 |
+
|
22 |
echo "<p>Customer created with id " . $customer->id . "</p>";
|
23 |
+
|
24 |
+
$mandate = $customer->createMandate([
|
25 |
+
"method" => \Mollie\Api\Types\MandateMethod::DIRECTDEBIT,
|
26 |
+
"consumerAccount" => 'NL34ABNA0243341423',
|
27 |
+
"consumerName" => 'B. A. Example',
|
28 |
+
]);
|
29 |
+
|
30 |
echo "<p>Mandate created with id " . $mandate->id . "</p>";
|
31 |
+
|
32 |
/*
|
33 |
* Generate a unique subscription id for this example. It is important to include this unique attribute
|
34 |
* in the webhookUrl (below) so new payments can be associated with this subscription.
|
35 |
*/
|
36 |
+
$subscriptionId = time();
|
37 |
+
|
38 |
$subscription = $customer->createSubscription([
|
39 |
"amount" => [
|
40 |
+
"value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings
|
41 |
+
"currency" => "EUR"
|
|
|
42 |
],
|
43 |
+
"times" => 12, // recurring membership for 1 year
|
44 |
+
"interval" => "1 months", // every month
|
|
|
|
|
45 |
"description" => "Subscription #{$subscriptionId}",
|
46 |
"webhookUrl" => "https://example.com/webhook.php?subscription_id={$subscriptionId}",
|
47 |
+
"metadata" => [
|
48 |
+
"subscription_id" => $subscriptionId,
|
49 |
+
],
|
50 |
]);
|
51 |
+
|
52 |
echo "<p>Subscription created with id " . $subscription->id . "</p>";
|
53 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
54 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
55 |
+
}
|
@@ -1,17 +1,17 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
Example 23 - Delete a customer from mollie api.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "initialize.php";
|
|
|
13 |
$mollie->customers->delete("customer_id");
|
14 |
echo "Customer deleted!";
|
|
|
15 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
16 |
-
echo "API call failed: " .
|
17 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
Example 23 - Delete a customer from mollie api.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "initialize.php";
|
11 |
+
|
12 |
$mollie->customers->delete("customer_id");
|
13 |
echo "Customer deleted!";
|
14 |
+
|
15 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
16 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
17 |
}
|
@@ -1,28 +1,31 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
Example 24 - Revoke a customer mandate
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "initialize.php";
|
|
|
13 |
/*
|
14 |
* Retrieve an existing customer by his customerId
|
15 |
*/
|
16 |
$customer = $mollie->customers->get("cst_cUa8HjKBus");
|
|
|
17 |
/*
|
18 |
* Retrieve an existing mandate by his mandateId
|
19 |
*/
|
20 |
$mandate = $customer->getMandate("mdt_pa3s7rGnrC");
|
|
|
21 |
/*
|
22 |
* Revoke the mandate
|
23 |
*/
|
24 |
$mandate->revoke();
|
|
|
25 |
echo "<p>Mandate has been successfully revoked.</p>";
|
|
|
26 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
27 |
-
echo "API call failed: " .
|
28 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
Example 24 - Revoke a customer mandate
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Retrieve an existing customer by his customerId
|
14 |
*/
|
15 |
$customer = $mollie->customers->get("cst_cUa8HjKBus");
|
16 |
+
|
17 |
/*
|
18 |
* Retrieve an existing mandate by his mandateId
|
19 |
*/
|
20 |
$mandate = $customer->getMandate("mdt_pa3s7rGnrC");
|
21 |
+
|
22 |
/*
|
23 |
* Revoke the mandate
|
24 |
*/
|
25 |
$mandate->revoke();
|
26 |
+
|
27 |
echo "<p>Mandate has been successfully revoked.</p>";
|
28 |
+
|
29 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
30 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
31 |
}
|
@@ -1,33 +1,35 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 25 - Updating an existing subscription via the Mollie API.
|
7 |
*/
|
|
|
8 |
use Mollie\Api\Exceptions\ApiException;
|
|
|
9 |
try {
|
10 |
/*
|
11 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
12 |
*/
|
13 |
require "./initialize.php";
|
|
|
14 |
/*
|
15 |
* Retrieve an existing subscription
|
16 |
*/
|
17 |
$customer = $mollie->customers->get("cst_cUe8HjeBuz");
|
18 |
$subscription = $customer->getSubscription("sub_DRjwaT5qHx");
|
|
|
19 |
/**
|
20 |
* Subscription fields that can be updated are described by the link:
|
21 |
* See https://docs.mollie.com/reference/v2/subscriptions-api/update-subscription
|
22 |
*/
|
23 |
$subscription->times = 10;
|
24 |
-
$subscription->startDate = '2018-12-02';
|
25 |
-
|
26 |
-
$subscription->amount = (object) ['value' => '12.12', 'currency' => 'EUR'];
|
27 |
$subscription->webhookUrl = 'https://some-webhook-url.com/with/path';
|
28 |
$subscription->description = 'Monthly subscription';
|
29 |
$subscription->update();
|
|
|
30 |
echo "<p>Subscription updated: " . $subscription->id . "</p>";
|
31 |
-
} catch (
|
32 |
-
echo "API call failed: " .
|
33 |
-
}
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
/*
|
4 |
* Example 25 - Updating an existing subscription via the Mollie API.
|
5 |
*/
|
6 |
+
|
7 |
use Mollie\Api\Exceptions\ApiException;
|
8 |
+
|
9 |
try {
|
10 |
/*
|
11 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
12 |
*/
|
13 |
require "./initialize.php";
|
14 |
+
|
15 |
/*
|
16 |
* Retrieve an existing subscription
|
17 |
*/
|
18 |
$customer = $mollie->customers->get("cst_cUe8HjeBuz");
|
19 |
$subscription = $customer->getSubscription("sub_DRjwaT5qHx");
|
20 |
+
|
21 |
/**
|
22 |
* Subscription fields that can be updated are described by the link:
|
23 |
* See https://docs.mollie.com/reference/v2/subscriptions-api/update-subscription
|
24 |
*/
|
25 |
$subscription->times = 10;
|
26 |
+
$subscription->startDate = '2018-12-02'; // Year-month-day
|
27 |
+
$subscription->amount = (object)['value' => '12.12', 'currency' => 'EUR'];
|
|
|
28 |
$subscription->webhookUrl = 'https://some-webhook-url.com/with/path';
|
29 |
$subscription->description = 'Monthly subscription';
|
30 |
$subscription->update();
|
31 |
+
|
32 |
echo "<p>Subscription updated: " . $subscription->id . "</p>";
|
33 |
+
} catch (ApiException $e) {
|
34 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
35 |
+
}
|
@@ -1,26 +1,106 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 26 - How to create a new order in the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Order creation parameters.
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/orders-api/create-order
|
17 |
*/
|
18 |
-
$order = $mollie->orders->create([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
/*
|
20 |
* Send the customer off to complete the order payment.
|
21 |
* This request should always be a GET, thus we enforce 303 http response code
|
22 |
*/
|
23 |
-
|
24 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
25 |
-
echo "API call failed: " .
|
26 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 26 - How to create a new order in the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Order creation parameters.
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/orders-api/create-order
|
16 |
*/
|
17 |
+
$order = $mollie->orders->create([
|
18 |
+
"amount" => [
|
19 |
+
"value" => "1027.99",
|
20 |
+
"currency" => "EUR"
|
21 |
+
],
|
22 |
+
"billingAddress" => [
|
23 |
+
"streetAndNumber" => "Keizersgracht 313",
|
24 |
+
"postalCode" => "1016 EE",
|
25 |
+
"city" => "Amsterdam",
|
26 |
+
"country" => "nl",
|
27 |
+
"givenName" => "Luke",
|
28 |
+
"familyName" => "Skywalker",
|
29 |
+
"email" => "luke@skywalker.com",
|
30 |
+
],
|
31 |
+
"shippingAddress" => [
|
32 |
+
"streetAndNumber" => "Keizersgracht 313",
|
33 |
+
"postalCode" => "1016 EE",
|
34 |
+
"city" => "Amsterdam",
|
35 |
+
"country" => "nl",
|
36 |
+
"givenName" => "Luke",
|
37 |
+
"familyName" => "Skywalker",
|
38 |
+
"email" => "luke@skywalker.com",
|
39 |
+
],
|
40 |
+
"metadata" => [
|
41 |
+
"order_id" => "1337",
|
42 |
+
"description" => "Lego cars"
|
43 |
+
],
|
44 |
+
"consumerDateOfBirth" => "1958-01-31",
|
45 |
+
"locale" => "nl_NL",
|
46 |
+
"orderNumber" => "1337",
|
47 |
+
"redirectUrl" => "https://example.org/redirect",
|
48 |
+
"webhookUrl" => "https://example.org/webhook",
|
49 |
+
"method" => "ideal",
|
50 |
+
"lines" => [
|
51 |
+
[
|
52 |
+
"sku" => "5702016116977",
|
53 |
+
"name" => "LEGO 42083 Bugatti Chiron",
|
54 |
+
"productUrl" => "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083",
|
55 |
+
"imageUrl" => 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$',
|
56 |
+
"quantity" => 2,
|
57 |
+
"vatRate" => "21.00",
|
58 |
+
"unitPrice" => [
|
59 |
+
"currency" => "EUR",
|
60 |
+
"value" => "399.00"
|
61 |
+
],
|
62 |
+
"totalAmount" => [
|
63 |
+
"currency" => "EUR",
|
64 |
+
"value" => "698.00"
|
65 |
+
],
|
66 |
+
"discountAmount" => [
|
67 |
+
"currency" => "EUR",
|
68 |
+
"value" => "100.00"
|
69 |
+
],
|
70 |
+
"vatAmount" => [
|
71 |
+
"currency" => "EUR",
|
72 |
+
"value" => "121.14"
|
73 |
+
]
|
74 |
+
],
|
75 |
+
[
|
76 |
+
"type" => "digital",
|
77 |
+
"sku" => "5702015594028",
|
78 |
+
"name" => "LEGO 42056 Porsche 911 GT3 RS",
|
79 |
+
"productUrl" => "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056",
|
80 |
+
"imageUrl" => 'https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$',
|
81 |
+
"quantity" => 1,
|
82 |
+
"vatRate" => "21.00",
|
83 |
+
"unitPrice" => [
|
84 |
+
"currency" => "EUR",
|
85 |
+
"value" => "329.99"
|
86 |
+
],
|
87 |
+
"totalAmount" => [
|
88 |
+
"currency" => "EUR",
|
89 |
+
"value" => "329.99"
|
90 |
+
],
|
91 |
+
"vatAmount" => [
|
92 |
+
"currency" => "EUR",
|
93 |
+
"value" => "57.27"
|
94 |
+
]
|
95 |
+
]
|
96 |
+
]
|
97 |
+
]);
|
98 |
+
|
99 |
/*
|
100 |
* Send the customer off to complete the order payment.
|
101 |
* This request should always be a GET, thus we enforce 303 http response code
|
102 |
*/
|
103 |
+
header("Location: " . $order->getCheckoutUrl(), true, 303);
|
104 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
105 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
106 |
}
|
@@ -1,15 +1,14 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 27 - Handle an order status change using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* After your webhook has been called with the order ID in its body, you'd like
|
15 |
* to handle the order's status change. This is how you can do that.
|
@@ -17,6 +16,7 @@ try {
|
|
17 |
* See: https://docs.mollie.com/reference/v2/orders-api/get-order
|
18 |
*/
|
19 |
$order = $mollie->orders->get("ord_pbjz8x");
|
|
|
20 |
if ($order->isPaid() || $order->isAuthorized()) {
|
21 |
echo "The payment for your order " . $order->id . " has been processed.";
|
22 |
echo "\nYour order is now being prepared for shipment.";
|
@@ -30,5 +30,5 @@ try {
|
|
30 |
echo "Your order " . $order->id . " is completed.";
|
31 |
}
|
32 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
33 |
-
echo "API call failed: " .
|
34 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 27 - Handle an order status change using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* After your webhook has been called with the order ID in its body, you'd like
|
14 |
* to handle the order's status change. This is how you can do that.
|
16 |
* See: https://docs.mollie.com/reference/v2/orders-api/get-order
|
17 |
*/
|
18 |
$order = $mollie->orders->get("ord_pbjz8x");
|
19 |
+
|
20 |
if ($order->isPaid() || $order->isAuthorized()) {
|
21 |
echo "The payment for your order " . $order->id . " has been processed.";
|
22 |
echo "\nYour order is now being prepared for shipment.";
|
30 |
echo "Your order " . $order->id . " is completed.";
|
31 |
}
|
32 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
33 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
34 |
}
|
@@ -1,15 +1,14 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 28 - Cancel an order using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Cancel the order with ID "ord_pbjz8x"
|
15 |
*
|
@@ -23,5 +22,5 @@ try {
|
|
23 |
echo "Unable to cancel your order " . $order->id . ".";
|
24 |
}
|
25 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
26 |
-
echo "API call failed: " .
|
27 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 28 - Cancel an order using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Cancel the order with ID "ord_pbjz8x"
|
14 |
*
|
22 |
echo "Unable to cancel your order " . $order->id . ".";
|
23 |
}
|
24 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
25 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
26 |
}
|
@@ -1,16 +1,16 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 29 - List orders using the Mollie API.
|
7 |
*/
|
|
|
8 |
use Mollie\Api\Resources\OrderCollection;
|
|
|
9 |
try {
|
10 |
/*
|
11 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
12 |
*/
|
13 |
require "./initialize.php";
|
|
|
14 |
/*
|
15 |
* List the most recent orders
|
16 |
*
|
@@ -18,29 +18,32 @@ try {
|
|
18 |
*/
|
19 |
echo '<ul>';
|
20 |
$latestOrders = $mollie->orders->page();
|
21 |
-
|
|
|
22 |
$previousOrders = $latestOrders->next();
|
23 |
-
|
24 |
echo '</ul>';
|
25 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
26 |
-
echo "API call failed: " .
|
27 |
}
|
|
|
28 |
function printOrders($orders)
|
29 |
{
|
30 |
if (empty($orders)) {
|
31 |
-
return;
|
32 |
}
|
|
|
33 |
foreach ($orders as $order) {
|
34 |
-
echo '<li><b>Order ' .
|
35 |
-
echo '<br>Status: <b>' .
|
36 |
echo '<table border="1"><tr><th>Billed to</th><th>Shipped to</th><th>Total amount</th></tr>';
|
37 |
echo '<tr>';
|
38 |
-
echo '<td>' .
|
39 |
-
echo '<td>' .
|
40 |
-
echo '<td>' .
|
41 |
echo '</tr>';
|
42 |
echo '</table>';
|
43 |
-
echo '<a href="'
|
44 |
echo '</li>';
|
45 |
}
|
46 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 29 - List orders using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
use Mollie\Api\Resources\OrderCollection;
|
7 |
+
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
13 |
+
|
14 |
/*
|
15 |
* List the most recent orders
|
16 |
*
|
18 |
*/
|
19 |
echo '<ul>';
|
20 |
$latestOrders = $mollie->orders->page();
|
21 |
+
printOrders($latestOrders);
|
22 |
+
|
23 |
$previousOrders = $latestOrders->next();
|
24 |
+
printOrders($previousOrders);
|
25 |
echo '</ul>';
|
26 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
27 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
28 |
}
|
29 |
+
|
30 |
function printOrders($orders)
|
31 |
{
|
32 |
if (empty($orders)) {
|
33 |
+
return ;
|
34 |
}
|
35 |
+
|
36 |
foreach ($orders as $order) {
|
37 |
+
echo '<li><b>Order ' . htmlspecialchars($order->id) . ':</b> (' . htmlspecialchars($order->createdAt) . ')';
|
38 |
+
echo '<br>Status: <b>' . htmlspecialchars($order->status);
|
39 |
echo '<table border="1"><tr><th>Billed to</th><th>Shipped to</th><th>Total amount</th></tr>';
|
40 |
echo '<tr>';
|
41 |
+
echo '<td>' . htmlspecialchars($order->shippingAddress->givenName) . ' ' . htmlspecialchars($order->shippingAddress->familyName) . '</td>';
|
42 |
+
echo '<td>' . htmlspecialchars($order->billingAddress->givenName) . ' ' . htmlspecialchars($order->billingAddress->familyName) . '</td>';
|
43 |
+
echo '<td>' . htmlspecialchars($order->amount->currency) . str_replace('.', ',', htmlspecialchars($order->amount->value)) . '</td>';
|
44 |
echo '</tr>';
|
45 |
echo '</table>';
|
46 |
+
echo '<a href="'. $order->getCheckoutUrl() .'" target="_blank">Click here to pay</a>';
|
47 |
echo '</li>';
|
48 |
}
|
49 |
}
|
@@ -1,27 +1,36 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 30 - Cancel an order line using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Cancel an order line with ID "odl_dgtxyl" for order ID "ord_8wmqcHMN4U"
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/orders-api/cancel-order-line
|
17 |
*/
|
|
|
18 |
$orderId = 'ord_8wmqcHMN4U';
|
19 |
$lineId = 'odl_dgtxyl';
|
|
|
20 |
$order = $mollie->orders->get($orderId);
|
21 |
$line = $order->lines()->get($lineId);
|
22 |
if ($line && $line->isCancelable) {
|
23 |
-
$order->cancelLines([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
$updatedOrder = $mollie->orders->get($orderId);
|
|
|
25 |
echo 'Your order ' . $order->id . ' was updated:';
|
26 |
foreach ($order->lines as $line) {
|
27 |
echo $line->description . '. Status: <b>' . $line->status . '</b>.';
|
@@ -30,5 +39,5 @@ try {
|
|
30 |
echo "Unable to cancel line " . $lineId . " for your order " . $orderId . ".";
|
31 |
}
|
32 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
33 |
-
echo "API call failed: " .
|
34 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 30 - Cancel an order line using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Cancel an order line with ID "odl_dgtxyl" for order ID "ord_8wmqcHMN4U"
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/orders-api/cancel-order-line
|
16 |
*/
|
17 |
+
|
18 |
$orderId = 'ord_8wmqcHMN4U';
|
19 |
$lineId = 'odl_dgtxyl';
|
20 |
+
|
21 |
$order = $mollie->orders->get($orderId);
|
22 |
$line = $order->lines()->get($lineId);
|
23 |
if ($line && $line->isCancelable) {
|
24 |
+
$order->cancelLines([
|
25 |
+
'lines' => [
|
26 |
+
'id' => $lineId,
|
27 |
+
// # You can set a quantity if you like:
|
28 |
+
// 'quantity' => 1,
|
29 |
+
],
|
30 |
+
]);
|
31 |
+
|
32 |
$updatedOrder = $mollie->orders->get($orderId);
|
33 |
+
|
34 |
echo 'Your order ' . $order->id . ' was updated:';
|
35 |
foreach ($order->lines as $line) {
|
36 |
echo $line->description . '. Status: <b>' . $line->status . '</b>.';
|
39 |
echo "Unable to cancel line " . $lineId . " for your order " . $orderId . ".";
|
40 |
}
|
41 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
42 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
43 |
}
|
@@ -1,26 +1,27 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 31 - Create a shipment for an entire order using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Create a shipment for the entire order with ID "ord_8wmqcHMN4U"
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/shipments-api/create-shipment
|
17 |
*/
|
|
|
18 |
$order = $this->getOrder('ord_8wmqcHMN4U');
|
19 |
$shipment = $order->shipAll();
|
20 |
-
|
|
|
21 |
foreach ($shipment->lines as $line) {
|
22 |
echo $line->name . ' - status: <b>' . $line->status . '</b>.';
|
23 |
}
|
24 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
25 |
-
echo "API call failed: " .
|
26 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 31 - Create a shipment for an entire order using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Create a shipment for the entire order with ID "ord_8wmqcHMN4U"
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/shipments-api/create-shipment
|
16 |
*/
|
17 |
+
|
18 |
$order = $this->getOrder('ord_8wmqcHMN4U');
|
19 |
$shipment = $order->shipAll();
|
20 |
+
|
21 |
+
echo 'A shipment with ID ' . $shipment->id. ' has been created for your order with ID ' . $order->id . '.';
|
22 |
foreach ($shipment->lines as $line) {
|
23 |
echo $line->name . ' - status: <b>' . $line->status . '</b>.';
|
24 |
}
|
25 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
26 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
27 |
}
|
@@ -1,28 +1,42 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 32 - Create a shipment for part of an order using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Create a shipment for only two lines of the order with ID "ord_8wmqcHMN4U".
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/shipments-api/create-shipment
|
17 |
*/
|
|
|
18 |
$order = $this->getOrder('ord_8wmqcHMN4U');
|
19 |
$lineId1 = $order->lines()[0]->id;
|
20 |
$lineId2 = $order->lines()[1]->id;
|
21 |
-
$shipment = $order->createShipment(
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
foreach ($shipment->lines as $line) {
|
24 |
echo $line->name . '- status: <b>' . $line->status . '</b>.';
|
25 |
}
|
26 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
27 |
-
echo "API call failed: " .
|
28 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 32 - Create a shipment for part of an order using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Create a shipment for only two lines of the order with ID "ord_8wmqcHMN4U".
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/shipments-api/create-shipment
|
16 |
*/
|
17 |
+
|
18 |
$order = $this->getOrder('ord_8wmqcHMN4U');
|
19 |
$lineId1 = $order->lines()[0]->id;
|
20 |
$lineId2 = $order->lines()[1]->id;
|
21 |
+
$shipment = $order->createShipment(
|
22 |
+
[
|
23 |
+
'lines' => [
|
24 |
+
[
|
25 |
+
'id' => $lineId1,
|
26 |
+
// assume all is shipped if no quantity is specified
|
27 |
+
],
|
28 |
+
[
|
29 |
+
'id' => $lineId2,
|
30 |
+
'quantity' => 1, // you can set the quantity if not all is shipped at once
|
31 |
+
],
|
32 |
+
],
|
33 |
+
]
|
34 |
+
);
|
35 |
+
|
36 |
+
echo 'A shipment with ID ' . $shipment->id. ' has been created for your order with ID ' . $order->id . '.';
|
37 |
foreach ($shipment->lines as $line) {
|
38 |
echo $line->name . '- status: <b>' . $line->status . '</b>.';
|
39 |
}
|
40 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
41 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
42 |
}
|
@@ -1,26 +1,27 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 33 - Retrieve a shipment using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Retrieve a shipment with ID "shp_3wmsgCJN4U" for the order with ID "ord_8wmqcHMN4U".
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/shipments-api/get-shipment
|
17 |
*/
|
|
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
$shipment = $order->getShipment("shp_3wmsgCJN4U");
|
20 |
-
|
|
|
21 |
foreach ($shipment->lines as $line) {
|
22 |
echo $line->name . ' - status: <b>' . $line->status . '</b>.';
|
23 |
}
|
24 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
25 |
-
echo "API call failed: " .
|
26 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 33 - Retrieve a shipment using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Retrieve a shipment with ID "shp_3wmsgCJN4U" for the order with ID "ord_8wmqcHMN4U".
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/shipments-api/get-shipment
|
16 |
*/
|
17 |
+
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
$shipment = $order->getShipment("shp_3wmsgCJN4U");
|
20 |
+
|
21 |
+
echo 'Shipment with ID ' . $shipment->id. ' for order with ID ' . $order->id . '.';
|
22 |
foreach ($shipment->lines as $line) {
|
23 |
echo $line->name . ' - status: <b>' . $line->status . '</b>.';
|
24 |
}
|
25 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
26 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
27 |
}
|
@@ -1,22 +1,23 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 34 - List shipment for an order using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Listing shipments for the order with ID "ord_8wmqcHMN4U".
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/shipments-api/get-shipment
|
17 |
*/
|
|
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
$shipments = $order->shipments();
|
|
|
20 |
echo 'Shipments for order with ID ' . $order->id . ':';
|
21 |
foreach ($shipments as $shipment) {
|
22 |
echo 'Shipment ' . $shipment->id . '. Items:';
|
@@ -25,5 +26,5 @@ try {
|
|
25 |
}
|
26 |
}
|
27 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
28 |
-
echo "API call failed: " .
|
29 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 34 - List shipment for an order using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Listing shipments for the order with ID "ord_8wmqcHMN4U".
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/shipments-api/get-shipment
|
16 |
*/
|
17 |
+
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
$shipments = $order->shipments();
|
20 |
+
|
21 |
echo 'Shipments for order with ID ' . $order->id . ':';
|
22 |
foreach ($shipments as $shipment) {
|
23 |
echo 'Shipment ' . $shipment->id . '. Items:';
|
26 |
}
|
27 |
}
|
28 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
29 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
30 |
}
|
@@ -1,24 +1,25 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 35 - Refund all eligible items for an order using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Refund all eligible items for an order with ID "ord_8wmqcHMN4U".
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/orders-api/create-order-refund
|
17 |
*/
|
|
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
$refund = $order->refundAll();
|
|
|
20 |
echo 'Refund ' . $refund->id . ' was created for order ' . $order->id;
|
21 |
echo 'You will receive ' . $refund->amount->currency . $refund->amount->value;
|
22 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
23 |
-
echo "API call failed: " .
|
24 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 35 - Refund all eligible items for an order using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Refund all eligible items for an order with ID "ord_8wmqcHMN4U".
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/orders-api/create-order-refund
|
16 |
*/
|
17 |
+
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
$refund = $order->refundAll();
|
20 |
+
|
21 |
echo 'Refund ' . $refund->id . ' was created for order ' . $order->id;
|
22 |
echo 'You will receive ' . $refund->amount->currency . $refund->amount->value;
|
23 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
24 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
25 |
}
|
@@ -1,24 +1,33 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 36 - Refund some items for an order using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Refund 1 item of order line "odl_dgtxyl" for an order with ID "ord_8wmqcHMN4U".
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/orders-api/create-order-refund
|
17 |
*/
|
|
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
-
$refund = $order->refund([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
echo 'Refund ' . $refund->id . ' was created for part of your order ' . $order->id;
|
21 |
echo 'You will receive ' . $refund->amount->currency . $refund->amount->value;
|
22 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
23 |
-
echo "API call failed: " .
|
24 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 36 - Refund some items for an order using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Refund 1 item of order line "odl_dgtxyl" for an order with ID "ord_8wmqcHMN4U".
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/orders-api/create-order-refund
|
16 |
*/
|
17 |
+
|
18 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
19 |
+
$refund = $order->refund([
|
20 |
+
'lines' => [
|
21 |
+
[
|
22 |
+
'id' => 'odl_dgtxyl',
|
23 |
+
'quantity' => 1,
|
24 |
+
]
|
25 |
+
],
|
26 |
+
"description" => "Required quantity not in stock, refunding one photo book.",
|
27 |
+
]);
|
28 |
+
|
29 |
echo 'Refund ' . $refund->id . ' was created for part of your order ' . $order->id;
|
30 |
echo 'You will receive ' . $refund->amount->currency . $refund->amount->value;
|
31 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
32 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
33 |
}
|
@@ -1,33 +1,40 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 37 - Update shipment tracking information using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Update the tracking information for a shipment with ID "shp_3wmsgCJN4U" and
|
15 |
* order ID "ord_8wmqcHMN4U"
|
16 |
*
|
17 |
* See: https://docs.mollie.com/reference/v2/shipments-api/update-shipment
|
18 |
*/
|
|
|
19 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
20 |
$shipment = $order->getShipment("shp_3wmsgCJN4U");
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
22 |
$shipment = $shipment->update();
|
23 |
-
|
|
|
24 |
echo 'Tracking information updated:';
|
25 |
echo 'Carrier: ' . $shipment->tracking->carrier;
|
26 |
echo 'Code: ' . $shipment->tracking->code;
|
27 |
echo 'Url: ' . $shipment->tracking->url;
|
|
|
28 |
foreach ($shipment->lines as $line) {
|
29 |
echo $line->name . ' - status: <b>' . $line->status . '</b>.';
|
30 |
}
|
31 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
32 |
-
echo "API call failed: " .
|
33 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 37 - Update shipment tracking information using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Update the tracking information for a shipment with ID "shp_3wmsgCJN4U" and
|
14 |
* order ID "ord_8wmqcHMN4U"
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/shipments-api/update-shipment
|
17 |
*/
|
18 |
+
|
19 |
$order = $mollie->orders->get('ord_8wmqcHMN4U');
|
20 |
$shipment = $order->getShipment("shp_3wmsgCJN4U");
|
21 |
+
|
22 |
+
$shipment->tracking = [
|
23 |
+
'carrier' => 'PostNL',
|
24 |
+
'code' => '3SKABA000000000',
|
25 |
+
'url' => 'http://postnl.nl/tracktrace/?B=3SKABA000000000&P=1016EE&D=NL&T=C',
|
26 |
+
];
|
27 |
$shipment = $shipment->update();
|
28 |
+
|
29 |
+
echo 'Shipment with ID ' . $shipment->id. ' for order with ID ' . $order->id . '.';
|
30 |
echo 'Tracking information updated:';
|
31 |
echo 'Carrier: ' . $shipment->tracking->carrier;
|
32 |
echo 'Code: ' . $shipment->tracking->code;
|
33 |
echo 'Url: ' . $shipment->tracking->url;
|
34 |
+
|
35 |
foreach ($shipment->lines as $line) {
|
36 |
echo $line->name . ' - status: <b>' . $line->status . '</b>.';
|
37 |
}
|
38 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
39 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
40 |
}
|
@@ -1,25 +1,27 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 38 - Retrieve a payment capture using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* Retrieve a capture with ID 'cpt_4qqhO89gsT' for payment with
|
15 |
* ID 'tr_WDqYK6vllg'.
|
16 |
*
|
17 |
* See: https://docs.mollie.com/reference/v2/captures-api/get-capture
|
18 |
*/
|
|
|
19 |
$payment = $mollie->payments->get('tr_WDqYK6vllg');
|
20 |
$capture = $payment->getCapture('cpt_4qqhO89gsT');
|
|
|
21 |
$amount = $capture->amount->currency . ' ' . $capture->amount->value;
|
|
|
22 |
echo 'Captured ' . $amount;
|
23 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
24 |
-
echo "API call failed: " .
|
25 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 38 - Retrieve a payment capture using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* Retrieve a capture with ID 'cpt_4qqhO89gsT' for payment with
|
14 |
* ID 'tr_WDqYK6vllg'.
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/captures-api/get-capture
|
17 |
*/
|
18 |
+
|
19 |
$payment = $mollie->payments->get('tr_WDqYK6vllg');
|
20 |
$capture = $payment->getCapture('cpt_4qqhO89gsT');
|
21 |
+
|
22 |
$amount = $capture->amount->currency . ' ' . $capture->amount->value;
|
23 |
+
|
24 |
echo 'Captured ' . $amount;
|
25 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
26 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
27 |
}
|
@@ -1,26 +1,27 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Example 39 - List captures for a payment using the Mollie API.
|
7 |
*/
|
|
|
8 |
try {
|
9 |
/*
|
10 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
11 |
*/
|
12 |
require "./initialize.php";
|
|
|
13 |
/*
|
14 |
* List captures for payment with ID 'tr_WDqYK6vllg'.
|
15 |
*
|
16 |
* See: https://docs.mollie.com/reference/v2/captures-api/list-captures
|
17 |
*/
|
|
|
18 |
$payment = $mollie->payments->get('tr_WDqYK6vllg');
|
19 |
$captures = $payment->captures();
|
|
|
20 |
foreach ($captures as $capture) {
|
21 |
$amount = $capture->amount->currency . ' ' . $capture->amount->value;
|
22 |
echo 'Captured ' . $amount . ' for payment ' . $payment->id;
|
23 |
}
|
24 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
25 |
-
echo "API call failed: " .
|
26 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Example 39 - List captures for a payment using the Mollie API.
|
4 |
*/
|
5 |
+
|
6 |
try {
|
7 |
/*
|
8 |
* Initialize the Mollie API library with your API key or OAuth access token.
|
9 |
*/
|
10 |
require "./initialize.php";
|
11 |
+
|
12 |
/*
|
13 |
* List captures for payment with ID 'tr_WDqYK6vllg'.
|
14 |
*
|
15 |
* See: https://docs.mollie.com/reference/v2/captures-api/list-captures
|
16 |
*/
|
17 |
+
|
18 |
$payment = $mollie->payments->get('tr_WDqYK6vllg');
|
19 |
$captures = $payment->captures();
|
20 |
+
|
21 |
foreach ($captures as $capture) {
|
22 |
$amount = $capture->amount->currency . ' ' . $capture->amount->value;
|
23 |
echo 'Captured ' . $amount . ' for payment ' . $payment->id;
|
24 |
}
|
25 |
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
26 |
+
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
27 |
}
|
@@ -1,14 +1,13 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Make sure to disable the display of errors in production code!
|
7 |
*/
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
11 |
require_once __DIR__ . "/../vendor/autoload.php";
|
|
|
12 |
/*
|
13 |
* Initialize the Mollie API library with your API key.
|
14 |
*
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Make sure to disable the display of errors in production code!
|
4 |
*/
|
5 |
+
ini_set('display_errors', 1);
|
6 |
+
ini_set('display_startup_errors', 1);
|
7 |
+
error_reporting(E_ALL);
|
8 |
+
|
9 |
require_once __DIR__ . "/../vendor/autoload.php";
|
10 |
+
|
11 |
/*
|
12 |
* Initialize the Mollie API library with your API key.
|
13 |
*
|
@@ -1,18 +1,18 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
/*
|
6 |
* Make sure to disable the display of errors in production code!
|
7 |
*/
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
11 |
require_once __DIR__ . "/../vendor/autoload.php";
|
|
|
12 |
/*
|
13 |
* Initialize the Mollie API library with OAuth.
|
14 |
*
|
15 |
* See: https://docs.mollie.com/oauth/overview
|
16 |
*/
|
17 |
$mollie = new \Mollie\Api\MollieApiClient();
|
18 |
-
$mollie->setAccessToken("access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ");
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
/*
|
4 |
* Make sure to disable the display of errors in production code!
|
5 |
*/
|
6 |
+
ini_set('display_errors', 1);
|
7 |
+
ini_set('display_startup_errors', 1);
|
8 |
+
error_reporting(E_ALL);
|
9 |
+
|
10 |
require_once __DIR__ . "/../vendor/autoload.php";
|
11 |
+
|
12 |
/*
|
13 |
* Initialize the Mollie API library with OAuth.
|
14 |
*
|
15 |
* See: https://docs.mollie.com/oauth/overview
|
16 |
*/
|
17 |
$mollie = new \Mollie\Api\MollieApiClient();
|
18 |
+
$mollie->setAccessToken("access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ");
|
@@ -0,0 +1 @@
|
|
|
1 |
+
*.txt
|
@@ -3,12 +3,14 @@
|
|
3 |
namespace Mollie\Api;
|
4 |
|
5 |
use Mollie\Api\Exceptions\IncompatiblePlatform;
|
|
|
6 |
class CompatibilityChecker
|
7 |
{
|
8 |
/**
|
9 |
* @var string
|
10 |
*/
|
11 |
const MIN_PHP_VERSION = "5.6.0";
|
|
|
12 |
/**
|
13 |
* @throws IncompatiblePlatform
|
14 |
* @return void
|
@@ -16,20 +18,29 @@ class CompatibilityChecker
|
|
16 |
public function checkCompatibility()
|
17 |
{
|
18 |
if (!$this->satisfiesPhpVersion()) {
|
19 |
-
throw new
|
|
|
|
|
|
|
20 |
}
|
|
|
21 |
if (!$this->satisfiesJsonExtension()) {
|
22 |
-
throw new
|
|
|
|
|
|
|
23 |
}
|
24 |
}
|
|
|
25 |
/**
|
26 |
* @return bool
|
27 |
* @codeCoverageIgnore
|
28 |
*/
|
29 |
public function satisfiesPhpVersion()
|
30 |
{
|
31 |
-
return (bool)
|
32 |
}
|
|
|
33 |
/**
|
34 |
* @return bool
|
35 |
* @codeCoverageIgnore
|
@@ -37,11 +48,12 @@ class CompatibilityChecker
|
|
37 |
public function satisfiesJsonExtension()
|
38 |
{
|
39 |
// Check by extension_loaded
|
40 |
-
if (
|
41 |
-
return
|
42 |
-
} elseif (
|
43 |
-
return
|
44 |
}
|
45 |
-
|
|
|
46 |
}
|
47 |
}
|
3 |
namespace Mollie\Api;
|
4 |
|
5 |
use Mollie\Api\Exceptions\IncompatiblePlatform;
|
6 |
+
|
7 |
class CompatibilityChecker
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
const MIN_PHP_VERSION = "5.6.0";
|
13 |
+
|
14 |
/**
|
15 |
* @throws IncompatiblePlatform
|
16 |
* @return void
|
18 |
public function checkCompatibility()
|
19 |
{
|
20 |
if (!$this->satisfiesPhpVersion()) {
|
21 |
+
throw new IncompatiblePlatform(
|
22 |
+
"The client requires PHP version >= " . self::MIN_PHP_VERSION . ", you have " . PHP_VERSION . ".",
|
23 |
+
IncompatiblePlatform::INCOMPATIBLE_PHP_VERSION
|
24 |
+
);
|
25 |
}
|
26 |
+
|
27 |
if (!$this->satisfiesJsonExtension()) {
|
28 |
+
throw new IncompatiblePlatform(
|
29 |
+
"PHP extension json is not enabled. Please make sure to enable 'json' in your PHP configuration.",
|
30 |
+
IncompatiblePlatform::INCOMPATIBLE_JSON_EXTENSION
|
31 |
+
);
|
32 |
}
|
33 |
}
|
34 |
+
|
35 |
/**
|
36 |
* @return bool
|
37 |
* @codeCoverageIgnore
|
38 |
*/
|
39 |
public function satisfiesPhpVersion()
|
40 |
{
|
41 |
+
return (bool)version_compare(PHP_VERSION, self::MIN_PHP_VERSION, ">=");
|
42 |
}
|
43 |
+
|
44 |
/**
|
45 |
* @return bool
|
46 |
* @codeCoverageIgnore
|
48 |
public function satisfiesJsonExtension()
|
49 |
{
|
50 |
// Check by extension_loaded
|
51 |
+
if (function_exists('extension_loaded') && extension_loaded('json')) {
|
52 |
+
return true;
|
53 |
+
} elseif (function_exists('json_encode')) {
|
54 |
+
return true;
|
55 |
}
|
56 |
+
|
57 |
+
return false;
|
58 |
}
|
59 |
}
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Customer;
|
7 |
use Mollie\Api\Resources\CustomerCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "customers";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class CustomerEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class CustomerEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* Creates a customer in Mollie.
|
34 |
*
|
@@ -42,6 +46,7 @@ class CustomerEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
42 |
{
|
43 |
return $this->rest_create($data, $filters);
|
44 |
}
|
|
|
45 |
/**
|
46 |
* Retrieve a single customer from Mollie.
|
47 |
*
|
@@ -56,6 +61,7 @@ class CustomerEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
56 |
{
|
57 |
return $this->rest_read($customerId, $parameters);
|
58 |
}
|
|
|
59 |
/**
|
60 |
* Deletes the given Customer.
|
61 |
*
|
@@ -72,6 +78,7 @@ class CustomerEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
72 |
{
|
73 |
return $this->rest_delete($customerId, $data);
|
74 |
}
|
|
|
75 |
/**
|
76 |
* Retrieves a collection of Customers from Mollie.
|
77 |
*
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Customer;
|
7 |
use Mollie\Api\Resources\CustomerCollection;
|
8 |
+
|
9 |
+
class CustomerEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "customers";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Customer($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new CustomerCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* Creates a customer in Mollie.
|
38 |
*
|
46 |
{
|
47 |
return $this->rest_create($data, $filters);
|
48 |
}
|
49 |
+
|
50 |
/**
|
51 |
* Retrieve a single customer from Mollie.
|
52 |
*
|
61 |
{
|
62 |
return $this->rest_read($customerId, $parameters);
|
63 |
}
|
64 |
+
|
65 |
/**
|
66 |
* Deletes the given Customer.
|
67 |
*
|
78 |
{
|
79 |
return $this->rest_delete($customerId, $data);
|
80 |
}
|
81 |
+
|
82 |
/**
|
83 |
* Retrieves a collection of Customers from Mollie.
|
84 |
*
|
@@ -6,9 +6,11 @@ use Mollie\Api\Resources\BaseCollection;
|
|
6 |
use Mollie\Api\Resources\Customer;
|
7 |
use Mollie\Api\Resources\Payment;
|
8 |
use Mollie\Api\Resources\PaymentCollection;
|
9 |
-
|
|
|
10 |
{
|
11 |
protected $resourcePath = "customers_payments";
|
|
|
12 |
/**
|
13 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
14 |
*
|
@@ -16,8 +18,9 @@ class CustomerPaymentsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
16 |
*/
|
17 |
protected function getResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
|
|
21 |
/**
|
22 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
23 |
*
|
@@ -28,8 +31,9 @@ class CustomerPaymentsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
28 |
*/
|
29 |
protected function getResourceCollectionObject($count, $_links)
|
30 |
{
|
31 |
-
return new
|
32 |
}
|
|
|
33 |
/**
|
34 |
* Create a subscription for a Customer
|
35 |
*
|
@@ -39,11 +43,13 @@ class CustomerPaymentsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
39 |
*
|
40 |
* @return Payment
|
41 |
*/
|
42 |
-
public function createFor(
|
43 |
{
|
44 |
$this->parentId = $customer->id;
|
|
|
45 |
return parent::rest_create($options, $filters);
|
46 |
}
|
|
|
47 |
/**
|
48 |
* @param Customer $customer
|
49 |
* @param string $from The first resource ID you want to include in your list.
|
@@ -52,9 +58,10 @@ class CustomerPaymentsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
52 |
*
|
53 |
* @return PaymentCollection
|
54 |
*/
|
55 |
-
public function listFor(
|
56 |
{
|
57 |
$this->parentId = $customer->id;
|
|
|
58 |
return parent::rest_list($from, $limit, $parameters);
|
59 |
}
|
60 |
-
}
|
6 |
use Mollie\Api\Resources\Customer;
|
7 |
use Mollie\Api\Resources\Payment;
|
8 |
use Mollie\Api\Resources\PaymentCollection;
|
9 |
+
|
10 |
+
class CustomerPaymentsEndpoint extends EndpointAbstract
|
11 |
{
|
12 |
protected $resourcePath = "customers_payments";
|
13 |
+
|
14 |
/**
|
15 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
16 |
*
|
18 |
*/
|
19 |
protected function getResourceObject()
|
20 |
{
|
21 |
+
return new Payment($this->client);
|
22 |
}
|
23 |
+
|
24 |
/**
|
25 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
26 |
*
|
31 |
*/
|
32 |
protected function getResourceCollectionObject($count, $_links)
|
33 |
{
|
34 |
+
return new PaymentCollection($this->client, $count, $_links);
|
35 |
}
|
36 |
+
|
37 |
/**
|
38 |
* Create a subscription for a Customer
|
39 |
*
|
43 |
*
|
44 |
* @return Payment
|
45 |
*/
|
46 |
+
public function createFor(Customer $customer, array $options = [], array $filters = [])
|
47 |
{
|
48 |
$this->parentId = $customer->id;
|
49 |
+
|
50 |
return parent::rest_create($options, $filters);
|
51 |
}
|
52 |
+
|
53 |
/**
|
54 |
* @param Customer $customer
|
55 |
* @param string $from The first resource ID you want to include in your list.
|
58 |
*
|
59 |
* @return PaymentCollection
|
60 |
*/
|
61 |
+
public function listFor(Customer $customer, $from = null, $limit = null, array $parameters = [])
|
62 |
{
|
63 |
$this->parentId = $customer->id;
|
64 |
+
|
65 |
return parent::rest_list($from, $limit, $parameters);
|
66 |
}
|
67 |
+
}
|
@@ -7,32 +7,38 @@ use Mollie\Api\MollieApiClient;
|
|
7 |
use Mollie\Api\Resources\BaseCollection;
|
8 |
use Mollie\Api\Resources\BaseResource;
|
9 |
use Mollie\Api\Resources\ResourceFactory;
|
|
|
10 |
abstract class EndpointAbstract
|
11 |
{
|
12 |
-
const REST_CREATE =
|
13 |
-
const REST_UPDATE =
|
14 |
-
const REST_READ =
|
15 |
-
const REST_LIST =
|
16 |
-
const REST_DELETE =
|
|
|
17 |
/**
|
18 |
* @var MollieApiClient
|
19 |
*/
|
20 |
protected $client;
|
|
|
21 |
/**
|
22 |
* @var string
|
23 |
*/
|
24 |
protected $resourcePath;
|
|
|
25 |
/**
|
26 |
* @var string|null
|
27 |
*/
|
28 |
protected $parentId;
|
|
|
29 |
/**
|
30 |
* @param MollieApiClient $api
|
31 |
*/
|
32 |
-
public function __construct(
|
33 |
{
|
34 |
$this->client = $api;
|
35 |
}
|
|
|
36 |
/**
|
37 |
* @param array $filters
|
38 |
* @return string
|
@@ -42,16 +48,20 @@ abstract class EndpointAbstract
|
|
42 |
if (empty($filters)) {
|
43 |
return "";
|
44 |
}
|
|
|
45 |
foreach ($filters as $key => $value) {
|
46 |
-
if ($value ===
|
47 |
$filters[$key] = "true";
|
48 |
}
|
49 |
-
|
|
|
50 |
$filters[$key] = "false";
|
51 |
}
|
52 |
}
|
53 |
-
|
|
|
54 |
}
|
|
|
55 |
/**
|
56 |
* @param array $body
|
57 |
* @param array $filters
|
@@ -60,9 +70,15 @@ abstract class EndpointAbstract
|
|
60 |
*/
|
61 |
protected function rest_create(array $body, array $filters)
|
62 |
{
|
63 |
-
$result = $this->client->performHttpCall(
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
65 |
}
|
|
|
66 |
/**
|
67 |
* Retrieves a single object from the REST API.
|
68 |
*
|
@@ -74,12 +90,18 @@ abstract class EndpointAbstract
|
|
74 |
protected function rest_read($id, array $filters)
|
75 |
{
|
76 |
if (empty($id)) {
|
77 |
-
throw new
|
78 |
}
|
79 |
-
|
80 |
-
$
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
82 |
}
|
|
|
83 |
/**
|
84 |
* Sends a DELETE request to a single Molle API object.
|
85 |
*
|
@@ -92,15 +114,23 @@ abstract class EndpointAbstract
|
|
92 |
protected function rest_delete($id, array $body = [])
|
93 |
{
|
94 |
if (empty($id)) {
|
95 |
-
throw new
|
96 |
}
|
97 |
-
|
98 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
if ($result === null) {
|
100 |
return null;
|
101 |
}
|
102 |
-
|
|
|
103 |
}
|
|
|
104 |
/**
|
105 |
* Get a collection of objects from the REST API.
|
106 |
*
|
@@ -113,22 +143,29 @@ abstract class EndpointAbstract
|
|
113 |
*/
|
114 |
protected function rest_list($from = null, $limit = null, array $filters)
|
115 |
{
|
116 |
-
$filters =
|
|
|
117 |
$apiPath = $this->getResourcePath() . $this->buildQueryString($filters);
|
|
|
118 |
$result = $this->client->performHttpCall(self::REST_LIST, $apiPath);
|
|
|
119 |
/** @var BaseCollection $collection */
|
120 |
$collection = $this->getResourceCollectionObject($result->count, $result->_links);
|
|
|
121 |
foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) {
|
122 |
-
$collection[] =
|
123 |
}
|
|
|
124 |
return $collection;
|
125 |
}
|
|
|
126 |
/**
|
127 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
128 |
*
|
129 |
* @return BaseResource
|
130 |
*/
|
131 |
-
protected
|
|
|
132 |
/**
|
133 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
134 |
*
|
@@ -137,29 +174,35 @@ abstract class EndpointAbstract
|
|
137 |
*
|
138 |
* @return BaseCollection
|
139 |
*/
|
140 |
-
protected
|
|
|
141 |
/**
|
142 |
* @param string $resourcePath
|
143 |
*/
|
144 |
public function setResourcePath($resourcePath)
|
145 |
{
|
146 |
-
$this->resourcePath =
|
147 |
}
|
|
|
148 |
/**
|
149 |
* @return string
|
150 |
* @throws ApiException
|
151 |
*/
|
152 |
public function getResourcePath()
|
153 |
{
|
154 |
-
if (
|
155 |
-
list($parentResource, $childResource) =
|
|
|
156 |
if (empty($this->parentId)) {
|
157 |
-
throw new
|
158 |
}
|
159 |
-
|
|
|
160 |
}
|
|
|
161 |
return $this->resourcePath;
|
162 |
}
|
|
|
163 |
/**
|
164 |
* @param array $body
|
165 |
* @return null|string
|
@@ -170,11 +213,13 @@ abstract class EndpointAbstract
|
|
170 |
if (empty($body)) {
|
171 |
return null;
|
172 |
}
|
|
|
173 |
try {
|
174 |
-
$encoded = \
|
175 |
} catch (\InvalidArgumentException $e) {
|
176 |
-
throw new
|
177 |
}
|
|
|
178 |
return $encoded;
|
179 |
}
|
180 |
}
|
7 |
use Mollie\Api\Resources\BaseCollection;
|
8 |
use Mollie\Api\Resources\BaseResource;
|
9 |
use Mollie\Api\Resources\ResourceFactory;
|
10 |
+
|
11 |
abstract class EndpointAbstract
|
12 |
{
|
13 |
+
const REST_CREATE = MollieApiClient::HTTP_POST;
|
14 |
+
const REST_UPDATE = MollieApiClient::HTTP_PATCH;
|
15 |
+
const REST_READ = MollieApiClient::HTTP_GET;
|
16 |
+
const REST_LIST = MollieApiClient::HTTP_GET;
|
17 |
+
const REST_DELETE = MollieApiClient::HTTP_DELETE;
|
18 |
+
|
19 |
/**
|
20 |
* @var MollieApiClient
|
21 |
*/
|
22 |
protected $client;
|
23 |
+
|
24 |
/**
|
25 |
* @var string
|
26 |
*/
|
27 |
protected $resourcePath;
|
28 |
+
|
29 |
/**
|
30 |
* @var string|null
|
31 |
*/
|
32 |
protected $parentId;
|
33 |
+
|
34 |
/**
|
35 |
* @param MollieApiClient $api
|
36 |
*/
|
37 |
+
public function __construct(MollieApiClient $api)
|
38 |
{
|
39 |
$this->client = $api;
|
40 |
}
|
41 |
+
|
42 |
/**
|
43 |
* @param array $filters
|
44 |
* @return string
|
48 |
if (empty($filters)) {
|
49 |
return "";
|
50 |
}
|
51 |
+
|
52 |
foreach ($filters as $key => $value) {
|
53 |
+
if ($value === true) {
|
54 |
$filters[$key] = "true";
|
55 |
}
|
56 |
+
|
57 |
+
if ($value === false) {
|
58 |
$filters[$key] = "false";
|
59 |
}
|
60 |
}
|
61 |
+
|
62 |
+
return "?" . http_build_query($filters, "", "&");
|
63 |
}
|
64 |
+
|
65 |
/**
|
66 |
* @param array $body
|
67 |
* @param array $filters
|
70 |
*/
|
71 |
protected function rest_create(array $body, array $filters)
|
72 |
{
|
73 |
+
$result = $this->client->performHttpCall(
|
74 |
+
self::REST_CREATE,
|
75 |
+
$this->getResourcePath() . $this->buildQueryString($filters),
|
76 |
+
$this->parseRequestBody($body)
|
77 |
+
);
|
78 |
+
|
79 |
+
return ResourceFactory::createFromApiResult($result, $this->getResourceObject());
|
80 |
}
|
81 |
+
|
82 |
/**
|
83 |
* Retrieves a single object from the REST API.
|
84 |
*
|
90 |
protected function rest_read($id, array $filters)
|
91 |
{
|
92 |
if (empty($id)) {
|
93 |
+
throw new ApiException("Invalid resource id.");
|
94 |
}
|
95 |
+
|
96 |
+
$id = urlencode($id);
|
97 |
+
$result = $this->client->performHttpCall(
|
98 |
+
self::REST_READ,
|
99 |
+
"{$this->getResourcePath()}/{$id}" . $this->buildQueryString($filters)
|
100 |
+
);
|
101 |
+
|
102 |
+
return ResourceFactory::createFromApiResult($result, $this->getResourceObject());
|
103 |
}
|
104 |
+
|
105 |
/**
|
106 |
* Sends a DELETE request to a single Molle API object.
|
107 |
*
|
114 |
protected function rest_delete($id, array $body = [])
|
115 |
{
|
116 |
if (empty($id)) {
|
117 |
+
throw new ApiException("Invalid resource id.");
|
118 |
}
|
119 |
+
|
120 |
+
$id = urlencode($id);
|
121 |
+
$result = $this->client->performHttpCall(
|
122 |
+
self::REST_DELETE,
|
123 |
+
"{$this->getResourcePath()}/{$id}",
|
124 |
+
$this->parseRequestBody($body)
|
125 |
+
);
|
126 |
+
|
127 |
if ($result === null) {
|
128 |
return null;
|
129 |
}
|
130 |
+
|
131 |
+
return ResourceFactory::createFromApiResult($result, $this->getResourceObject());
|
132 |
}
|
133 |
+
|
134 |
/**
|
135 |
* Get a collection of objects from the REST API.
|
136 |
*
|
143 |
*/
|
144 |
protected function rest_list($from = null, $limit = null, array $filters)
|
145 |
{
|
146 |
+
$filters = array_merge(["from" => $from, "limit" => $limit], $filters);
|
147 |
+
|
148 |
$apiPath = $this->getResourcePath() . $this->buildQueryString($filters);
|
149 |
+
|
150 |
$result = $this->client->performHttpCall(self::REST_LIST, $apiPath);
|
151 |
+
|
152 |
/** @var BaseCollection $collection */
|
153 |
$collection = $this->getResourceCollectionObject($result->count, $result->_links);
|
154 |
+
|
155 |
foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) {
|
156 |
+
$collection[] = ResourceFactory::createFromApiResult($dataResult, $this->getResourceObject());
|
157 |
}
|
158 |
+
|
159 |
return $collection;
|
160 |
}
|
161 |
+
|
162 |
/**
|
163 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
164 |
*
|
165 |
* @return BaseResource
|
166 |
*/
|
167 |
+
abstract protected function getResourceObject();
|
168 |
+
|
169 |
/**
|
170 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
171 |
*
|
174 |
*
|
175 |
* @return BaseCollection
|
176 |
*/
|
177 |
+
abstract protected function getResourceCollectionObject($count, $_links);
|
178 |
+
|
179 |
/**
|
180 |
* @param string $resourcePath
|
181 |
*/
|
182 |
public function setResourcePath($resourcePath)
|
183 |
{
|
184 |
+
$this->resourcePath = strtolower($resourcePath);
|
185 |
}
|
186 |
+
|
187 |
/**
|
188 |
* @return string
|
189 |
* @throws ApiException
|
190 |
*/
|
191 |
public function getResourcePath()
|
192 |
{
|
193 |
+
if (strpos($this->resourcePath, "_") !== false) {
|
194 |
+
list($parentResource, $childResource) = explode("_", $this->resourcePath, 2);
|
195 |
+
|
196 |
if (empty($this->parentId)) {
|
197 |
+
throw new ApiException("Subresource '{$this->resourcePath}' used without parent '$parentResource' ID.");
|
198 |
}
|
199 |
+
|
200 |
+
return "$parentResource/{$this->parentId}/$childResource";
|
201 |
}
|
202 |
+
|
203 |
return $this->resourcePath;
|
204 |
}
|
205 |
+
|
206 |
/**
|
207 |
* @param array $body
|
208 |
* @return null|string
|
213 |
if (empty($body)) {
|
214 |
return null;
|
215 |
}
|
216 |
+
|
217 |
try {
|
218 |
+
$encoded = \GuzzleHttp\json_encode($body);
|
219 |
} catch (\InvalidArgumentException $e) {
|
220 |
+
throw new ApiException("Error encoding parameters into JSON: '" . $e->getMessage() . "'.");
|
221 |
}
|
222 |
+
|
223 |
return $encoded;
|
224 |
}
|
225 |
}
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Invoice;
|
7 |
use Mollie\Api\Resources\InvoiceCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "invoices";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API. Every API uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class InvoiceEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API. Every API uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class InvoiceEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* Retrieve an Invoice from Mollie.
|
34 |
*
|
@@ -44,6 +48,7 @@ class InvoiceEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
44 |
{
|
45 |
return $this->rest_read($invoiceId, $parameters);
|
46 |
}
|
|
|
47 |
/**
|
48 |
* Retrieves a collection of Invoices from Mollie.
|
49 |
*
|
@@ -58,6 +63,7 @@ class InvoiceEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
58 |
{
|
59 |
return $this->rest_list($from, $limit, $parameters);
|
60 |
}
|
|
|
61 |
/**
|
62 |
* This is a wrapper method for page
|
63 |
*
|
@@ -67,6 +73,6 @@ class InvoiceEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
67 |
*/
|
68 |
public function all(array $parameters = [])
|
69 |
{
|
70 |
-
return $this->page(null, null, $parameters);
|
71 |
}
|
72 |
-
}
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Invoice;
|
7 |
use Mollie\Api\Resources\InvoiceCollection;
|
8 |
+
|
9 |
+
class InvoiceEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "invoices";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API. Every API uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Invoice($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API. Every API uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new InvoiceCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* Retrieve an Invoice from Mollie.
|
38 |
*
|
48 |
{
|
49 |
return $this->rest_read($invoiceId, $parameters);
|
50 |
}
|
51 |
+
|
52 |
/**
|
53 |
* Retrieves a collection of Invoices from Mollie.
|
54 |
*
|
63 |
{
|
64 |
return $this->rest_list($from, $limit, $parameters);
|
65 |
}
|
66 |
+
|
67 |
/**
|
68 |
* This is a wrapper method for page
|
69 |
*
|
73 |
*/
|
74 |
public function all(array $parameters = [])
|
75 |
{
|
76 |
+
return $this->page( null, null, $parameters);
|
77 |
}
|
78 |
+
}
|
@@ -6,9 +6,11 @@ use Mollie\Api\Resources\BaseCollection;
|
|
6 |
use Mollie\Api\Resources\Customer;
|
7 |
use Mollie\Api\Resources\Mandate;
|
8 |
use Mollie\Api\Resources\MandateCollection;
|
9 |
-
|
|
|
10 |
{
|
11 |
protected $resourcePath = "customers_mandates";
|
|
|
12 |
/**
|
13 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
14 |
*
|
@@ -16,8 +18,9 @@ class MandateEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
16 |
*/
|
17 |
protected function getResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
|
|
21 |
/**
|
22 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
23 |
*
|
@@ -28,8 +31,9 @@ class MandateEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
28 |
*/
|
29 |
protected function getResourceCollectionObject($count, $_links)
|
30 |
{
|
31 |
-
return new
|
32 |
}
|
|
|
33 |
/**
|
34 |
* @param Customer $customer
|
35 |
* @param array $options
|
@@ -37,11 +41,13 @@ class MandateEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
37 |
*
|
38 |
* @return Mandate
|
39 |
*/
|
40 |
-
public function createFor(
|
41 |
{
|
42 |
$this->parentId = $customer->id;
|
|
|
43 |
return parent::rest_create($options, $filters);
|
44 |
}
|
|
|
45 |
/**
|
46 |
* @param Customer $customer
|
47 |
* @param string $mandateId
|
@@ -49,11 +55,13 @@ class MandateEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
49 |
*
|
50 |
* @return Mandate
|
51 |
*/
|
52 |
-
public function getFor(
|
53 |
{
|
54 |
$this->parentId = $customer->id;
|
|
|
55 |
return parent::rest_read($mandateId, $parameters);
|
56 |
}
|
|
|
57 |
/**
|
58 |
* @param Customer $customer
|
59 |
* @param string $from The first resource ID you want to include in your list.
|
@@ -62,11 +70,13 @@ class MandateEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
62 |
*
|
63 |
* @return MandateCollection
|
64 |
*/
|
65 |
-
public function listFor(
|
66 |
{
|
67 |
$this->parentId = $customer->id;
|
|
|
68 |
return parent::rest_list($from, $limit, $parameters);
|
69 |
}
|
|
|
70 |
/**
|
71 |
* @param Customer $customer
|
72 |
* @param string $mandateId
|
@@ -75,9 +85,10 @@ class MandateEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
75 |
* @return null
|
76 |
* @throws \Mollie\Api\Exceptions\ApiException
|
77 |
*/
|
78 |
-
public function revokeFor(
|
79 |
{
|
80 |
$this->parentId = $customer->id;
|
|
|
81 |
return parent::rest_delete($mandateId, $data);
|
82 |
}
|
83 |
-
}
|
6 |
use Mollie\Api\Resources\Customer;
|
7 |
use Mollie\Api\Resources\Mandate;
|
8 |
use Mollie\Api\Resources\MandateCollection;
|
9 |
+
|
10 |
+
class MandateEndpoint extends EndpointAbstract
|
11 |
{
|
12 |
protected $resourcePath = "customers_mandates";
|
13 |
+
|
14 |
/**
|
15 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
16 |
*
|
18 |
*/
|
19 |
protected function getResourceObject()
|
20 |
{
|
21 |
+
return new Mandate($this->client);
|
22 |
}
|
23 |
+
|
24 |
/**
|
25 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
26 |
*
|
31 |
*/
|
32 |
protected function getResourceCollectionObject($count, $_links)
|
33 |
{
|
34 |
+
return new MandateCollection($this->client, $count, $_links);
|
35 |
}
|
36 |
+
|
37 |
/**
|
38 |
* @param Customer $customer
|
39 |
* @param array $options
|
41 |
*
|
42 |
* @return Mandate
|
43 |
*/
|
44 |
+
public function createFor(Customer $customer, array $options = [], array $filters = [])
|
45 |
{
|
46 |
$this->parentId = $customer->id;
|
47 |
+
|
48 |
return parent::rest_create($options, $filters);
|
49 |
}
|
50 |
+
|
51 |
/**
|
52 |
* @param Customer $customer
|
53 |
* @param string $mandateId
|
55 |
*
|
56 |
* @return Mandate
|
57 |
*/
|
58 |
+
public function getFor(Customer $customer, $mandateId, array $parameters = [])
|
59 |
{
|
60 |
$this->parentId = $customer->id;
|
61 |
+
|
62 |
return parent::rest_read($mandateId, $parameters);
|
63 |
}
|
64 |
+
|
65 |
/**
|
66 |
* @param Customer $customer
|
67 |
* @param string $from The first resource ID you want to include in your list.
|
70 |
*
|
71 |
* @return MandateCollection
|
72 |
*/
|
73 |
+
public function listFor(Customer $customer, $from = null, $limit = null, array $parameters = [])
|
74 |
{
|
75 |
$this->parentId = $customer->id;
|
76 |
+
|
77 |
return parent::rest_list($from, $limit, $parameters);
|
78 |
}
|
79 |
+
|
80 |
/**
|
81 |
* @param Customer $customer
|
82 |
* @param string $mandateId
|
85 |
* @return null
|
86 |
* @throws \Mollie\Api\Exceptions\ApiException
|
87 |
*/
|
88 |
+
public function revokeFor(Customer $customer, $mandateId, $data = [])
|
89 |
{
|
90 |
$this->parentId = $customer->id;
|
91 |
+
|
92 |
return parent::rest_delete($mandateId, $data);
|
93 |
}
|
94 |
+
}
|
@@ -5,16 +5,19 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Method;
|
7 |
use Mollie\Api\Resources\MethodCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "methods";
|
|
|
11 |
/**
|
12 |
* @return Method
|
13 |
*/
|
14 |
protected function getResourceObject()
|
15 |
{
|
16 |
-
return new
|
17 |
}
|
|
|
18 |
/**
|
19 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
20 |
*
|
@@ -25,8 +28,9 @@ class MethodEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
25 |
*/
|
26 |
protected function getResourceCollectionObject($count, $_links)
|
27 |
{
|
28 |
-
return new
|
29 |
}
|
|
|
30 |
/**
|
31 |
* Retrieve a payment method from Mollie.
|
32 |
*
|
@@ -40,10 +44,12 @@ class MethodEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
40 |
public function get($methodId, array $parameters = [])
|
41 |
{
|
42 |
if (empty($methodId)) {
|
43 |
-
throw new
|
44 |
}
|
|
|
45 |
return parent::rest_read($methodId, $parameters);
|
46 |
}
|
|
|
47 |
/**
|
48 |
* Retrieve all methods.
|
49 |
*
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Method;
|
7 |
use Mollie\Api\Resources\MethodCollection;
|
8 |
+
|
9 |
+
class MethodEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "methods";
|
12 |
+
|
13 |
/**
|
14 |
* @return Method
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
+
return new Method($this->client);
|
19 |
}
|
20 |
+
|
21 |
/**
|
22 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
23 |
*
|
28 |
*/
|
29 |
protected function getResourceCollectionObject($count, $_links)
|
30 |
{
|
31 |
+
return new MethodCollection($count, $_links);
|
32 |
}
|
33 |
+
|
34 |
/**
|
35 |
* Retrieve a payment method from Mollie.
|
36 |
*
|
44 |
public function get($methodId, array $parameters = [])
|
45 |
{
|
46 |
if (empty($methodId)) {
|
47 |
+
throw new ApiException("Method ID is empty.");
|
48 |
}
|
49 |
+
|
50 |
return parent::rest_read($methodId, $parameters);
|
51 |
}
|
52 |
+
|
53 |
/**
|
54 |
* Retrieve all methods.
|
55 |
*
|
@@ -5,13 +5,16 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Order;
|
7 |
use Mollie\Api\Resources\OrderCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "orders";
|
|
|
11 |
/**
|
12 |
* @var string
|
13 |
*/
|
14 |
const RESOURCE_ID_PREFIX = 'ord_';
|
|
|
15 |
/**
|
16 |
* Get the object that is used by this API endpoint. Every API endpoint uses one
|
17 |
* type of object.
|
@@ -20,8 +23,9 @@ class OrderEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
20 |
*/
|
21 |
protected function getResourceObject()
|
22 |
{
|
23 |
-
return new
|
24 |
}
|
|
|
25 |
/**
|
26 |
* Get the collection object that is used by this API endpoint. Every API
|
27 |
* endpoint uses one type of collection object.
|
@@ -33,8 +37,9 @@ class OrderEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
33 |
*/
|
34 |
protected function getResourceCollectionObject($count, $_links)
|
35 |
{
|
36 |
-
return new
|
37 |
}
|
|
|
38 |
/**
|
39 |
* Creates a order in Mollie.
|
40 |
*
|
@@ -48,6 +53,7 @@ class OrderEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
48 |
{
|
49 |
return $this->rest_create($data, $filters);
|
50 |
}
|
|
|
51 |
/**
|
52 |
* Retrieve a single order from Mollie.
|
53 |
*
|
@@ -61,11 +67,13 @@ class OrderEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
61 |
*/
|
62 |
public function get($orderId, array $parameters = [])
|
63 |
{
|
64 |
-
if (empty($orderId) ||
|
65 |
-
throw new
|
66 |
}
|
|
|
67 |
return parent::rest_read($orderId, $parameters);
|
68 |
}
|
|
|
69 |
/**
|
70 |
* Cancel the given Order.
|
71 |
*
|
@@ -84,6 +92,7 @@ class OrderEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
84 |
{
|
85 |
return $this->rest_delete($orderId);
|
86 |
}
|
|
|
87 |
/**
|
88 |
* Retrieves a collection of Orders from Mollie.
|
89 |
*
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Order;
|
7 |
use Mollie\Api\Resources\OrderCollection;
|
8 |
+
|
9 |
+
class OrderEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "orders";
|
12 |
+
|
13 |
/**
|
14 |
* @var string
|
15 |
*/
|
16 |
const RESOURCE_ID_PREFIX = 'ord_';
|
17 |
+
|
18 |
/**
|
19 |
* Get the object that is used by this API endpoint. Every API endpoint uses one
|
20 |
* type of object.
|
23 |
*/
|
24 |
protected function getResourceObject()
|
25 |
{
|
26 |
+
return new Order($this->client);
|
27 |
}
|
28 |
+
|
29 |
/**
|
30 |
* Get the collection object that is used by this API endpoint. Every API
|
31 |
* endpoint uses one type of collection object.
|
37 |
*/
|
38 |
protected function getResourceCollectionObject($count, $_links)
|
39 |
{
|
40 |
+
return new OrderCollection($this->client, $count, $_links);
|
41 |
}
|
42 |
+
|
43 |
/**
|
44 |
* Creates a order in Mollie.
|
45 |
*
|
53 |
{
|
54 |
return $this->rest_create($data, $filters);
|
55 |
}
|
56 |
+
|
57 |
/**
|
58 |
* Retrieve a single order from Mollie.
|
59 |
*
|
67 |
*/
|
68 |
public function get($orderId, array $parameters = [])
|
69 |
{
|
70 |
+
if (empty($orderId) || strpos($orderId, self::RESOURCE_ID_PREFIX) !== 0) {
|
71 |
+
throw new ApiException("Invalid order ID: '{$orderId}'. An order ID should start with '" . self::RESOURCE_ID_PREFIX . "'.");
|
72 |
}
|
73 |
+
|
74 |
return parent::rest_read($orderId, $parameters);
|
75 |
}
|
76 |
+
|
77 |
/**
|
78 |
* Cancel the given Order.
|
79 |
*
|
92 |
{
|
93 |
return $this->rest_delete($orderId);
|
94 |
}
|
95 |
+
|
96 |
/**
|
97 |
* Retrieves a collection of Orders from Mollie.
|
98 |
*
|
@@ -7,13 +7,16 @@ use Mollie\Api\Resources\Order;
|
|
7 |
use Mollie\Api\Resources\OrderLine;
|
8 |
use Mollie\Api\Resources\OrderLineCollection;
|
9 |
use Mollie\Api\Resources\ResourceFactory;
|
10 |
-
|
|
|
11 |
{
|
12 |
protected $resourcePath = "orders_lines";
|
|
|
13 |
/**
|
14 |
* @var string
|
15 |
*/
|
16 |
const RESOURCE_ID_PREFIX = 'odl_';
|
|
|
17 |
/**
|
18 |
* Get the object that is used by this API endpoint. Every API endpoint uses one
|
19 |
* type of object.
|
@@ -22,8 +25,9 @@ class OrderLineEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
22 |
*/
|
23 |
protected function getResourceObject()
|
24 |
{
|
25 |
-
return new
|
26 |
}
|
|
|
27 |
/**
|
28 |
* Get the collection object that is used by this API endpoint. Every API
|
29 |
* endpoint uses one type of collection object.
|
@@ -35,8 +39,9 @@ class OrderLineEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
35 |
*/
|
36 |
protected function getResourceCollectionObject($count, $_links)
|
37 |
{
|
38 |
-
return new
|
39 |
}
|
|
|
40 |
/**
|
41 |
* Cancel lines for the provided order.
|
42 |
* The data array must contain a lines array.
|
@@ -49,13 +54,19 @@ class OrderLineEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
49 |
* @return null
|
50 |
* @throws ApiException
|
51 |
*/
|
52 |
-
public function cancelFor(
|
53 |
{
|
54 |
-
if
|
55 |
-
throw new
|
56 |
}
|
57 |
$this->parentId = $order->id;
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
return null;
|
60 |
}
|
61 |
}
|
7 |
use Mollie\Api\Resources\OrderLine;
|
8 |
use Mollie\Api\Resources\OrderLineCollection;
|
9 |
use Mollie\Api\Resources\ResourceFactory;
|
10 |
+
|
11 |
+
class OrderLineEndpoint extends EndpointAbstract
|
12 |
{
|
13 |
protected $resourcePath = "orders_lines";
|
14 |
+
|
15 |
/**
|
16 |
* @var string
|
17 |
*/
|
18 |
const RESOURCE_ID_PREFIX = 'odl_';
|
19 |
+
|
20 |
/**
|
21 |
* Get the object that is used by this API endpoint. Every API endpoint uses one
|
22 |
* type of object.
|
25 |
*/
|
26 |
protected function getResourceObject()
|
27 |
{
|
28 |
+
return new OrderLine($this->client);
|
29 |
}
|
30 |
+
|
31 |
/**
|
32 |
* Get the collection object that is used by this API endpoint. Every API
|
33 |
* endpoint uses one type of collection object.
|
39 |
*/
|
40 |
protected function getResourceCollectionObject($count, $_links)
|
41 |
{
|
42 |
+
return new OrderLineCollection($count, $_links);
|
43 |
}
|
44 |
+
|
45 |
/**
|
46 |
* Cancel lines for the provided order.
|
47 |
* The data array must contain a lines array.
|
54 |
* @return null
|
55 |
* @throws ApiException
|
56 |
*/
|
57 |
+
public function cancelFor(Order $order, array $data)
|
58 |
{
|
59 |
+
if(! isset($data, $data['lines']) || ! is_array($data['lines'])) {
|
60 |
+
throw new ApiException("A lines array is required.");
|
61 |
}
|
62 |
$this->parentId = $order->id;
|
63 |
+
|
64 |
+
$this->client->performHttpCall(
|
65 |
+
self::REST_DELETE,
|
66 |
+
"{$this->getResourcePath()}",
|
67 |
+
$this->parseRequestBody($data)
|
68 |
+
);
|
69 |
+
|
70 |
return null;
|
71 |
}
|
72 |
}
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Resources\Order;
|
6 |
use Mollie\Api\Resources\Refund;
|
7 |
use Mollie\Api\Resources\RefundCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "orders_refunds";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class OrderRefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class OrderRefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* Refund some order lines. You can provide an empty array for the
|
34 |
* "lines" data to refund all eligable lines for this order.
|
@@ -39,7 +43,7 @@ class OrderRefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
39 |
*
|
40 |
* @return Refund
|
41 |
*/
|
42 |
-
public function createFor(
|
43 |
{
|
44 |
$this->parentId = $order->id;
|
45 |
return parent::rest_create($data, $filters);
|
5 |
use Mollie\Api\Resources\Order;
|
6 |
use Mollie\Api\Resources\Refund;
|
7 |
use Mollie\Api\Resources\RefundCollection;
|
8 |
+
|
9 |
+
class OrderRefundEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "orders_refunds";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Refund($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new RefundCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* Refund some order lines. You can provide an empty array for the
|
38 |
* "lines" data to refund all eligable lines for this order.
|
43 |
*
|
44 |
* @return Refund
|
45 |
*/
|
46 |
+
public function createFor(Order $order, array $data, array $filters = [])
|
47 |
{
|
48 |
$this->parentId = $order->id;
|
49 |
return parent::rest_create($data, $filters);
|
@@ -6,16 +6,19 @@ use Mollie\Api\Exceptions\ApiException;
|
|
6 |
use Mollie\Api\Resources\Method;
|
7 |
use Mollie\Api\Resources\Organization;
|
8 |
use Mollie\Api\Resources\OrganizationCollection;
|
9 |
-
|
|
|
10 |
{
|
11 |
protected $resourcePath = "organizations";
|
|
|
12 |
/**
|
13 |
* @return Organization
|
14 |
*/
|
15 |
protected function getResourceObject()
|
16 |
{
|
17 |
-
return new
|
18 |
}
|
|
|
19 |
/**
|
20 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
21 |
*
|
@@ -26,8 +29,9 @@ class OrganizationEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
26 |
*/
|
27 |
protected function getResourceCollectionObject($count, $_links)
|
28 |
{
|
29 |
-
return new
|
30 |
}
|
|
|
31 |
/**
|
32 |
* Retrieve an organization from Mollie.
|
33 |
*
|
@@ -41,10 +45,12 @@ class OrganizationEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
41 |
public function get($organizationId, array $parameters = [])
|
42 |
{
|
43 |
if (empty($organizationId)) {
|
44 |
-
throw new
|
45 |
}
|
|
|
46 |
return parent::rest_read($organizationId, $parameters);
|
47 |
}
|
|
|
48 |
/**
|
49 |
* Retrieve the current organization from Mollie.
|
50 |
*
|
@@ -56,6 +62,7 @@ class OrganizationEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
56 |
{
|
57 |
return parent::rest_read('me', $parameters);
|
58 |
}
|
|
|
59 |
/**
|
60 |
* Retrieves a collection of Organizations from Mollie.
|
61 |
*
|
6 |
use Mollie\Api\Resources\Method;
|
7 |
use Mollie\Api\Resources\Organization;
|
8 |
use Mollie\Api\Resources\OrganizationCollection;
|
9 |
+
|
10 |
+
class OrganizationEndpoint extends EndpointAbstract
|
11 |
{
|
12 |
protected $resourcePath = "organizations";
|
13 |
+
|
14 |
/**
|
15 |
* @return Organization
|
16 |
*/
|
17 |
protected function getResourceObject()
|
18 |
{
|
19 |
+
return new Organization($this->client);
|
20 |
}
|
21 |
+
|
22 |
/**
|
23 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
24 |
*
|
29 |
*/
|
30 |
protected function getResourceCollectionObject($count, $_links)
|
31 |
{
|
32 |
+
return new OrganizationCollection($this->client, $count, $_links);
|
33 |
}
|
34 |
+
|
35 |
/**
|
36 |
* Retrieve an organization from Mollie.
|
37 |
*
|
45 |
public function get($organizationId, array $parameters = [])
|
46 |
{
|
47 |
if (empty($organizationId)) {
|
48 |
+
throw new ApiException("Organization ID is empty.");
|
49 |
}
|
50 |
+
|
51 |
return parent::rest_read($organizationId, $parameters);
|
52 |
}
|
53 |
+
|
54 |
/**
|
55 |
* Retrieve the current organization from Mollie.
|
56 |
*
|
62 |
{
|
63 |
return parent::rest_read('me', $parameters);
|
64 |
}
|
65 |
+
|
66 |
/**
|
67 |
* Retrieves a collection of Organizations from Mollie.
|
68 |
*
|
@@ -4,9 +4,11 @@ namespace Mollie\Api\Endpoints;
|
|
4 |
|
5 |
use Mollie\Api\Resources\Capture;
|
6 |
use Mollie\Api\Resources\Payment;
|
7 |
-
|
|
|
8 |
{
|
9 |
protected $resourcePath = "payments_captures";
|
|
|
10 |
/**
|
11 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
12 |
*
|
@@ -14,8 +16,9 @@ class PaymentCaptureEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
14 |
*/
|
15 |
protected function getResourceObject()
|
16 |
{
|
17 |
-
return new
|
18 |
}
|
|
|
19 |
/**
|
20 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
21 |
*
|
@@ -26,8 +29,9 @@ class PaymentCaptureEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
26 |
*/
|
27 |
protected function getResourceCollectionObject($count, $_links)
|
28 |
{
|
29 |
-
return new
|
30 |
}
|
|
|
31 |
/**
|
32 |
* @param Payment $payment
|
33 |
* @param string $captureId
|
@@ -35,9 +39,10 @@ class PaymentCaptureEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
35 |
*
|
36 |
* @return Capture
|
37 |
*/
|
38 |
-
public function getFor(
|
39 |
{
|
40 |
$this->parentId = $payment->id;
|
|
|
41 |
return parent::rest_read($captureId, $parameters);
|
42 |
}
|
43 |
}
|
4 |
|
5 |
use Mollie\Api\Resources\Capture;
|
6 |
use Mollie\Api\Resources\Payment;
|
7 |
+
|
8 |
+
class PaymentCaptureEndpoint extends EndpointAbstract
|
9 |
{
|
10 |
protected $resourcePath = "payments_captures";
|
11 |
+
|
12 |
/**
|
13 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
14 |
*
|
16 |
*/
|
17 |
protected function getResourceObject()
|
18 |
{
|
19 |
+
return new Capture($this->client);
|
20 |
}
|
21 |
+
|
22 |
/**
|
23 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
24 |
*
|
29 |
*/
|
30 |
protected function getResourceCollectionObject($count, $_links)
|
31 |
{
|
32 |
+
return new CaptureCollection($this->client, $count, $_links);
|
33 |
}
|
34 |
+
|
35 |
/**
|
36 |
* @param Payment $payment
|
37 |
* @param string $captureId
|
39 |
*
|
40 |
* @return Capture
|
41 |
*/
|
42 |
+
public function getFor(Payment $payment, $captureId, array $parameters = [])
|
43 |
{
|
44 |
$this->parentId = $payment->id;
|
45 |
+
|
46 |
return parent::rest_read($captureId, $parameters);
|
47 |
}
|
48 |
}
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Resources\Chargeback;
|
6 |
use Mollie\Api\Resources\ChargebackCollection;
|
7 |
use Mollie\Api\Resources\Payment;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "payments_chargebacks";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class PaymentChargebackEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class PaymentChargebackEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* @param Payment $payment
|
34 |
* @param string $chargebackId
|
@@ -36,9 +40,10 @@ class PaymentChargebackEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
36 |
*
|
37 |
* @return Chargeback
|
38 |
*/
|
39 |
-
public function getFor(
|
40 |
{
|
41 |
$this->parentId = $payment->id;
|
|
|
42 |
return parent::rest_read($chargebackId, $parameters);
|
43 |
}
|
44 |
}
|
5 |
use Mollie\Api\Resources\Chargeback;
|
6 |
use Mollie\Api\Resources\ChargebackCollection;
|
7 |
use Mollie\Api\Resources\Payment;
|
8 |
+
|
9 |
+
class PaymentChargebackEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "payments_chargebacks";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Chargeback($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new ChargebackCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* @param Payment $payment
|
38 |
* @param string $chargebackId
|
40 |
*
|
41 |
* @return Chargeback
|
42 |
*/
|
43 |
+
public function getFor(Payment $payment, $chargebackId, array $parameters = [])
|
44 |
{
|
45 |
$this->parentId = $payment->id;
|
46 |
+
|
47 |
return parent::rest_read($chargebackId, $parameters);
|
48 |
}
|
49 |
}
|
@@ -7,20 +7,24 @@ use Mollie\Api\Resources\Payment;
|
|
7 |
use Mollie\Api\Resources\PaymentCollection;
|
8 |
use Mollie\Api\Resources\Refund;
|
9 |
use Mollie\Api\Resources\ResourceFactory;
|
10 |
-
|
|
|
11 |
{
|
12 |
protected $resourcePath = "payments";
|
|
|
13 |
/**
|
14 |
* @var string
|
15 |
*/
|
16 |
const RESOURCE_ID_PREFIX = 'tr_';
|
|
|
17 |
/**
|
18 |
* @return Payment
|
19 |
*/
|
20 |
protected function getResourceObject()
|
21 |
{
|
22 |
-
return new
|
23 |
}
|
|
|
24 |
/**
|
25 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
26 |
*
|
@@ -31,8 +35,9 @@ class PaymentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
31 |
*/
|
32 |
protected function getResourceCollectionObject($count, $_links)
|
33 |
{
|
34 |
-
return new
|
35 |
}
|
|
|
36 |
/**
|
37 |
* Creates a payment in Mollie.
|
38 |
*
|
@@ -46,6 +51,7 @@ class PaymentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
46 |
{
|
47 |
return $this->rest_create($data, $filters);
|
48 |
}
|
|
|
49 |
/**
|
50 |
* Retrieve a single payment from Mollie.
|
51 |
*
|
@@ -58,11 +64,13 @@ class PaymentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
58 |
*/
|
59 |
public function get($paymentId, array $parameters = [])
|
60 |
{
|
61 |
-
if (empty($paymentId) ||
|
62 |
-
throw new
|
63 |
}
|
|
|
64 |
return parent::rest_read($paymentId, $parameters);
|
65 |
}
|
|
|
66 |
/**
|
67 |
* Deletes the given Payment.
|
68 |
*
|
@@ -79,6 +87,7 @@ class PaymentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
79 |
{
|
80 |
return $this->rest_delete($paymentId, $data);
|
81 |
}
|
|
|
82 |
/**
|
83 |
* Cancel the given Payment. This is just an alias of the 'delete' method.
|
84 |
*
|
@@ -95,6 +104,7 @@ class PaymentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
95 |
{
|
96 |
return $this->rest_delete($paymentId, $data);
|
97 |
}
|
|
|
98 |
/**
|
99 |
* Retrieves a collection of Payments from Mollie.
|
100 |
*
|
@@ -109,6 +119,7 @@ class PaymentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
109 |
{
|
110 |
return $this->rest_list($from, $limit, $parameters);
|
111 |
}
|
|
|
112 |
/**
|
113 |
* Issue a refund for the given payment.
|
114 |
*
|
@@ -121,14 +132,17 @@ class PaymentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
121 |
* @return Refund
|
122 |
* @throws ApiException
|
123 |
*/
|
124 |
-
public function refund(
|
125 |
{
|
126 |
-
$resource = "{$this->getResourcePath()}/" .
|
|
|
127 |
$body = null;
|
128 |
-
if (
|
129 |
-
$body =
|
130 |
}
|
|
|
131 |
$result = $this->client->performHttpCall(self::REST_CREATE, $resource, $body);
|
132 |
-
|
|
|
133 |
}
|
134 |
}
|
7 |
use Mollie\Api\Resources\PaymentCollection;
|
8 |
use Mollie\Api\Resources\Refund;
|
9 |
use Mollie\Api\Resources\ResourceFactory;
|
10 |
+
|
11 |
+
class PaymentEndpoint extends EndpointAbstract
|
12 |
{
|
13 |
protected $resourcePath = "payments";
|
14 |
+
|
15 |
/**
|
16 |
* @var string
|
17 |
*/
|
18 |
const RESOURCE_ID_PREFIX = 'tr_';
|
19 |
+
|
20 |
/**
|
21 |
* @return Payment
|
22 |
*/
|
23 |
protected function getResourceObject()
|
24 |
{
|
25 |
+
return new Payment($this->client);
|
26 |
}
|
27 |
+
|
28 |
/**
|
29 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
30 |
*
|
35 |
*/
|
36 |
protected function getResourceCollectionObject($count, $_links)
|
37 |
{
|
38 |
+
return new PaymentCollection($this->client, $count, $_links);
|
39 |
}
|
40 |
+
|
41 |
/**
|
42 |
* Creates a payment in Mollie.
|
43 |
*
|
51 |
{
|
52 |
return $this->rest_create($data, $filters);
|
53 |
}
|
54 |
+
|
55 |
/**
|
56 |
* Retrieve a single payment from Mollie.
|
57 |
*
|
64 |
*/
|
65 |
public function get($paymentId, array $parameters = [])
|
66 |
{
|
67 |
+
if (empty($paymentId) || strpos($paymentId, self::RESOURCE_ID_PREFIX) !== 0) {
|
68 |
+
throw new ApiException("Invalid payment ID: '{$paymentId}'. A payment ID should start with '" . self::RESOURCE_ID_PREFIX . "'.");
|
69 |
}
|
70 |
+
|
71 |
return parent::rest_read($paymentId, $parameters);
|
72 |
}
|
73 |
+
|
74 |
/**
|
75 |
* Deletes the given Payment.
|
76 |
*
|
87 |
{
|
88 |
return $this->rest_delete($paymentId, $data);
|
89 |
}
|
90 |
+
|
91 |
/**
|
92 |
* Cancel the given Payment. This is just an alias of the 'delete' method.
|
93 |
*
|
104 |
{
|
105 |
return $this->rest_delete($paymentId, $data);
|
106 |
}
|
107 |
+
|
108 |
/**
|
109 |
* Retrieves a collection of Payments from Mollie.
|
110 |
*
|
119 |
{
|
120 |
return $this->rest_list($from, $limit, $parameters);
|
121 |
}
|
122 |
+
|
123 |
/**
|
124 |
* Issue a refund for the given payment.
|
125 |
*
|
132 |
* @return Refund
|
133 |
* @throws ApiException
|
134 |
*/
|
135 |
+
public function refund(Payment $payment, $data = [])
|
136 |
{
|
137 |
+
$resource = "{$this->getResourcePath()}/" . urlencode($payment->id) . "/refunds";
|
138 |
+
|
139 |
$body = null;
|
140 |
+
if (count($data) > 0) {
|
141 |
+
$body = json_encode($data);
|
142 |
}
|
143 |
+
|
144 |
$result = $this->client->performHttpCall(self::REST_CREATE, $resource, $body);
|
145 |
+
|
146 |
+
return ResourceFactory::createFromApiResult($result, new Refund($this->client));
|
147 |
}
|
148 |
}
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Resources\Payment;
|
6 |
use Mollie\Api\Resources\Refund;
|
7 |
use Mollie\Api\Resources\RefundCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "payments_refunds";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class PaymentRefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class PaymentRefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* @param Payment $payment
|
34 |
* @param string $refundId
|
@@ -36,9 +40,10 @@ class PaymentRefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
36 |
*
|
37 |
* @return Refund
|
38 |
*/
|
39 |
-
public function getFor(
|
40 |
{
|
41 |
$this->parentId = $payment->id;
|
|
|
42 |
return parent::rest_read($refundId, $parameters);
|
43 |
}
|
44 |
}
|
5 |
use Mollie\Api\Resources\Payment;
|
6 |
use Mollie\Api\Resources\Refund;
|
7 |
use Mollie\Api\Resources\RefundCollection;
|
8 |
+
|
9 |
+
class PaymentRefundEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "payments_refunds";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Refund($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new RefundCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* @param Payment $payment
|
38 |
* @param string $refundId
|
40 |
*
|
41 |
* @return Refund
|
42 |
*/
|
43 |
+
public function getFor(Payment $payment, $refundId, array $parameters = [])
|
44 |
{
|
45 |
$this->parentId = $payment->id;
|
46 |
+
|
47 |
return parent::rest_read($refundId, $parameters);
|
48 |
}
|
49 |
}
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Permission;
|
7 |
use Mollie\Api\Resources\PermissionCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "permissions";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API endpoint. Every API endpoint uses one
|
13 |
* type of object.
|
@@ -16,8 +18,9 @@ class PermissionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
16 |
*/
|
17 |
protected function getResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
|
|
21 |
/**
|
22 |
* Get the collection object that is used by this API endpoint. Every API
|
23 |
* endpoint uses one type of collection object.
|
@@ -29,8 +32,9 @@ class PermissionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
29 |
*/
|
30 |
protected function getResourceCollectionObject($count, $_links)
|
31 |
{
|
32 |
-
return new
|
33 |
}
|
|
|
34 |
/**
|
35 |
* Retrieve a single Permission from Mollie.
|
36 |
*
|
@@ -45,6 +49,7 @@ class PermissionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
45 |
{
|
46 |
return $this->rest_read($permissionId, $parameters);
|
47 |
}
|
|
|
48 |
/**
|
49 |
* Retrieve all permissions.
|
50 |
*
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Permission;
|
7 |
use Mollie\Api\Resources\PermissionCollection;
|
8 |
+
|
9 |
+
class PermissionEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "permissions";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one
|
15 |
* type of object.
|
18 |
*/
|
19 |
protected function getResourceObject()
|
20 |
{
|
21 |
+
return new Permission($this->client);
|
22 |
}
|
23 |
+
|
24 |
/**
|
25 |
* Get the collection object that is used by this API endpoint. Every API
|
26 |
* endpoint uses one type of collection object.
|
32 |
*/
|
33 |
protected function getResourceCollectionObject($count, $_links)
|
34 |
{
|
35 |
+
return new PermissionCollection($this->client, $count, $_links);
|
36 |
}
|
37 |
+
|
38 |
/**
|
39 |
* Retrieve a single Permission from Mollie.
|
40 |
*
|
49 |
{
|
50 |
return $this->rest_read($permissionId, $parameters);
|
51 |
}
|
52 |
+
|
53 |
/**
|
54 |
* Retrieve all permissions.
|
55 |
*
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Profile;
|
7 |
use Mollie\Api\Resources\ProfileCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "profiles";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class ProfileEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class ProfileEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* Creates a Profile in Mollie.
|
34 |
*
|
@@ -40,8 +44,9 @@ class ProfileEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
40 |
*/
|
41 |
public function create(array $data = [], array $filters = [])
|
42 |
{
|
43 |
-
|
44 |
}
|
|
|
45 |
/**
|
46 |
* Retrieve a Profile from Mollie.
|
47 |
*
|
@@ -57,6 +62,7 @@ class ProfileEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
57 |
{
|
58 |
return $this->rest_read($profileId, $parameters);
|
59 |
}
|
|
|
60 |
/**
|
61 |
* Delete a Profile from Mollie.
|
62 |
*
|
@@ -73,6 +79,7 @@ class ProfileEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
73 |
{
|
74 |
return $this->rest_delete($profileId, $data);
|
75 |
}
|
|
|
76 |
/**
|
77 |
* Retrieves a collection of Profiles from Mollie.
|
78 |
*
|
@@ -87,4 +94,6 @@ class ProfileEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
87 |
{
|
88 |
return $this->rest_list($from, $limit, $parameters);
|
89 |
}
|
90 |
-
|
|
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Profile;
|
7 |
use Mollie\Api\Resources\ProfileCollection;
|
8 |
+
|
9 |
+
class ProfileEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "profiles";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Profile($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new ProfileCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* Creates a Profile in Mollie.
|
38 |
*
|
44 |
*/
|
45 |
public function create(array $data = [], array $filters = [])
|
46 |
{
|
47 |
+
return $this->rest_create($data, $filters);
|
48 |
}
|
49 |
+
|
50 |
/**
|
51 |
* Retrieve a Profile from Mollie.
|
52 |
*
|
62 |
{
|
63 |
return $this->rest_read($profileId, $parameters);
|
64 |
}
|
65 |
+
|
66 |
/**
|
67 |
* Delete a Profile from Mollie.
|
68 |
*
|
79 |
{
|
80 |
return $this->rest_delete($profileId, $data);
|
81 |
}
|
82 |
+
|
83 |
/**
|
84 |
* Retrieves a collection of Profiles from Mollie.
|
85 |
*
|
94 |
{
|
95 |
return $this->rest_list($from, $limit, $parameters);
|
96 |
}
|
97 |
+
|
98 |
+
|
99 |
+
}
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Refund;
|
7 |
use Mollie\Api\Resources\RefundCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "refunds";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class RefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class RefundEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* Retrieves a collection of Refunds from Mollie.
|
34 |
*
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Refund;
|
7 |
use Mollie\Api\Resources\RefundCollection;
|
8 |
+
|
9 |
+
class RefundEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "refunds";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Refund($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new RefundCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* Retrieves a collection of Refunds from Mollie.
|
38 |
*
|
@@ -5,9 +5,11 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Settlement;
|
7 |
use Mollie\Api\Resources\SettlementCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "settlements";
|
|
|
11 |
/**
|
12 |
* Get the object that is used by this API. Every API uses one type of object.
|
13 |
*
|
@@ -15,8 +17,9 @@ class SettlementsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
15 |
*/
|
16 |
protected function getResourceObject()
|
17 |
{
|
18 |
-
return new
|
19 |
}
|
|
|
20 |
/**
|
21 |
* Get the collection object that is used by this API. Every API uses one type of collection object.
|
22 |
*
|
@@ -27,8 +30,9 @@ class SettlementsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
27 |
*/
|
28 |
protected function getResourceCollectionObject($count, $_links)
|
29 |
{
|
30 |
-
return new
|
31 |
}
|
|
|
32 |
/**
|
33 |
* Retrieve a single settlement from Mollie.
|
34 |
*
|
@@ -41,8 +45,9 @@ class SettlementsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
41 |
*/
|
42 |
public function get($settlementId, array $parameters = [])
|
43 |
{
|
44 |
-
|
45 |
}
|
|
|
46 |
/**
|
47 |
* Retrieve the details of the current settlement that has not yet been paid out.
|
48 |
*
|
@@ -53,6 +58,7 @@ class SettlementsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
53 |
{
|
54 |
return parent::rest_read("next", []);
|
55 |
}
|
|
|
56 |
/**
|
57 |
* Retrieve the details of the open balance of the organization.
|
58 |
*
|
@@ -63,6 +69,7 @@ class SettlementsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
63 |
{
|
64 |
return parent::rest_read("open", []);
|
65 |
}
|
|
|
66 |
/**
|
67 |
* Retrieves a collection of Settlements from Mollie.
|
68 |
*
|
@@ -77,4 +84,4 @@ class SettlementsEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
77 |
{
|
78 |
return $this->rest_list($from, $limit, $parameters);
|
79 |
}
|
80 |
-
}
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\Resources\Settlement;
|
7 |
use Mollie\Api\Resources\SettlementCollection;
|
8 |
+
|
9 |
+
class SettlementsEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "settlements";
|
12 |
+
|
13 |
/**
|
14 |
* Get the object that is used by this API. Every API uses one type of object.
|
15 |
*
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
+
return new Settlement($this->client);
|
21 |
}
|
22 |
+
|
23 |
/**
|
24 |
* Get the collection object that is used by this API. Every API uses one type of collection object.
|
25 |
*
|
30 |
*/
|
31 |
protected function getResourceCollectionObject($count, $_links)
|
32 |
{
|
33 |
+
return new SettlementCollection($this->client, $count, $_links);
|
34 |
}
|
35 |
+
|
36 |
/**
|
37 |
* Retrieve a single settlement from Mollie.
|
38 |
*
|
45 |
*/
|
46 |
public function get($settlementId, array $parameters = [])
|
47 |
{
|
48 |
+
return parent::rest_read($settlementId, $parameters);
|
49 |
}
|
50 |
+
|
51 |
/**
|
52 |
* Retrieve the details of the current settlement that has not yet been paid out.
|
53 |
*
|
58 |
{
|
59 |
return parent::rest_read("next", []);
|
60 |
}
|
61 |
+
|
62 |
/**
|
63 |
* Retrieve the details of the open balance of the organization.
|
64 |
*
|
69 |
{
|
70 |
return parent::rest_read("open", []);
|
71 |
}
|
72 |
+
|
73 |
/**
|
74 |
* Retrieves a collection of Settlements from Mollie.
|
75 |
*
|
84 |
{
|
85 |
return $this->rest_list($from, $limit, $parameters);
|
86 |
}
|
87 |
+
}
|
@@ -5,13 +5,16 @@ namespace Mollie\Api\Endpoints;
|
|
5 |
use Mollie\Api\Resources\Order;
|
6 |
use Mollie\Api\Resources\Shipment;
|
7 |
use Mollie\Api\Resources\ShipmentCollection;
|
8 |
-
|
|
|
9 |
{
|
10 |
protected $resourcePath = "orders_shipments";
|
|
|
11 |
/**
|
12 |
* @var string
|
13 |
*/
|
14 |
const RESOURCE_ID_PREFIX = 'shp_';
|
|
|
15 |
/**
|
16 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
17 |
*
|
@@ -19,8 +22,9 @@ class ShipmentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
19 |
*/
|
20 |
protected function getResourceObject()
|
21 |
{
|
22 |
-
return new
|
23 |
}
|
|
|
24 |
/**
|
25 |
* Get the collection object that is used by this API endpoint. Every API
|
26 |
* endpoint uses one type of collection object.
|
@@ -32,8 +36,9 @@ class ShipmentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
32 |
*/
|
33 |
protected function getResourceCollectionObject($count, $_links)
|
34 |
{
|
35 |
-
return new
|
36 |
}
|
|
|
37 |
/**
|
38 |
* Create a shipment for some order lines. You can provide an empty array for the
|
39 |
* "lines" option to include all unshipped lines for this order.
|
@@ -44,11 +49,12 @@ class ShipmentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
44 |
*
|
45 |
* @return Shipment
|
46 |
*/
|
47 |
-
public function createFor(
|
48 |
{
|
49 |
$this->parentId = $order->id;
|
50 |
return parent::rest_create($options, $filters);
|
51 |
}
|
|
|
52 |
/**
|
53 |
* Retrieve a single shipment and the order lines shipped by a shipment’s ID.
|
54 |
*
|
@@ -58,11 +64,13 @@ class ShipmentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
58 |
*
|
59 |
* @return Shipment
|
60 |
*/
|
61 |
-
public function getFor(
|
62 |
{
|
63 |
$this->parentId = $order->id;
|
|
|
64 |
return parent::rest_read($shipmentId, $parameters);
|
65 |
}
|
|
|
66 |
/**
|
67 |
* Return all shipments for the Order provided.
|
68 |
*
|
@@ -71,9 +79,10 @@ class ShipmentEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
71 |
*
|
72 |
* @return ShipmentCollection
|
73 |
*/
|
74 |
-
public function listFor(
|
75 |
{
|
76 |
$this->parentId = $order->id;
|
|
|
77 |
return parent::rest_list(null, null, $parameters);
|
78 |
}
|
79 |
}
|
5 |
use Mollie\Api\Resources\Order;
|
6 |
use Mollie\Api\Resources\Shipment;
|
7 |
use Mollie\Api\Resources\ShipmentCollection;
|
8 |
+
|
9 |
+
class ShipmentEndpoint extends EndpointAbstract
|
10 |
{
|
11 |
protected $resourcePath = "orders_shipments";
|
12 |
+
|
13 |
/**
|
14 |
* @var string
|
15 |
*/
|
16 |
const RESOURCE_ID_PREFIX = 'shp_';
|
17 |
+
|
18 |
/**
|
19 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
20 |
*
|
22 |
*/
|
23 |
protected function getResourceObject()
|
24 |
{
|
25 |
+
return new Shipment($this->client);
|
26 |
}
|
27 |
+
|
28 |
/**
|
29 |
* Get the collection object that is used by this API endpoint. Every API
|
30 |
* endpoint uses one type of collection object.
|
36 |
*/
|
37 |
protected function getResourceCollectionObject($count, $_links)
|
38 |
{
|
39 |
+
return new ShipmentCollection($this->client, $count, $_links);
|
40 |
}
|
41 |
+
|
42 |
/**
|
43 |
* Create a shipment for some order lines. You can provide an empty array for the
|
44 |
* "lines" option to include all unshipped lines for this order.
|
49 |
*
|
50 |
* @return Shipment
|
51 |
*/
|
52 |
+
public function createFor(Order $order, array $options = [], array $filters = [])
|
53 |
{
|
54 |
$this->parentId = $order->id;
|
55 |
return parent::rest_create($options, $filters);
|
56 |
}
|
57 |
+
|
58 |
/**
|
59 |
* Retrieve a single shipment and the order lines shipped by a shipment’s ID.
|
60 |
*
|
64 |
*
|
65 |
* @return Shipment
|
66 |
*/
|
67 |
+
public function getFor(Order $order, $shipmentId, array $parameters = [])
|
68 |
{
|
69 |
$this->parentId = $order->id;
|
70 |
+
|
71 |
return parent::rest_read($shipmentId, $parameters);
|
72 |
}
|
73 |
+
|
74 |
/**
|
75 |
* Return all shipments for the Order provided.
|
76 |
*
|
79 |
*
|
80 |
* @return ShipmentCollection
|
81 |
*/
|
82 |
+
public function listFor(Order $order, array $parameters = [])
|
83 |
{
|
84 |
$this->parentId = $order->id;
|
85 |
+
|
86 |
return parent::rest_list(null, null, $parameters);
|
87 |
}
|
88 |
}
|
@@ -7,9 +7,11 @@ use Mollie\Api\Resources\BaseResource;
|
|
7 |
use Mollie\Api\Resources\Customer;
|
8 |
use Mollie\Api\Resources\Subscription;
|
9 |
use Mollie\Api\Resources\SubscriptionCollection;
|
10 |
-
|
|
|
11 |
{
|
12 |
protected $resourcePath = "customers_subscriptions";
|
|
|
13 |
/**
|
14 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
15 |
*
|
@@ -17,8 +19,9 @@ class SubscriptionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
17 |
*/
|
18 |
protected function getResourceObject()
|
19 |
{
|
20 |
-
return new
|
21 |
}
|
|
|
22 |
/**
|
23 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
24 |
*
|
@@ -29,8 +32,9 @@ class SubscriptionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
29 |
*/
|
30 |
protected function getResourceCollectionObject($count, $_links)
|
31 |
{
|
32 |
-
return new
|
33 |
}
|
|
|
34 |
/**
|
35 |
* Create a subscription for a Customer
|
36 |
*
|
@@ -40,11 +44,13 @@ class SubscriptionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
40 |
*
|
41 |
* @return Subscription
|
42 |
*/
|
43 |
-
public function createFor(
|
44 |
{
|
45 |
$this->parentId = $customer->id;
|
|
|
46 |
return parent::rest_create($options, $filters);
|
47 |
}
|
|
|
48 |
/**
|
49 |
* @param Customer $customer
|
50 |
* @param string $subscriptionId
|
@@ -52,11 +58,13 @@ class SubscriptionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
52 |
*
|
53 |
* @return Subscription
|
54 |
*/
|
55 |
-
public function getFor(
|
56 |
{
|
57 |
$this->parentId = $customer->id;
|
|
|
58 |
return parent::rest_read($subscriptionId, $parameters);
|
59 |
}
|
|
|
60 |
/**
|
61 |
* @param Customer $customer
|
62 |
* @param string $from The first resource ID you want to include in your list.
|
@@ -65,11 +73,13 @@ class SubscriptionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
65 |
*
|
66 |
* @return SubscriptionCollection
|
67 |
*/
|
68 |
-
public function listFor(
|
69 |
{
|
70 |
$this->parentId = $customer->id;
|
|
|
71 |
return parent::rest_list($from, $limit, $parameters);
|
72 |
}
|
|
|
73 |
/**
|
74 |
* @param Customer $customer
|
75 |
* @param string $subscriptionId
|
@@ -78,9 +88,10 @@ class SubscriptionEndpoint extends \Mollie\Api\Endpoints\EndpointAbstract
|
|
78 |
* @return null
|
79 |
* @throws \Mollie\Api\Exceptions\ApiException
|
80 |
*/
|
81 |
-
public function cancelFor(
|
82 |
{
|
83 |
$this->parentId = $customer->id;
|
|
|
84 |
return parent::rest_delete($subscriptionId, $data);
|
85 |
}
|
86 |
-
}
|
7 |
use Mollie\Api\Resources\Customer;
|
8 |
use Mollie\Api\Resources\Subscription;
|
9 |
use Mollie\Api\Resources\SubscriptionCollection;
|
10 |
+
|
11 |
+
class SubscriptionEndpoint extends EndpointAbstract
|
12 |
{
|
13 |
protected $resourcePath = "customers_subscriptions";
|
14 |
+
|
15 |
/**
|
16 |
* Get the object that is used by this API endpoint. Every API endpoint uses one type of object.
|
17 |
*
|
19 |
*/
|
20 |
protected function getResourceObject()
|
21 |
{
|
22 |
+
return new Subscription($this->client);
|
23 |
}
|
24 |
+
|
25 |
/**
|
26 |
* Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object.
|
27 |
*
|
32 |
*/
|
33 |
protected function getResourceCollectionObject($count, $_links)
|
34 |
{
|
35 |
+
return new SubscriptionCollection($this->client, $count, $_links);
|
36 |
}
|
37 |
+
|
38 |
/**
|
39 |
* Create a subscription for a Customer
|
40 |
*
|
44 |
*
|
45 |
* @return Subscription
|
46 |
*/
|
47 |
+
public function createFor(Customer $customer, array $options = [], array $filters = [])
|
48 |
{
|
49 |
$this->parentId = $customer->id;
|
50 |
+
|
51 |
return parent::rest_create($options, $filters);
|
52 |
}
|
53 |
+
|
54 |
/**
|
55 |
* @param Customer $customer
|
56 |
* @param string $subscriptionId
|
58 |
*
|
59 |
* @return Subscription
|
60 |
*/
|
61 |
+
public function getFor(Customer $customer, $subscriptionId, array $parameters = [])
|
62 |
{
|
63 |
$this->parentId = $customer->id;
|
64 |
+
|
65 |
return parent::rest_read($subscriptionId, $parameters);
|
66 |
}
|
67 |
+
|
68 |
/**
|
69 |
* @param Customer $customer
|
70 |
* @param string $from The first resource ID you want to include in your list.
|
73 |
*
|
74 |
* @return SubscriptionCollection
|
75 |
*/
|
76 |
+
public function listFor(Customer $customer, $from = null, $limit = null, array $parameters = [])
|
77 |
{
|
78 |
$this->parentId = $customer->id;
|
79 |
+
|
80 |
return parent::rest_list($from, $limit, $parameters);
|
81 |
}
|
82 |
+
|
83 |
/**
|
84 |
* @param Customer $customer
|
85 |
* @param string $subscriptionId
|
88 |
* @return null
|
89 |
* @throws \Mollie\Api\Exceptions\ApiException
|
90 |
*/
|
91 |
+
public function cancelFor(Customer $customer, $subscriptionId, array $data = [])
|
92 |
{
|
93 |
$this->parentId = $customer->id;
|
94 |
+
|
95 |
return parent::rest_delete($subscriptionId, $data);
|
96 |
}
|
97 |
+
}
|
@@ -8,10 +8,12 @@ class ApiException extends \Exception
|
|
8 |
* @var string
|
9 |
*/
|
10 |
protected $field;
|
|
|
11 |
/**
|
12 |
* @var string
|
13 |
*/
|
14 |
protected $documentationUrl;
|
|
|
15 |
/**
|
16 |
* @param string $message
|
17 |
* @param int $code
|
@@ -22,15 +24,20 @@ class ApiException extends \Exception
|
|
22 |
public function __construct($message = "", $code = 0, $field = null, $documentationUrl = null, \Throwable $previous = null)
|
23 |
{
|
24 |
if (!empty($field)) {
|
25 |
-
$this->field = (string)
|
26 |
$message .= ". Field: {$this->field}";
|
27 |
}
|
|
|
28 |
if (!empty($documentationUrl)) {
|
29 |
-
$this->documentationUrl = (string)
|
30 |
$message .= ". Documentation: {$this->documentationUrl}";
|
31 |
}
|
|
|
32 |
parent::__construct($message, $code, $previous);
|
|
|
|
|
33 |
}
|
|
|
34 |
/**
|
35 |
* @return string
|
36 |
*/
|
@@ -38,6 +45,7 @@ class ApiException extends \Exception
|
|
38 |
{
|
39 |
return $this->field;
|
40 |
}
|
|
|
41 |
/**
|
42 |
* @return string
|
43 |
*/
|
8 |
* @var string
|
9 |
*/
|
10 |
protected $field;
|
11 |
+
|
12 |
/**
|
13 |
* @var string
|
14 |
*/
|
15 |
protected $documentationUrl;
|
16 |
+
|
17 |
/**
|
18 |
* @param string $message
|
19 |
* @param int $code
|
24 |
public function __construct($message = "", $code = 0, $field = null, $documentationUrl = null, \Throwable $previous = null)
|
25 |
{
|
26 |
if (!empty($field)) {
|
27 |
+
$this->field = (string)$field;
|
28 |
$message .= ". Field: {$this->field}";
|
29 |
}
|
30 |
+
|
31 |
if (!empty($documentationUrl)) {
|
32 |
+
$this->documentationUrl = (string)$documentationUrl;
|
33 |
$message .= ". Documentation: {$this->documentationUrl}";
|
34 |
}
|
35 |
+
|
36 |
parent::__construct($message, $code, $previous);
|
37 |
+
|
38 |
+
|
39 |
}
|
40 |
+
|
41 |
/**
|
42 |
* @return string
|
43 |
*/
|
45 |
{
|
46 |
return $this->field;
|
47 |
}
|
48 |
+
|
49 |
/**
|
50 |
* @return string
|
51 |
*/
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Exceptions;
|
4 |
|
5 |
-
class IncompatiblePlatform extends
|
6 |
{
|
7 |
const INCOMPATIBLE_PHP_VERSION = 1000;
|
8 |
const INCOMPATIBLE_CURL_EXTENSION = 2000;
|
2 |
|
3 |
namespace Mollie\Api\Exceptions;
|
4 |
|
5 |
+
class IncompatiblePlatform extends ApiException
|
6 |
{
|
7 |
const INCOMPATIBLE_PHP_VERSION = 1000;
|
8 |
const INCOMPATIBLE_CURL_EXTENSION = 2000;
|
@@ -2,10 +2,10 @@
|
|
2 |
|
3 |
namespace Mollie\Api;
|
4 |
|
5 |
-
use
|
6 |
-
use
|
7 |
-
use
|
8 |
-
use
|
9 |
use Mollie\Api\Endpoints\CustomerEndpoint;
|
10 |
use Mollie\Api\Endpoints\CustomerPaymentsEndpoint;
|
11 |
use Mollie\Api\Endpoints\InvoiceEndpoint;
|
@@ -27,22 +27,26 @@ use Mollie\Api\Endpoints\ShipmentEndpoint;
|
|
27 |
use Mollie\Api\Endpoints\SubscriptionEndpoint;
|
28 |
use Mollie\Api\Exceptions\ApiException;
|
29 |
use Mollie\Api\Exceptions\IncompatiblePlatform;
|
30 |
-
use
|
31 |
-
use
|
|
|
32 |
class MollieApiClient
|
33 |
{
|
34 |
/**
|
35 |
* Version of our client.
|
36 |
*/
|
37 |
-
const CLIENT_VERSION =
|
|
|
38 |
/**
|
39 |
* Endpoint of the remote API.
|
40 |
*/
|
41 |
const API_ENDPOINT = "https://api.mollie.com";
|
|
|
42 |
/**
|
43 |
* Version of the remote API.
|
44 |
*/
|
45 |
const API_VERSION = "v2";
|
|
|
46 |
/**
|
47 |
* HTTP Methods
|
48 |
*/
|
@@ -50,187 +54,225 @@ class MollieApiClient
|
|
50 |
const HTTP_POST = "POST";
|
51 |
const HTTP_DELETE = "DELETE";
|
52 |
const HTTP_PATCH = "PATCH";
|
|
|
53 |
/**
|
54 |
* HTTP status codes
|
55 |
*/
|
56 |
const HTTP_NO_CONTENT = 204;
|
|
|
57 |
/**
|
58 |
* Default response timeout (in seconds).
|
59 |
*/
|
60 |
const TIMEOUT = 10;
|
|
|
61 |
/**
|
62 |
* @var ClientInterface
|
63 |
*/
|
64 |
protected $httpClient;
|
|
|
65 |
/**
|
66 |
* @var string
|
67 |
*/
|
68 |
protected $apiEndpoint = self::API_ENDPOINT;
|
|
|
69 |
/**
|
70 |
* RESTful Payments resource.
|
71 |
*
|
72 |
* @var PaymentEndpoint
|
73 |
*/
|
74 |
public $payments;
|
|
|
75 |
/**
|
76 |
* RESTful Methods resource.
|
77 |
*
|
78 |
* @var MethodEndpoint
|
79 |
*/
|
80 |
public $methods;
|
|
|
81 |
/**
|
82 |
* RESTful Customers resource.
|
83 |
*
|
84 |
* @var CustomerEndpoint
|
85 |
*/
|
86 |
public $customers;
|
|
|
87 |
/**
|
88 |
* RESTful Customer payments resource.
|
89 |
*
|
90 |
* @var CustomerPaymentsEndpoint
|
91 |
*/
|
92 |
public $customerPayments;
|
|
|
93 |
/**
|
94 |
* @var SettlementsEndpoint
|
95 |
*/
|
96 |
public $settlements;
|
|
|
97 |
/**
|
98 |
* RESTful Subscription resource.
|
99 |
*
|
100 |
* @var SubscriptionEndpoint
|
101 |
*/
|
102 |
public $subscriptions;
|
|
|
103 |
/**
|
104 |
* RESTful Mandate resource.
|
105 |
*
|
106 |
* @var MandateEndpoint
|
107 |
*/
|
108 |
public $mandates;
|
|
|
109 |
/**
|
110 |
* @var ProfileEndpoint
|
111 |
*/
|
112 |
public $profiles;
|
|
|
113 |
/**
|
114 |
* RESTful Organization resource.
|
115 |
*
|
116 |
* @var OrganizationEndpoint
|
117 |
*/
|
118 |
public $organizations;
|
|
|
119 |
/**
|
120 |
* RESTful Permission resource.
|
121 |
*
|
122 |
* @var PermissionEndpoint
|
123 |
*/
|
124 |
public $permissions;
|
|
|
125 |
/**
|
126 |
* RESTful Invoice resource.
|
127 |
*
|
128 |
* @var InvoiceEndpoint
|
129 |
*/
|
130 |
public $invoices;
|
|
|
131 |
/**
|
132 |
* RESTful Order resource.
|
133 |
*
|
134 |
* @var OrderEndpoint
|
135 |
*/
|
136 |
public $orders;
|
|
|
137 |
/**
|
138 |
* RESTful OrderLine resource.
|
139 |
*
|
140 |
* @var OrderLineEndpoint
|
141 |
*/
|
142 |
public $orderLines;
|
|
|
143 |
/**
|
144 |
* RESTful Shipment resource.
|
145 |
*
|
146 |
* @var ShipmentEndpoint
|
147 |
*/
|
148 |
public $shipments;
|
|
|
149 |
/**
|
150 |
* RESTful Refunds resource.
|
151 |
*
|
152 |
* @var RefundEndpoint
|
153 |
*/
|
154 |
public $refunds;
|
|
|
155 |
/**
|
156 |
* RESTful Payment Refunds resource.
|
157 |
*
|
158 |
* @var PaymentRefundEndpoint
|
159 |
*/
|
160 |
public $paymentRefunds;
|
|
|
161 |
/**
|
162 |
* RESTful Payment Captures resource.
|
163 |
*
|
164 |
* @var PaymentCaptureEndpoint
|
165 |
*/
|
166 |
public $paymentCaptures;
|
|
|
167 |
/**
|
168 |
* RESTful Payment Chargebacks resource.
|
169 |
*
|
170 |
* @var PaymentChargebacksEndpoint
|
171 |
*/
|
172 |
public $paymentChargebacks;
|
|
|
173 |
/**
|
174 |
* RESTful Order Refunds resource.
|
175 |
*
|
176 |
* @var OrderRefundEndpoint
|
177 |
*/
|
178 |
public $orderRefunds;
|
|
|
179 |
/**
|
180 |
* @var string
|
181 |
*/
|
182 |
protected $apiKey;
|
|
|
183 |
/**
|
184 |
* True if an OAuth access token is set as API key.
|
185 |
*
|
186 |
* @var bool
|
187 |
*/
|
188 |
protected $oauthAccess;
|
|
|
189 |
/**
|
190 |
* @var array
|
191 |
*/
|
192 |
protected $versionStrings = [];
|
|
|
193 |
/**
|
194 |
* @var int
|
195 |
*/
|
196 |
protected $lastHttpResponseStatusCode;
|
|
|
197 |
/**
|
198 |
* @param ClientInterface $httpClient
|
199 |
*
|
200 |
* @throws IncompatiblePlatform
|
201 |
*/
|
202 |
-
public function __construct(
|
203 |
{
|
204 |
-
$this->httpClient = $httpClient ?
|
205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
$compatibilityChecker->checkCompatibility();
|
|
|
207 |
$this->initializeEndpoints();
|
|
|
208 |
$this->addVersionString("Mollie/" . self::CLIENT_VERSION);
|
209 |
-
$this->addVersionString("PHP/" .
|
210 |
-
$this->addVersionString("Guzzle/" .
|
211 |
}
|
|
|
212 |
public function initializeEndpoints()
|
213 |
{
|
214 |
-
$this->payments = new
|
215 |
-
$this->methods = new
|
216 |
-
$this->customers = new
|
217 |
-
$this->settlements = new
|
218 |
-
$this->subscriptions = new
|
219 |
-
$this->customerPayments = new
|
220 |
-
$this->mandates = new
|
221 |
-
$this->invoices = new
|
222 |
-
$this->permissions = new
|
223 |
-
$this->profiles = new
|
224 |
-
$this->organizations = new
|
225 |
-
$this->orders = new
|
226 |
-
$this->orderLines = new
|
227 |
-
$this->orderRefunds = new
|
228 |
-
$this->shipments = new
|
229 |
-
$this->refunds = new
|
230 |
-
$this->paymentRefunds = new
|
231 |
-
$this->paymentCaptures = new
|
232 |
-
$this->paymentChargebacks = new
|
233 |
}
|
|
|
234 |
/**
|
235 |
* @param string $url
|
236 |
*
|
@@ -238,9 +280,10 @@ class MollieApiClient
|
|
238 |
*/
|
239 |
public function setApiEndpoint($url)
|
240 |
{
|
241 |
-
$this->apiEndpoint =
|
242 |
return $this;
|
243 |
}
|
|
|
244 |
/**
|
245 |
* @return string
|
246 |
*/
|
@@ -248,6 +291,7 @@ class MollieApiClient
|
|
248 |
{
|
249 |
return $this->apiEndpoint;
|
250 |
}
|
|
|
251 |
/**
|
252 |
* @param string $apiKey The Mollie API key, starting with 'test_' or 'live_'
|
253 |
*
|
@@ -256,14 +300,17 @@ class MollieApiClient
|
|
256 |
*/
|
257 |
public function setApiKey($apiKey)
|
258 |
{
|
259 |
-
$apiKey =
|
260 |
-
|
261 |
-
|
|
|
262 |
}
|
|
|
263 |
$this->apiKey = $apiKey;
|
264 |
-
$this->oauthAccess =
|
265 |
return $this;
|
266 |
}
|
|
|
267 |
/**
|
268 |
* @param string $accessToken OAuth access token, starting with 'access_'
|
269 |
*
|
@@ -272,14 +319,17 @@ class MollieApiClient
|
|
272 |
*/
|
273 |
public function setAccessToken($accessToken)
|
274 |
{
|
275 |
-
$accessToken =
|
276 |
-
|
277 |
-
|
|
|
278 |
}
|
|
|
279 |
$this->apiKey = $accessToken;
|
280 |
-
$this->oauthAccess =
|
281 |
return $this;
|
282 |
}
|
|
|
283 |
/**
|
284 |
* Returns null if no API key has been set yet.
|
285 |
*
|
@@ -289,6 +339,7 @@ class MollieApiClient
|
|
289 |
{
|
290 |
return $this->oauthAccess;
|
291 |
}
|
|
|
292 |
/**
|
293 |
* @param string $versionString
|
294 |
*
|
@@ -296,9 +347,10 @@ class MollieApiClient
|
|
296 |
*/
|
297 |
public function addVersionString($versionString)
|
298 |
{
|
299 |
-
$this->versionStrings[] =
|
300 |
return $this;
|
301 |
}
|
|
|
302 |
/**
|
303 |
* Perform an http call. This method is used by the resource specific classes. Please use the $payments property to
|
304 |
* perform operations on payments.
|
@@ -318,8 +370,10 @@ class MollieApiClient
|
|
318 |
public function performHttpCall($httpMethod, $apiMethod, $httpBody = null)
|
319 |
{
|
320 |
$url = $this->apiEndpoint . "/" . self::API_VERSION . "/" . $apiMethod;
|
|
|
321 |
return $this->performHttpCallToFullUrl($httpMethod, $url, $httpBody);
|
322 |
}
|
|
|
323 |
/**
|
324 |
* Perform an http call to a full url. This method is used by the resource specific classes.
|
325 |
*
|
@@ -338,27 +392,40 @@ class MollieApiClient
|
|
338 |
public function performHttpCallToFullUrl($httpMethod, $url, $httpBody = null)
|
339 |
{
|
340 |
if (empty($this->apiKey)) {
|
341 |
-
throw new
|
342 |
}
|
343 |
-
|
|
|
|
|
344 |
if ($this->usesOAuth()) {
|
345 |
$userAgent .= " OAuth/2.0";
|
346 |
}
|
347 |
-
|
348 |
-
|
349 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
350 |
}
|
351 |
-
|
|
|
|
|
352 |
try {
|
353 |
-
$response = $this->httpClient->send($request, ['http_errors' =>
|
354 |
-
} catch (
|
355 |
-
throw new
|
356 |
}
|
|
|
357 |
if (!$response) {
|
358 |
-
throw new
|
359 |
}
|
|
|
360 |
return $this->parseResponseBody($response);
|
361 |
}
|
|
|
362 |
/**
|
363 |
* Parse the PSR-7 Response body
|
364 |
*
|
@@ -366,32 +433,45 @@ class MollieApiClient
|
|
366 |
* @return object|null
|
367 |
* @throws ApiException
|
368 |
*/
|
369 |
-
private function parseResponseBody(
|
370 |
{
|
371 |
$body = (string) $response->getBody();
|
372 |
if (empty($body)) {
|
373 |
if ($response->getStatusCode() === self::HTTP_NO_CONTENT) {
|
374 |
return null;
|
375 |
}
|
376 |
-
|
|
|
377 |
}
|
378 |
-
|
379 |
-
|
380 |
-
|
|
|
|
|
381 |
}
|
|
|
382 |
if ($response->getStatusCode() >= 400) {
|
383 |
$field = null;
|
384 |
if (!empty($object->field)) {
|
385 |
$field = $object->field;
|
386 |
}
|
|
|
387 |
$documentationUrl = null;
|
388 |
if (!empty($object->_links) && !empty($object->_links->documentation)) {
|
389 |
$documentationUrl = $object->_links->documentation->href;
|
390 |
}
|
391 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
392 |
}
|
|
|
393 |
return $object;
|
394 |
}
|
|
|
395 |
/**
|
396 |
* Serialization can be used for caching. Of course doing so can be dangerous but some like to live dangerously.
|
397 |
*
|
@@ -409,6 +489,7 @@ class MollieApiClient
|
|
409 |
{
|
410 |
return ["apiEndpoint"];
|
411 |
}
|
|
|
412 |
/**
|
413 |
* When unserializing a collection or a resource, this class should restore itself.
|
414 |
*
|
2 |
|
3 |
namespace Mollie\Api;
|
4 |
|
5 |
+
use GuzzleHttp\Client;
|
6 |
+
use GuzzleHttp\ClientInterface;
|
7 |
+
use GuzzleHttp\Exception\GuzzleException;
|
8 |
+
use GuzzleHttp\Psr7\Request;
|
9 |
use Mollie\Api\Endpoints\CustomerEndpoint;
|
10 |
use Mollie\Api\Endpoints\CustomerPaymentsEndpoint;
|
11 |
use Mollie\Api\Endpoints\InvoiceEndpoint;
|
27 |
use Mollie\Api\Endpoints\SubscriptionEndpoint;
|
28 |
use Mollie\Api\Exceptions\ApiException;
|
29 |
use Mollie\Api\Exceptions\IncompatiblePlatform;
|
30 |
+
use Psr\Http\Message\ResponseInterface;
|
31 |
+
use Psr\Http\Message\StreamInterface;
|
32 |
+
|
33 |
class MollieApiClient
|
34 |
{
|
35 |
/**
|
36 |
* Version of our client.
|
37 |
*/
|
38 |
+
const CLIENT_VERSION = "2.1.2";
|
39 |
+
|
40 |
/**
|
41 |
* Endpoint of the remote API.
|
42 |
*/
|
43 |
const API_ENDPOINT = "https://api.mollie.com";
|
44 |
+
|
45 |
/**
|
46 |
* Version of the remote API.
|
47 |
*/
|
48 |
const API_VERSION = "v2";
|
49 |
+
|
50 |
/**
|
51 |
* HTTP Methods
|
52 |
*/
|
54 |
const HTTP_POST = "POST";
|
55 |
const HTTP_DELETE = "DELETE";
|
56 |
const HTTP_PATCH = "PATCH";
|
57 |
+
|
58 |
/**
|
59 |
* HTTP status codes
|
60 |
*/
|
61 |
const HTTP_NO_CONTENT = 204;
|
62 |
+
|
63 |
/**
|
64 |
* Default response timeout (in seconds).
|
65 |
*/
|
66 |
const TIMEOUT = 10;
|
67 |
+
|
68 |
/**
|
69 |
* @var ClientInterface
|
70 |
*/
|
71 |
protected $httpClient;
|
72 |
+
|
73 |
/**
|
74 |
* @var string
|
75 |
*/
|
76 |
protected $apiEndpoint = self::API_ENDPOINT;
|
77 |
+
|
78 |
/**
|
79 |
* RESTful Payments resource.
|
80 |
*
|
81 |
* @var PaymentEndpoint
|
82 |
*/
|
83 |
public $payments;
|
84 |
+
|
85 |
/**
|
86 |
* RESTful Methods resource.
|
87 |
*
|
88 |
* @var MethodEndpoint
|
89 |
*/
|
90 |
public $methods;
|
91 |
+
|
92 |
/**
|
93 |
* RESTful Customers resource.
|
94 |
*
|
95 |
* @var CustomerEndpoint
|
96 |
*/
|
97 |
public $customers;
|
98 |
+
|
99 |
/**
|
100 |
* RESTful Customer payments resource.
|
101 |
*
|
102 |
* @var CustomerPaymentsEndpoint
|
103 |
*/
|
104 |
public $customerPayments;
|
105 |
+
|
106 |
/**
|
107 |
* @var SettlementsEndpoint
|
108 |
*/
|
109 |
public $settlements;
|
110 |
+
|
111 |
/**
|
112 |
* RESTful Subscription resource.
|
113 |
*
|
114 |
* @var SubscriptionEndpoint
|
115 |
*/
|
116 |
public $subscriptions;
|
117 |
+
|
118 |
/**
|
119 |
* RESTful Mandate resource.
|
120 |
*
|
121 |
* @var MandateEndpoint
|
122 |
*/
|
123 |
public $mandates;
|
124 |
+
|
125 |
/**
|
126 |
* @var ProfileEndpoint
|
127 |
*/
|
128 |
public $profiles;
|
129 |
+
|
130 |
/**
|
131 |
* RESTful Organization resource.
|
132 |
*
|
133 |
* @var OrganizationEndpoint
|
134 |
*/
|
135 |
public $organizations;
|
136 |
+
|
137 |
/**
|
138 |
* RESTful Permission resource.
|
139 |
*
|
140 |
* @var PermissionEndpoint
|
141 |
*/
|
142 |
public $permissions;
|
143 |
+
|
144 |
/**
|
145 |
* RESTful Invoice resource.
|
146 |
*
|
147 |
* @var InvoiceEndpoint
|
148 |
*/
|
149 |
public $invoices;
|
150 |
+
|
151 |
/**
|
152 |
* RESTful Order resource.
|
153 |
*
|
154 |
* @var OrderEndpoint
|
155 |
*/
|
156 |
public $orders;
|
157 |
+
|
158 |
/**
|
159 |
* RESTful OrderLine resource.
|
160 |
*
|
161 |
* @var OrderLineEndpoint
|
162 |
*/
|
163 |
public $orderLines;
|
164 |
+
|
165 |
/**
|
166 |
* RESTful Shipment resource.
|
167 |
*
|
168 |
* @var ShipmentEndpoint
|
169 |
*/
|
170 |
public $shipments;
|
171 |
+
|
172 |
/**
|
173 |
* RESTful Refunds resource.
|
174 |
*
|
175 |
* @var RefundEndpoint
|
176 |
*/
|
177 |
public $refunds;
|
178 |
+
|
179 |
/**
|
180 |
* RESTful Payment Refunds resource.
|
181 |
*
|
182 |
* @var PaymentRefundEndpoint
|
183 |
*/
|
184 |
public $paymentRefunds;
|
185 |
+
|
186 |
/**
|
187 |
* RESTful Payment Captures resource.
|
188 |
*
|
189 |
* @var PaymentCaptureEndpoint
|
190 |
*/
|
191 |
public $paymentCaptures;
|
192 |
+
|
193 |
/**
|
194 |
* RESTful Payment Chargebacks resource.
|
195 |
*
|
196 |
* @var PaymentChargebacksEndpoint
|
197 |
*/
|
198 |
public $paymentChargebacks;
|
199 |
+
|
200 |
/**
|
201 |
* RESTful Order Refunds resource.
|
202 |
*
|
203 |
* @var OrderRefundEndpoint
|
204 |
*/
|
205 |
public $orderRefunds;
|
206 |
+
|
207 |
/**
|
208 |
* @var string
|
209 |
*/
|
210 |
protected $apiKey;
|
211 |
+
|
212 |
/**
|
213 |
* True if an OAuth access token is set as API key.
|
214 |
*
|
215 |
* @var bool
|
216 |
*/
|
217 |
protected $oauthAccess;
|
218 |
+
|
219 |
/**
|
220 |
* @var array
|
221 |
*/
|
222 |
protected $versionStrings = [];
|
223 |
+
|
224 |
/**
|
225 |
* @var int
|
226 |
*/
|
227 |
protected $lastHttpResponseStatusCode;
|
228 |
+
|
229 |
/**
|
230 |
* @param ClientInterface $httpClient
|
231 |
*
|
232 |
* @throws IncompatiblePlatform
|
233 |
*/
|
234 |
+
public function __construct(ClientInterface $httpClient = null)
|
235 |
{
|
236 |
+
$this->httpClient = $httpClient ?
|
237 |
+
$httpClient :
|
238 |
+
new Client([
|
239 |
+
\GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getBundledCaBundlePath(),
|
240 |
+
\GuzzleHttp\RequestOptions::TIMEOUT => self::TIMEOUT,
|
241 |
+
]);
|
242 |
+
|
243 |
+
$compatibilityChecker = new CompatibilityChecker();
|
244 |
$compatibilityChecker->checkCompatibility();
|
245 |
+
|
246 |
$this->initializeEndpoints();
|
247 |
+
|
248 |
$this->addVersionString("Mollie/" . self::CLIENT_VERSION);
|
249 |
+
$this->addVersionString("PHP/" . phpversion());
|
250 |
+
$this->addVersionString("Guzzle/" . ClientInterface::VERSION);
|
251 |
}
|
252 |
+
|
253 |
public function initializeEndpoints()
|
254 |
{
|
255 |
+
$this->payments = new PaymentEndpoint($this);
|
256 |
+
$this->methods = new MethodEndpoint($this);
|
257 |
+
$this->customers = new CustomerEndpoint($this);
|
258 |
+
$this->settlements = new SettlementsEndpoint($this);
|
259 |
+
$this->subscriptions = new SubscriptionEndpoint($this);
|
260 |
+
$this->customerPayments = new CustomerPaymentsEndpoint($this);
|
261 |
+
$this->mandates = new MandateEndpoint($this);
|
262 |
+
$this->invoices = new InvoiceEndpoint($this);
|
263 |
+
$this->permissions = new PermissionEndpoint($this);
|
264 |
+
$this->profiles = new ProfileEndpoint($this);
|
265 |
+
$this->organizations = new OrganizationEndpoint($this);
|
266 |
+
$this->orders = new OrderEndpoint($this);
|
267 |
+
$this->orderLines = new OrderLineEndpoint($this);
|
268 |
+
$this->orderRefunds = new OrderRefundEndpoint($this);
|
269 |
+
$this->shipments = new ShipmentEndpoint($this);
|
270 |
+
$this->refunds = new RefundEndpoint($this);
|
271 |
+
$this->paymentRefunds = new PaymentRefundEndpoint($this);
|
272 |
+
$this->paymentCaptures = new PaymentCaptureEndpoint($this);
|
273 |
+
$this->paymentChargebacks = new PaymentChargebackEndpoint($this);
|
274 |
}
|
275 |
+
|
276 |
/**
|
277 |
* @param string $url
|
278 |
*
|
280 |
*/
|
281 |
public function setApiEndpoint($url)
|
282 |
{
|
283 |
+
$this->apiEndpoint = rtrim(trim($url), '/');
|
284 |
return $this;
|
285 |
}
|
286 |
+
|
287 |
/**
|
288 |
* @return string
|
289 |
*/
|
291 |
{
|
292 |
return $this->apiEndpoint;
|
293 |
}
|
294 |
+
|
295 |
/**
|
296 |
* @param string $apiKey The Mollie API key, starting with 'test_' or 'live_'
|
297 |
*
|
300 |
*/
|
301 |
public function setApiKey($apiKey)
|
302 |
{
|
303 |
+
$apiKey = trim($apiKey);
|
304 |
+
|
305 |
+
if (!preg_match('/^(live|test)_\w{30,}$/', $apiKey)) {
|
306 |
+
throw new ApiException("Invalid API key: '{$apiKey}'. An API key must start with 'test_' or 'live_' and must be at least 30 characters long.");
|
307 |
}
|
308 |
+
|
309 |
$this->apiKey = $apiKey;
|
310 |
+
$this->oauthAccess = false;
|
311 |
return $this;
|
312 |
}
|
313 |
+
|
314 |
/**
|
315 |
* @param string $accessToken OAuth access token, starting with 'access_'
|
316 |
*
|
319 |
*/
|
320 |
public function setAccessToken($accessToken)
|
321 |
{
|
322 |
+
$accessToken = trim($accessToken);
|
323 |
+
|
324 |
+
if (!preg_match('/^access_\w+$/', $accessToken)) {
|
325 |
+
throw new ApiException("Invalid OAuth access token: '{$accessToken}'. An access token must start with 'access_'.");
|
326 |
}
|
327 |
+
|
328 |
$this->apiKey = $accessToken;
|
329 |
+
$this->oauthAccess = true;
|
330 |
return $this;
|
331 |
}
|
332 |
+
|
333 |
/**
|
334 |
* Returns null if no API key has been set yet.
|
335 |
*
|
339 |
{
|
340 |
return $this->oauthAccess;
|
341 |
}
|
342 |
+
|
343 |
/**
|
344 |
* @param string $versionString
|
345 |
*
|
347 |
*/
|
348 |
public function addVersionString($versionString)
|
349 |
{
|
350 |
+
$this->versionStrings[] = str_replace([" ", "\t", "\n", "\r"], '-', $versionString);
|
351 |
return $this;
|
352 |
}
|
353 |
+
|
354 |
/**
|
355 |
* Perform an http call. This method is used by the resource specific classes. Please use the $payments property to
|
356 |
* perform operations on payments.
|
370 |
public function performHttpCall($httpMethod, $apiMethod, $httpBody = null)
|
371 |
{
|
372 |
$url = $this->apiEndpoint . "/" . self::API_VERSION . "/" . $apiMethod;
|
373 |
+
|
374 |
return $this->performHttpCallToFullUrl($httpMethod, $url, $httpBody);
|
375 |
}
|
376 |
+
|
377 |
/**
|
378 |
* Perform an http call to a full url. This method is used by the resource specific classes.
|
379 |
*
|
392 |
public function performHttpCallToFullUrl($httpMethod, $url, $httpBody = null)
|
393 |
{
|
394 |
if (empty($this->apiKey)) {
|
395 |
+
throw new ApiException("You have not set an API key or OAuth access token. Please use setApiKey() to set the API key.");
|
396 |
}
|
397 |
+
|
398 |
+
$userAgent = implode(' ', $this->versionStrings);
|
399 |
+
|
400 |
if ($this->usesOAuth()) {
|
401 |
$userAgent .= " OAuth/2.0";
|
402 |
}
|
403 |
+
|
404 |
+
$headers = [
|
405 |
+
'Accept' => "application/json",
|
406 |
+
'Authorization' => "Bearer {$this->apiKey}",
|
407 |
+
'User-Agent' => $userAgent,
|
408 |
+
];
|
409 |
+
|
410 |
+
if (function_exists("php_uname")) {
|
411 |
+
$headers['X-Mollie-Client-Info'] = php_uname();
|
412 |
}
|
413 |
+
|
414 |
+
$request = new Request($httpMethod, $url, $headers, $httpBody);
|
415 |
+
|
416 |
try {
|
417 |
+
$response = $this->httpClient->send($request, ['http_errors' => false]);
|
418 |
+
} catch (GuzzleException $e) {
|
419 |
+
throw new ApiException($e->getMessage(), $e->getCode(), $e);
|
420 |
}
|
421 |
+
|
422 |
if (!$response) {
|
423 |
+
throw new ApiException("Did not receive API response.");
|
424 |
}
|
425 |
+
|
426 |
return $this->parseResponseBody($response);
|
427 |
}
|
428 |
+
|
429 |
/**
|
430 |
* Parse the PSR-7 Response body
|
431 |
*
|
433 |
* @return object|null
|
434 |
* @throws ApiException
|
435 |
*/
|
436 |
+
private function parseResponseBody(ResponseInterface $response)
|
437 |
{
|
438 |
$body = (string) $response->getBody();
|
439 |
if (empty($body)) {
|
440 |
if ($response->getStatusCode() === self::HTTP_NO_CONTENT) {
|
441 |
return null;
|
442 |
}
|
443 |
+
|
444 |
+
throw new ApiException("No response body found.");
|
445 |
}
|
446 |
+
|
447 |
+
$object = @json_decode($body);
|
448 |
+
|
449 |
+
if (json_last_error() !== JSON_ERROR_NONE) {
|
450 |
+
throw new ApiException("Unable to decode Mollie response: '{$body}'.");
|
451 |
}
|
452 |
+
|
453 |
if ($response->getStatusCode() >= 400) {
|
454 |
$field = null;
|
455 |
if (!empty($object->field)) {
|
456 |
$field = $object->field;
|
457 |
}
|
458 |
+
|
459 |
$documentationUrl = null;
|
460 |
if (!empty($object->_links) && !empty($object->_links->documentation)) {
|
461 |
$documentationUrl = $object->_links->documentation->href;
|
462 |
}
|
463 |
+
|
464 |
+
throw new ApiException(
|
465 |
+
"Error executing API call ({$object->status}: {$object->title}): {$object->detail}",
|
466 |
+
$response->getStatusCode(),
|
467 |
+
$field,
|
468 |
+
$documentationUrl
|
469 |
+
);
|
470 |
}
|
471 |
+
|
472 |
return $object;
|
473 |
}
|
474 |
+
|
475 |
/**
|
476 |
* Serialization can be used for caching. Of course doing so can be dangerous but some like to live dangerously.
|
477 |
*
|
489 |
{
|
490 |
return ["apiEndpoint"];
|
491 |
}
|
492 |
+
|
493 |
/**
|
494 |
* When unserializing a collection or a resource, this class should restore itself.
|
495 |
*
|
@@ -10,10 +10,12 @@ abstract class BaseCollection extends \ArrayObject
|
|
10 |
* @var int
|
11 |
*/
|
12 |
public $count;
|
|
|
13 |
/**
|
14 |
* @var object[]
|
15 |
*/
|
16 |
public $_links;
|
|
|
17 |
/**
|
18 |
* @param int $count
|
19 |
* @param object[] $_links
|
@@ -23,8 +25,9 @@ abstract class BaseCollection extends \ArrayObject
|
|
23 |
$this->count = $count;
|
24 |
$this->_links = $_links;
|
25 |
}
|
|
|
26 |
/**
|
27 |
* @return string|null
|
28 |
*/
|
29 |
-
public
|
30 |
}
|
10 |
* @var int
|
11 |
*/
|
12 |
public $count;
|
13 |
+
|
14 |
/**
|
15 |
* @var object[]
|
16 |
*/
|
17 |
public $_links;
|
18 |
+
|
19 |
/**
|
20 |
* @param int $count
|
21 |
* @param object[] $_links
|
25 |
$this->count = $count;
|
26 |
$this->_links = $_links;
|
27 |
}
|
28 |
+
|
29 |
/**
|
30 |
* @return string|null
|
31 |
*/
|
32 |
+
abstract public function getCollectionResourceName();
|
33 |
}
|
@@ -3,17 +3,19 @@
|
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
|
|
6 |
abstract class BaseResource
|
7 |
{
|
8 |
/**
|
9 |
* @var MollieApiClient
|
10 |
*/
|
11 |
protected $client;
|
|
|
12 |
/**
|
13 |
* @param $client
|
14 |
*/
|
15 |
-
public function __construct(
|
16 |
{
|
17 |
$this->client = $client;
|
18 |
}
|
19 |
-
}
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
+
|
7 |
abstract class BaseResource
|
8 |
{
|
9 |
/**
|
10 |
* @var MollieApiClient
|
11 |
*/
|
12 |
protected $client;
|
13 |
+
|
14 |
/**
|
15 |
* @param $client
|
16 |
*/
|
17 |
+
public function __construct(MollieApiClient $client)
|
18 |
{
|
19 |
$this->client = $client;
|
20 |
}
|
21 |
+
}
|
@@ -2,58 +2,67 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class Capture extends
|
6 |
{
|
7 |
/**
|
8 |
* Always 'capture' for this object
|
9 |
* @var string
|
10 |
*/
|
11 |
public $resource;
|
|
|
12 |
/**
|
13 |
* Id of the capture
|
14 |
* @var string
|
15 |
*/
|
16 |
public $id;
|
|
|
17 |
/**
|
18 |
* Mode of the capture, either "live" or "test" depending on the API Key that was used.
|
19 |
*
|
20 |
* @var string
|
21 |
*/
|
22 |
public $mode;
|
|
|
23 |
/**
|
24 |
* Amount object containing the value and currency
|
25 |
*
|
26 |
* @var object
|
27 |
*/
|
28 |
public $amount;
|
|
|
29 |
/**
|
30 |
* Amount object containing the settlement value and currency
|
31 |
*
|
32 |
* @var object
|
33 |
*/
|
34 |
public $settlementAmount;
|
|
|
35 |
/**
|
36 |
* Id of the capture's payment (on the Mollie platform).
|
37 |
*
|
38 |
* @var string
|
39 |
*/
|
40 |
public $paymentId;
|
|
|
41 |
/**
|
42 |
* Id of the capture's shipment (on the Mollie platform).
|
43 |
*
|
44 |
* @var string
|
45 |
*/
|
46 |
public $shipmentId;
|
|
|
47 |
/**
|
48 |
* Id of the capture's settlement (on the Mollie platform).
|
49 |
*
|
50 |
* @var string
|
51 |
*/
|
52 |
public $settlementId;
|
|
|
53 |
/**
|
54 |
* @var string
|
55 |
*/
|
56 |
public $createdAt;
|
|
|
57 |
/**
|
58 |
* @var object
|
59 |
*/
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class Capture extends BaseResource
|
6 |
{
|
7 |
/**
|
8 |
* Always 'capture' for this object
|
9 |
* @var string
|
10 |
*/
|
11 |
public $resource;
|
12 |
+
|
13 |
/**
|
14 |
* Id of the capture
|
15 |
* @var string
|
16 |
*/
|
17 |
public $id;
|
18 |
+
|
19 |
/**
|
20 |
* Mode of the capture, either "live" or "test" depending on the API Key that was used.
|
21 |
*
|
22 |
* @var string
|
23 |
*/
|
24 |
public $mode;
|
25 |
+
|
26 |
/**
|
27 |
* Amount object containing the value and currency
|
28 |
*
|
29 |
* @var object
|
30 |
*/
|
31 |
public $amount;
|
32 |
+
|
33 |
/**
|
34 |
* Amount object containing the settlement value and currency
|
35 |
*
|
36 |
* @var object
|
37 |
*/
|
38 |
public $settlementAmount;
|
39 |
+
|
40 |
/**
|
41 |
* Id of the capture's payment (on the Mollie platform).
|
42 |
*
|
43 |
* @var string
|
44 |
*/
|
45 |
public $paymentId;
|
46 |
+
|
47 |
/**
|
48 |
* Id of the capture's shipment (on the Mollie platform).
|
49 |
*
|
50 |
* @var string
|
51 |
*/
|
52 |
public $shipmentId;
|
53 |
+
|
54 |
/**
|
55 |
* Id of the capture's settlement (on the Mollie platform).
|
56 |
*
|
57 |
* @var string
|
58 |
*/
|
59 |
public $settlementId;
|
60 |
+
|
61 |
/**
|
62 |
* @var string
|
63 |
*/
|
64 |
public $createdAt;
|
65 |
+
|
66 |
/**
|
67 |
* @var object
|
68 |
*/
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class CaptureCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class CaptureCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "captures";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class CaptureCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "captures";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Capture($this->client);
|
21 |
}
|
22 |
}
|
@@ -8,7 +8,7 @@ namespace Mollie\Api\Resources;
|
|
8 |
* @method Refund create(array $data = [], array $filters = [])
|
9 |
* @method Refund delete($refundId)
|
10 |
*/
|
11 |
-
class Chargeback extends
|
12 |
{
|
13 |
/**
|
14 |
* Id of the payment method.
|
@@ -16,12 +16,14 @@ class Chargeback extends \Mollie\Api\Resources\BaseResource
|
|
16 |
* @var string
|
17 |
*/
|
18 |
public $id;
|
|
|
19 |
/**
|
20 |
* The $amount that was refunded.
|
21 |
*
|
22 |
* @var object
|
23 |
*/
|
24 |
public $amount;
|
|
|
25 |
/**
|
26 |
* UTC datetime the payment was created in ISO-8601 format.
|
27 |
*
|
@@ -29,20 +31,24 @@ class Chargeback extends \Mollie\Api\Resources\BaseResource
|
|
29 |
* @var string|null
|
30 |
*/
|
31 |
public $createdAt;
|
|
|
32 |
/**
|
33 |
* The payment id that was refunded.
|
34 |
*
|
35 |
* @var string
|
36 |
*/
|
37 |
public $paymentId;
|
|
|
38 |
/**
|
39 |
* The settlement amount
|
40 |
*
|
41 |
* @var object
|
42 |
*/
|
43 |
public $settlementAmount;
|
|
|
44 |
/**
|
45 |
* @var object[]
|
46 |
*/
|
47 |
public $_links;
|
|
|
48 |
}
|
8 |
* @method Refund create(array $data = [], array $filters = [])
|
9 |
* @method Refund delete($refundId)
|
10 |
*/
|
11 |
+
class Chargeback extends BaseResource
|
12 |
{
|
13 |
/**
|
14 |
* Id of the payment method.
|
16 |
* @var string
|
17 |
*/
|
18 |
public $id;
|
19 |
+
|
20 |
/**
|
21 |
* The $amount that was refunded.
|
22 |
*
|
23 |
* @var object
|
24 |
*/
|
25 |
public $amount;
|
26 |
+
|
27 |
/**
|
28 |
* UTC datetime the payment was created in ISO-8601 format.
|
29 |
*
|
31 |
* @var string|null
|
32 |
*/
|
33 |
public $createdAt;
|
34 |
+
|
35 |
/**
|
36 |
* The payment id that was refunded.
|
37 |
*
|
38 |
* @var string
|
39 |
*/
|
40 |
public $paymentId;
|
41 |
+
|
42 |
/**
|
43 |
* The settlement amount
|
44 |
*
|
45 |
* @var object
|
46 |
*/
|
47 |
public $settlementAmount;
|
48 |
+
|
49 |
/**
|
50 |
* @var object[]
|
51 |
*/
|
52 |
public $_links;
|
53 |
+
|
54 |
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class ChargebackCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class ChargebackCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "chargebacks";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class ChargebackCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "chargebacks";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Chargeback($this->client);
|
21 |
}
|
22 |
+
}
|
@@ -3,58 +3,72 @@
|
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
-
|
|
|
7 |
{
|
8 |
/**
|
9 |
* @var MollieApiClient
|
10 |
*/
|
11 |
protected $client;
|
|
|
12 |
/**
|
13 |
* @param MollieApiClient $client
|
14 |
* @param int $count
|
15 |
* @param object[] $_links
|
16 |
*/
|
17 |
-
public
|
18 |
{
|
19 |
parent::__construct($count, $_links);
|
|
|
20 |
$this->client = $client;
|
21 |
}
|
|
|
22 |
/**
|
23 |
* @return BaseResource
|
24 |
*/
|
25 |
-
protected
|
|
|
26 |
/**
|
27 |
* Return the next set of resources when available
|
28 |
*
|
29 |
* @return CursorCollection|null
|
30 |
*/
|
31 |
-
public
|
32 |
{
|
33 |
if (!isset($this->_links->next->href)) {
|
34 |
return null;
|
35 |
}
|
36 |
-
|
|
|
|
|
37 |
$collection = new static($this->client, $result->count, $result->_links);
|
|
|
38 |
foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) {
|
39 |
-
$collection[] =
|
40 |
}
|
|
|
41 |
return $collection;
|
42 |
}
|
|
|
43 |
/**
|
44 |
* Return the previous set of resources when available
|
45 |
*
|
46 |
* @return CursorCollection|null
|
47 |
*/
|
48 |
-
public
|
49 |
{
|
50 |
if (!isset($this->_links->previous->href)) {
|
51 |
return null;
|
52 |
}
|
53 |
-
|
|
|
|
|
54 |
$collection = new static($this->client, $result->count, $result->_links);
|
|
|
55 |
foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) {
|
56 |
-
$collection[] =
|
57 |
}
|
|
|
58 |
return $collection;
|
59 |
}
|
60 |
-
}
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
+
|
7 |
+
abstract class CursorCollection extends BaseCollection
|
8 |
{
|
9 |
/**
|
10 |
* @var MollieApiClient
|
11 |
*/
|
12 |
protected $client;
|
13 |
+
|
14 |
/**
|
15 |
* @param MollieApiClient $client
|
16 |
* @param int $count
|
17 |
* @param object[] $_links
|
18 |
*/
|
19 |
+
final public function __construct(MollieApiClient $client, $count, $_links)
|
20 |
{
|
21 |
parent::__construct($count, $_links);
|
22 |
+
|
23 |
$this->client = $client;
|
24 |
}
|
25 |
+
|
26 |
/**
|
27 |
* @return BaseResource
|
28 |
*/
|
29 |
+
abstract protected function createResourceObject();
|
30 |
+
|
31 |
/**
|
32 |
* Return the next set of resources when available
|
33 |
*
|
34 |
* @return CursorCollection|null
|
35 |
*/
|
36 |
+
final public function next()
|
37 |
{
|
38 |
if (!isset($this->_links->next->href)) {
|
39 |
return null;
|
40 |
}
|
41 |
+
|
42 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->next->href);
|
43 |
+
|
44 |
$collection = new static($this->client, $result->count, $result->_links);
|
45 |
+
|
46 |
foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) {
|
47 |
+
$collection[] = ResourceFactory::createFromApiResult($dataResult, $this->createResourceObject());
|
48 |
}
|
49 |
+
|
50 |
return $collection;
|
51 |
}
|
52 |
+
|
53 |
/**
|
54 |
* Return the previous set of resources when available
|
55 |
*
|
56 |
* @return CursorCollection|null
|
57 |
*/
|
58 |
+
final public function previous()
|
59 |
{
|
60 |
if (!isset($this->_links->previous->href)) {
|
61 |
return null;
|
62 |
}
|
63 |
+
|
64 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->previous->href);
|
65 |
+
|
66 |
$collection = new static($this->client, $result->count, $result->_links);
|
67 |
+
|
68 |
foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) {
|
69 |
+
$collection[] = ResourceFactory::createFromApiResult($dataResult, $this->createResourceObject());
|
70 |
}
|
71 |
+
|
72 |
return $collection;
|
73 |
}
|
74 |
+
}
|
@@ -3,52 +3,63 @@
|
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
-
|
|
|
7 |
{
|
8 |
/**
|
9 |
* @var string
|
10 |
*/
|
11 |
public $resource;
|
|
|
12 |
/**
|
13 |
* Id of the customer.
|
14 |
*
|
15 |
* @var string
|
16 |
*/
|
17 |
public $id;
|
|
|
18 |
/**
|
19 |
* Either "live" or "test". Indicates this being a test or a live (verified) customer.
|
20 |
*
|
21 |
* @var string
|
22 |
*/
|
23 |
public $mode;
|
|
|
24 |
/**
|
25 |
* @var string
|
26 |
*/
|
27 |
public $name;
|
|
|
28 |
/**
|
29 |
* @var string
|
30 |
*/
|
31 |
public $email;
|
|
|
32 |
/**
|
33 |
* @var string|null
|
34 |
*/
|
35 |
public $locale;
|
|
|
36 |
/**
|
37 |
* @var object|mixed|null
|
38 |
*/
|
39 |
public $metadata;
|
|
|
40 |
/**
|
41 |
* @var string[]|array
|
42 |
*/
|
43 |
public $recentlyUsedMethods;
|
|
|
44 |
/**
|
45 |
* @var string
|
46 |
*/
|
47 |
public $createdAt;
|
|
|
48 |
/**
|
49 |
* @var object[]
|
50 |
*/
|
51 |
public $_links;
|
|
|
52 |
/**
|
53 |
* @return Customer
|
54 |
*/
|
@@ -57,10 +68,19 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
57 |
if (!isset($this->_links->self->href)) {
|
58 |
return $this;
|
59 |
}
|
60 |
-
|
61 |
-
$
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
}
|
|
|
64 |
/**
|
65 |
* @param array $options
|
66 |
* @param array $filters
|
@@ -71,6 +91,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
71 |
{
|
72 |
return $this->client->customerPayments->createFor($this, $options, $filters);
|
73 |
}
|
|
|
74 |
/**
|
75 |
* Get all payments for this customer
|
76 |
*
|
@@ -80,6 +101,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
80 |
{
|
81 |
return $this->client->customerPayments->listFor($this, null, null, $this->getPresetOptions());
|
82 |
}
|
|
|
83 |
/**
|
84 |
* @param array $options
|
85 |
* @param array $filters
|
@@ -90,6 +112,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
90 |
{
|
91 |
return $this->client->subscriptions->createFor($this, $options, $filters);
|
92 |
}
|
|
|
93 |
/**
|
94 |
* @param string $subscriptionId
|
95 |
* @param array $parameters
|
@@ -100,6 +123,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
100 |
{
|
101 |
return $this->client->subscriptions->getFor($this, $subscriptionId, $parameters);
|
102 |
}
|
|
|
103 |
/**
|
104 |
* @param string $subscriptionId
|
105 |
*
|
@@ -109,6 +133,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
109 |
{
|
110 |
return $this->client->subscriptions->cancelFor($this, $subscriptionId, $this->getPresetOptions());
|
111 |
}
|
|
|
112 |
/**
|
113 |
* Get all subscriptions for this customer
|
114 |
*
|
@@ -118,6 +143,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
118 |
{
|
119 |
return $this->client->subscriptions->listFor($this, null, null, $this->getPresetOptions());
|
120 |
}
|
|
|
121 |
/**
|
122 |
* @param array $options
|
123 |
* @param array $filters
|
@@ -128,6 +154,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
128 |
{
|
129 |
return $this->client->mandates->createFor($this, $options, $filters);
|
130 |
}
|
|
|
131 |
/**
|
132 |
* @param string $mandateId
|
133 |
* @param array $parameters
|
@@ -138,6 +165,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
138 |
{
|
139 |
return $this->client->mandates->getFor($this, $mandateId, $parameters);
|
140 |
}
|
|
|
141 |
/**
|
142 |
* @param string $mandateId
|
143 |
*
|
@@ -147,6 +175,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
147 |
{
|
148 |
return $this->client->mandates->revokeFor($this, $mandateId, $this->getPresetOptions());
|
149 |
}
|
|
|
150 |
/**
|
151 |
* Get all mandates for this customer
|
152 |
*
|
@@ -156,6 +185,7 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
156 |
{
|
157 |
return $this->client->mandates->listFor($this, null, null, $this->getPresetOptions());
|
158 |
}
|
|
|
159 |
/**
|
160 |
* Helper function to check for mandate with status valid
|
161 |
*
|
@@ -166,11 +196,13 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
166 |
$mandates = $this->client->mandates->listFor($this, null, null, $this->getPresetOptions());
|
167 |
foreach ($mandates as $mandate) {
|
168 |
if ($mandate->isValid()) {
|
169 |
-
return
|
170 |
}
|
171 |
}
|
172 |
-
|
|
|
173 |
}
|
|
|
174 |
/**
|
175 |
* When accessed by oAuth we want to pass the testmode by default
|
176 |
*
|
@@ -179,9 +211,10 @@ class Customer extends \Mollie\Api\Resources\BaseResource
|
|
179 |
private function getPresetOptions()
|
180 |
{
|
181 |
$options = [];
|
182 |
-
if
|
183 |
-
$options["testmode"] = $this->mode === "test" ?
|
184 |
}
|
|
|
185 |
return $options;
|
186 |
}
|
187 |
-
}
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
+
|
7 |
+
class Customer extends BaseResource
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
public $resource;
|
13 |
+
|
14 |
/**
|
15 |
* Id of the customer.
|
16 |
*
|
17 |
* @var string
|
18 |
*/
|
19 |
public $id;
|
20 |
+
|
21 |
/**
|
22 |
* Either "live" or "test". Indicates this being a test or a live (verified) customer.
|
23 |
*
|
24 |
* @var string
|
25 |
*/
|
26 |
public $mode;
|
27 |
+
|
28 |
/**
|
29 |
* @var string
|
30 |
*/
|
31 |
public $name;
|
32 |
+
|
33 |
/**
|
34 |
* @var string
|
35 |
*/
|
36 |
public $email;
|
37 |
+
|
38 |
/**
|
39 |
* @var string|null
|
40 |
*/
|
41 |
public $locale;
|
42 |
+
|
43 |
/**
|
44 |
* @var object|mixed|null
|
45 |
*/
|
46 |
public $metadata;
|
47 |
+
|
48 |
/**
|
49 |
* @var string[]|array
|
50 |
*/
|
51 |
public $recentlyUsedMethods;
|
52 |
+
|
53 |
/**
|
54 |
* @var string
|
55 |
*/
|
56 |
public $createdAt;
|
57 |
+
|
58 |
/**
|
59 |
* @var object[]
|
60 |
*/
|
61 |
public $_links;
|
62 |
+
|
63 |
/**
|
64 |
* @return Customer
|
65 |
*/
|
68 |
if (!isset($this->_links->self->href)) {
|
69 |
return $this;
|
70 |
}
|
71 |
+
|
72 |
+
$body = json_encode(array(
|
73 |
+
"name" => $this->name,
|
74 |
+
"email" => $this->email,
|
75 |
+
"locale" => $this->locale,
|
76 |
+
"metadata" => $this->metadata,
|
77 |
+
));
|
78 |
+
|
79 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_PATCH, $this->_links->self->href, $body);
|
80 |
+
|
81 |
+
return ResourceFactory::createFromApiResult($result, new Customer($this->client));
|
82 |
}
|
83 |
+
|
84 |
/**
|
85 |
* @param array $options
|
86 |
* @param array $filters
|
91 |
{
|
92 |
return $this->client->customerPayments->createFor($this, $options, $filters);
|
93 |
}
|
94 |
+
|
95 |
/**
|
96 |
* Get all payments for this customer
|
97 |
*
|
101 |
{
|
102 |
return $this->client->customerPayments->listFor($this, null, null, $this->getPresetOptions());
|
103 |
}
|
104 |
+
|
105 |
/**
|
106 |
* @param array $options
|
107 |
* @param array $filters
|
112 |
{
|
113 |
return $this->client->subscriptions->createFor($this, $options, $filters);
|
114 |
}
|
115 |
+
|
116 |
/**
|
117 |
* @param string $subscriptionId
|
118 |
* @param array $parameters
|
123 |
{
|
124 |
return $this->client->subscriptions->getFor($this, $subscriptionId, $parameters);
|
125 |
}
|
126 |
+
|
127 |
/**
|
128 |
* @param string $subscriptionId
|
129 |
*
|
133 |
{
|
134 |
return $this->client->subscriptions->cancelFor($this, $subscriptionId, $this->getPresetOptions());
|
135 |
}
|
136 |
+
|
137 |
/**
|
138 |
* Get all subscriptions for this customer
|
139 |
*
|
143 |
{
|
144 |
return $this->client->subscriptions->listFor($this, null, null, $this->getPresetOptions());
|
145 |
}
|
146 |
+
|
147 |
/**
|
148 |
* @param array $options
|
149 |
* @param array $filters
|
154 |
{
|
155 |
return $this->client->mandates->createFor($this, $options, $filters);
|
156 |
}
|
157 |
+
|
158 |
/**
|
159 |
* @param string $mandateId
|
160 |
* @param array $parameters
|
165 |
{
|
166 |
return $this->client->mandates->getFor($this, $mandateId, $parameters);
|
167 |
}
|
168 |
+
|
169 |
/**
|
170 |
* @param string $mandateId
|
171 |
*
|
175 |
{
|
176 |
return $this->client->mandates->revokeFor($this, $mandateId, $this->getPresetOptions());
|
177 |
}
|
178 |
+
|
179 |
/**
|
180 |
* Get all mandates for this customer
|
181 |
*
|
185 |
{
|
186 |
return $this->client->mandates->listFor($this, null, null, $this->getPresetOptions());
|
187 |
}
|
188 |
+
|
189 |
/**
|
190 |
* Helper function to check for mandate with status valid
|
191 |
*
|
196 |
$mandates = $this->client->mandates->listFor($this, null, null, $this->getPresetOptions());
|
197 |
foreach ($mandates as $mandate) {
|
198 |
if ($mandate->isValid()) {
|
199 |
+
return true;
|
200 |
}
|
201 |
}
|
202 |
+
|
203 |
+
return false;
|
204 |
}
|
205 |
+
|
206 |
/**
|
207 |
* When accessed by oAuth we want to pass the testmode by default
|
208 |
*
|
211 |
private function getPresetOptions()
|
212 |
{
|
213 |
$options = [];
|
214 |
+
if($this->client->usesOAuth()) {
|
215 |
+
$options["testmode"] = $this->mode === "test" ? true : false;
|
216 |
}
|
217 |
+
|
218 |
return $options;
|
219 |
}
|
220 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class CustomerCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class CustomerCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "customers";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class CustomerCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "customers";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Customer($this->client);
|
21 |
}
|
22 |
+
}
|
@@ -3,64 +3,76 @@
|
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\Types\InvoiceStatus;
|
6 |
-
|
|
|
7 |
{
|
8 |
/**
|
9 |
* @var string
|
10 |
*/
|
11 |
public $resource;
|
|
|
12 |
/**
|
13 |
* @var string
|
14 |
*/
|
15 |
public $id;
|
|
|
16 |
/**
|
17 |
* @var string
|
18 |
*/
|
19 |
public $reference;
|
|
|
20 |
/**
|
21 |
* @var string
|
22 |
*/
|
23 |
public $vatNumber;
|
|
|
24 |
/**
|
25 |
* @var string
|
26 |
*/
|
27 |
public $status;
|
|
|
28 |
/**
|
29 |
* Date the invoice was issued, e.g. 2018-01-01
|
30 |
*
|
31 |
* @var string
|
32 |
*/
|
33 |
public $issuedAt;
|
|
|
34 |
/**
|
35 |
* Date the invoice was paid, e.g. 2018-01-01
|
36 |
*
|
37 |
* @var string|null
|
38 |
*/
|
39 |
public $paidAt;
|
|
|
40 |
/**
|
41 |
* Date the invoice is due, e.g. 2018-01-01
|
42 |
*
|
43 |
* @var string|null
|
44 |
*/
|
45 |
public $dueAt;
|
|
|
46 |
/**
|
47 |
* Amount object containing the total amount of the invoice excluding VAT.
|
48 |
*
|
49 |
* @var object
|
50 |
*/
|
51 |
public $netAmount;
|
|
|
52 |
/**
|
53 |
* Amount object containing the VAT amount of the invoice. Only for merchants registered in the Netherlands.
|
54 |
*
|
55 |
* @var object
|
56 |
*/
|
57 |
public $vatAmount;
|
|
|
58 |
/**
|
59 |
* Total amount of the invoice including VAT.
|
60 |
*
|
61 |
* @var object
|
62 |
*/
|
63 |
public $grossAmount;
|
|
|
64 |
/**
|
65 |
* Object containing the invoice lines.
|
66 |
* See https://docs.mollie.com/reference/v2/invoices-api/get-invoice for reference
|
@@ -68,31 +80,35 @@ class Invoice extends \Mollie\Api\Resources\BaseResource
|
|
68 |
* @var object
|
69 |
*/
|
70 |
public $lines;
|
|
|
71 |
/**
|
72 |
* Contains a PDF to the Invoice
|
73 |
*
|
74 |
* @var object[]
|
75 |
*/
|
76 |
public $_links;
|
|
|
77 |
/**
|
78 |
* @return bool
|
79 |
*/
|
80 |
public function isPaid()
|
81 |
{
|
82 |
-
return $this->status ==
|
83 |
}
|
|
|
84 |
/**
|
85 |
* @return bool
|
86 |
*/
|
87 |
public function isOpen()
|
88 |
{
|
89 |
-
return $this->status ==
|
90 |
}
|
|
|
91 |
/**
|
92 |
* @return bool
|
93 |
*/
|
94 |
public function isOverdue()
|
95 |
{
|
96 |
-
return $this->status ==
|
97 |
}
|
98 |
-
}
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\Types\InvoiceStatus;
|
6 |
+
|
7 |
+
class Invoice extends BaseResource
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
public $resource;
|
13 |
+
|
14 |
/**
|
15 |
* @var string
|
16 |
*/
|
17 |
public $id;
|
18 |
+
|
19 |
/**
|
20 |
* @var string
|
21 |
*/
|
22 |
public $reference;
|
23 |
+
|
24 |
/**
|
25 |
* @var string
|
26 |
*/
|
27 |
public $vatNumber;
|
28 |
+
|
29 |
/**
|
30 |
* @var string
|
31 |
*/
|
32 |
public $status;
|
33 |
+
|
34 |
/**
|
35 |
* Date the invoice was issued, e.g. 2018-01-01
|
36 |
*
|
37 |
* @var string
|
38 |
*/
|
39 |
public $issuedAt;
|
40 |
+
|
41 |
/**
|
42 |
* Date the invoice was paid, e.g. 2018-01-01
|
43 |
*
|
44 |
* @var string|null
|
45 |
*/
|
46 |
public $paidAt;
|
47 |
+
|
48 |
/**
|
49 |
* Date the invoice is due, e.g. 2018-01-01
|
50 |
*
|
51 |
* @var string|null
|
52 |
*/
|
53 |
public $dueAt;
|
54 |
+
|
55 |
/**
|
56 |
* Amount object containing the total amount of the invoice excluding VAT.
|
57 |
*
|
58 |
* @var object
|
59 |
*/
|
60 |
public $netAmount;
|
61 |
+
|
62 |
/**
|
63 |
* Amount object containing the VAT amount of the invoice. Only for merchants registered in the Netherlands.
|
64 |
*
|
65 |
* @var object
|
66 |
*/
|
67 |
public $vatAmount;
|
68 |
+
|
69 |
/**
|
70 |
* Total amount of the invoice including VAT.
|
71 |
*
|
72 |
* @var object
|
73 |
*/
|
74 |
public $grossAmount;
|
75 |
+
|
76 |
/**
|
77 |
* Object containing the invoice lines.
|
78 |
* See https://docs.mollie.com/reference/v2/invoices-api/get-invoice for reference
|
80 |
* @var object
|
81 |
*/
|
82 |
public $lines;
|
83 |
+
|
84 |
/**
|
85 |
* Contains a PDF to the Invoice
|
86 |
*
|
87 |
* @var object[]
|
88 |
*/
|
89 |
public $_links;
|
90 |
+
|
91 |
/**
|
92 |
* @return bool
|
93 |
*/
|
94 |
public function isPaid()
|
95 |
{
|
96 |
+
return $this->status == InvoiceStatus::STATUS_PAID;
|
97 |
}
|
98 |
+
|
99 |
/**
|
100 |
* @return bool
|
101 |
*/
|
102 |
public function isOpen()
|
103 |
{
|
104 |
+
return $this->status == InvoiceStatus::STATUS_OPEN;
|
105 |
}
|
106 |
+
|
107 |
/**
|
108 |
* @return bool
|
109 |
*/
|
110 |
public function isOverdue()
|
111 |
{
|
112 |
+
return $this->status == InvoiceStatus::STATUS_OVERDUE;
|
113 |
}
|
114 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class InvoiceCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class InvoiceCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "invoices";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class InvoiceCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "invoices";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Invoice($this->client);
|
21 |
}
|
22 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class Issuer extends
|
6 |
{
|
7 |
/**
|
8 |
* Id of the issuer.
|
@@ -10,12 +10,14 @@ class Issuer extends \Mollie\Api\Resources\BaseResource
|
|
10 |
* @var string
|
11 |
*/
|
12 |
public $id;
|
|
|
13 |
/**
|
14 |
* Name of the issuer.
|
15 |
*
|
16 |
* @var string
|
17 |
*/
|
18 |
public $name;
|
|
|
19 |
/**
|
20 |
* The payment method this issuer belongs to.
|
21 |
*
|
@@ -23,10 +25,11 @@ class Issuer extends \Mollie\Api\Resources\BaseResource
|
|
23 |
* @var string
|
24 |
*/
|
25 |
public $method;
|
|
|
26 |
/**
|
27 |
* Object containing a size1x or size2x image
|
28 |
*
|
29 |
* @var object
|
30 |
*/
|
31 |
public $image;
|
32 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class Issuer extends BaseResource
|
6 |
{
|
7 |
/**
|
8 |
* Id of the issuer.
|
10 |
* @var string
|
11 |
*/
|
12 |
public $id;
|
13 |
+
|
14 |
/**
|
15 |
* Name of the issuer.
|
16 |
*
|
17 |
* @var string
|
18 |
*/
|
19 |
public $name;
|
20 |
+
|
21 |
/**
|
22 |
* The payment method this issuer belongs to.
|
23 |
*
|
25 |
* @var string
|
26 |
*/
|
27 |
public $method;
|
28 |
+
|
29 |
/**
|
30 |
* Object containing a size1x or size2x image
|
31 |
*
|
32 |
* @var object
|
33 |
*/
|
34 |
public $image;
|
35 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class IssuerCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string|null
|
@@ -11,4 +11,4 @@ class IssuerCollection extends \Mollie\Api\Resources\BaseCollection
|
|
11 |
{
|
12 |
return null;
|
13 |
}
|
14 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class IssuerCollection extends BaseCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string|null
|
11 |
{
|
12 |
return null;
|
13 |
}
|
14 |
+
}
|
@@ -4,75 +4,90 @@ namespace Mollie\Api\Resources;
|
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\MandateStatus;
|
7 |
-
|
|
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
public $resource;
|
|
|
13 |
/**
|
14 |
* @var string
|
15 |
*/
|
16 |
public $id;
|
|
|
17 |
/**
|
18 |
* @var string
|
19 |
*/
|
20 |
public $status;
|
|
|
21 |
/**
|
22 |
* @var string
|
23 |
*/
|
24 |
public $mode;
|
|
|
25 |
/**
|
26 |
* @var string
|
27 |
*/
|
28 |
public $method;
|
|
|
29 |
/**
|
30 |
* @var object|null
|
31 |
*/
|
32 |
public $details;
|
|
|
33 |
/**
|
34 |
* @var string
|
35 |
*/
|
36 |
public $customerId;
|
|
|
37 |
/**
|
38 |
* @var string
|
39 |
*/
|
40 |
public $createdAt;
|
|
|
41 |
/**
|
42 |
* @var string
|
43 |
*/
|
44 |
public $mandateReference;
|
|
|
45 |
/**
|
46 |
* Date of signature, for example: 2018-05-07
|
47 |
*
|
48 |
* @var string
|
49 |
*/
|
50 |
public $signatureDate;
|
|
|
51 |
/**
|
52 |
* @var object
|
53 |
*/
|
54 |
public $_links;
|
|
|
55 |
/**
|
56 |
* @return bool
|
57 |
*/
|
58 |
public function isValid()
|
59 |
{
|
60 |
-
return $this->status ===
|
61 |
}
|
|
|
62 |
/**
|
63 |
* @return bool
|
64 |
*/
|
65 |
public function isPending()
|
66 |
{
|
67 |
-
return $this->status ===
|
68 |
}
|
|
|
69 |
/**
|
70 |
* @return bool
|
71 |
*/
|
72 |
public function isInvalid()
|
73 |
{
|
74 |
-
return $this->status ===
|
75 |
}
|
|
|
76 |
/**
|
77 |
* Revoke the mandate
|
78 |
*
|
@@ -83,11 +98,21 @@ class Mandate extends \Mollie\Api\Resources\BaseResource
|
|
83 |
if (!isset($this->_links->self->href)) {
|
84 |
return $this;
|
85 |
}
|
|
|
86 |
$body = null;
|
87 |
-
if
|
88 |
-
$body =
|
|
|
|
|
89 |
}
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
return $result;
|
92 |
}
|
93 |
-
|
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\MandateStatus;
|
7 |
+
|
8 |
+
class Mandate extends BaseResource
|
9 |
{
|
10 |
/**
|
11 |
* @var string
|
12 |
*/
|
13 |
public $resource;
|
14 |
+
|
15 |
/**
|
16 |
* @var string
|
17 |
*/
|
18 |
public $id;
|
19 |
+
|
20 |
/**
|
21 |
* @var string
|
22 |
*/
|
23 |
public $status;
|
24 |
+
|
25 |
/**
|
26 |
* @var string
|
27 |
*/
|
28 |
public $mode;
|
29 |
+
|
30 |
/**
|
31 |
* @var string
|
32 |
*/
|
33 |
public $method;
|
34 |
+
|
35 |
/**
|
36 |
* @var object|null
|
37 |
*/
|
38 |
public $details;
|
39 |
+
|
40 |
/**
|
41 |
* @var string
|
42 |
*/
|
43 |
public $customerId;
|
44 |
+
|
45 |
/**
|
46 |
* @var string
|
47 |
*/
|
48 |
public $createdAt;
|
49 |
+
|
50 |
/**
|
51 |
* @var string
|
52 |
*/
|
53 |
public $mandateReference;
|
54 |
+
|
55 |
/**
|
56 |
* Date of signature, for example: 2018-05-07
|
57 |
*
|
58 |
* @var string
|
59 |
*/
|
60 |
public $signatureDate;
|
61 |
+
|
62 |
/**
|
63 |
* @var object
|
64 |
*/
|
65 |
public $_links;
|
66 |
+
|
67 |
/**
|
68 |
* @return bool
|
69 |
*/
|
70 |
public function isValid()
|
71 |
{
|
72 |
+
return $this->status === MandateStatus::STATUS_VALID;
|
73 |
}
|
74 |
+
|
75 |
/**
|
76 |
* @return bool
|
77 |
*/
|
78 |
public function isPending()
|
79 |
{
|
80 |
+
return $this->status === MandateStatus::STATUS_PENDING;
|
81 |
}
|
82 |
+
|
83 |
/**
|
84 |
* @return bool
|
85 |
*/
|
86 |
public function isInvalid()
|
87 |
{
|
88 |
+
return $this->status === MandateStatus::STATUS_INVALID;
|
89 |
}
|
90 |
+
|
91 |
/**
|
92 |
* Revoke the mandate
|
93 |
*
|
98 |
if (!isset($this->_links->self->href)) {
|
99 |
return $this;
|
100 |
}
|
101 |
+
|
102 |
$body = null;
|
103 |
+
if($this->client->usesOAuth()) {
|
104 |
+
$body = json_encode([
|
105 |
+
"testmode" => $this->mode === "test" ? true : false
|
106 |
+
]);
|
107 |
}
|
108 |
+
|
109 |
+
$result = $this->client->performHttpCallToFullUrl(
|
110 |
+
MollieApiClient::HTTP_DELETE,
|
111 |
+
$this->_links->self->href,
|
112 |
+
$body
|
113 |
+
);
|
114 |
+
|
115 |
return $result;
|
116 |
}
|
117 |
+
|
118 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class MandateCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class MandateCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "mandates";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class MandateCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "mandates";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Mandate($this->client);
|
21 |
}
|
22 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class Method extends
|
6 |
{
|
7 |
/**
|
8 |
* Id of the payment method.
|
@@ -10,18 +10,21 @@ class Method extends \Mollie\Api\Resources\BaseResource
|
|
10 |
* @var string
|
11 |
*/
|
12 |
public $id;
|
|
|
13 |
/**
|
14 |
* More legible description of the payment method.
|
15 |
*
|
16 |
* @var string
|
17 |
*/
|
18 |
public $description;
|
|
|
19 |
/**
|
20 |
* The $image->size1x and $image->size2x to display the payment method logo.
|
21 |
*
|
22 |
* @var object
|
23 |
*/
|
24 |
public $image;
|
|
|
25 |
/**
|
26 |
* The issuers available for this payment method. Only for the methods iDEAL, KBC/CBC and gift cards.
|
27 |
* Will only be filled when explicitly requested using the query string `include` parameter.
|
@@ -29,10 +32,12 @@ class Method extends \Mollie\Api\Resources\BaseResource
|
|
29 |
* @var array|object[]
|
30 |
*/
|
31 |
public $issuers;
|
|
|
32 |
/**
|
33 |
* @var object[]
|
34 |
*/
|
35 |
public $_links;
|
|
|
36 |
/**
|
37 |
* Get the issuer value objects
|
38 |
*
|
@@ -40,10 +45,11 @@ class Method extends \Mollie\Api\Resources\BaseResource
|
|
40 |
*/
|
41 |
public function issuers()
|
42 |
{
|
43 |
-
$issuers
|
44 |
foreach ($this->issuers as $issuer) {
|
45 |
-
$issuers->append(
|
46 |
}
|
|
|
47 |
return $issuers;
|
48 |
}
|
49 |
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class Method extends BaseResource
|
6 |
{
|
7 |
/**
|
8 |
* Id of the payment method.
|
10 |
* @var string
|
11 |
*/
|
12 |
public $id;
|
13 |
+
|
14 |
/**
|
15 |
* More legible description of the payment method.
|
16 |
*
|
17 |
* @var string
|
18 |
*/
|
19 |
public $description;
|
20 |
+
|
21 |
/**
|
22 |
* The $image->size1x and $image->size2x to display the payment method logo.
|
23 |
*
|
24 |
* @var object
|
25 |
*/
|
26 |
public $image;
|
27 |
+
|
28 |
/**
|
29 |
* The issuers available for this payment method. Only for the methods iDEAL, KBC/CBC and gift cards.
|
30 |
* Will only be filled when explicitly requested using the query string `include` parameter.
|
32 |
* @var array|object[]
|
33 |
*/
|
34 |
public $issuers;
|
35 |
+
|
36 |
/**
|
37 |
* @var object[]
|
38 |
*/
|
39 |
public $_links;
|
40 |
+
|
41 |
/**
|
42 |
* Get the issuer value objects
|
43 |
*
|
45 |
*/
|
46 |
public function issuers()
|
47 |
{
|
48 |
+
$issuers = new IssuerCollection(count($this->issuers), null);
|
49 |
foreach ($this->issuers as $issuer) {
|
50 |
+
$issuers->append(ResourceFactory::createFromApiResult($issuer, new Issuer($this->client)));
|
51 |
}
|
52 |
+
|
53 |
return $issuers;
|
54 |
}
|
55 |
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class MethodCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class MethodCollection extends BaseCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -4,12 +4,14 @@ namespace Mollie\Api\Resources;
|
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\OrderStatus;
|
7 |
-
|
|
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
public $resource;
|
|
|
13 |
/**
|
14 |
* Id of the order.
|
15 |
*
|
@@ -17,6 +19,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
17 |
* @var string
|
18 |
*/
|
19 |
public $id;
|
|
|
20 |
/**
|
21 |
* The profile ID this order belongs to.
|
22 |
*
|
@@ -24,60 +27,71 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
24 |
* @var string
|
25 |
*/
|
26 |
public $profileId;
|
|
|
27 |
/**
|
28 |
* Either "live" or "test". Indicates this being a test or a live (verified) order.
|
29 |
*
|
30 |
* @var string
|
31 |
*/
|
32 |
public $mode;
|
|
|
33 |
/**
|
34 |
* Amount object containing the value and currency
|
35 |
*
|
36 |
* @var object
|
37 |
*/
|
38 |
public $amount;
|
|
|
39 |
/**
|
40 |
* The total amount captured, thus far.
|
41 |
*
|
42 |
* @var object
|
43 |
*/
|
44 |
public $amountCaptured;
|
|
|
45 |
/**
|
46 |
* The total amount refunded, thus far.
|
47 |
*
|
48 |
* @var object
|
49 |
*/
|
50 |
public $amountRefunded;
|
|
|
51 |
/**
|
52 |
* The status of the order.
|
53 |
*
|
54 |
* @var string
|
55 |
*/
|
56 |
public $status;
|
|
|
57 |
/**
|
58 |
* The person and the address the order is billed to.
|
59 |
*
|
60 |
* @var object
|
61 |
*/
|
62 |
public $billingAddress;
|
|
|
63 |
/**
|
64 |
* The date of birth of your customer, if available.
|
65 |
* @example 1976-08-21
|
66 |
* @var string|null
|
67 |
*/
|
68 |
public $consumerDateOfBirth;
|
|
|
69 |
/**
|
70 |
* The order number that was used when creating the order.
|
71 |
*
|
72 |
* @var string
|
73 |
*/
|
74 |
public $orderNumber;
|
|
|
75 |
/**
|
76 |
* The person and the address the order is billed to.
|
77 |
*
|
78 |
* @var object
|
79 |
*/
|
80 |
public $shippingAddress;
|
|
|
|
|
81 |
/**
|
82 |
* The payment method last used when paying for the order.
|
83 |
*
|
@@ -85,12 +99,14 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
85 |
* @var string
|
86 |
*/
|
87 |
public $method;
|
|
|
88 |
/**
|
89 |
* The locale used for this order.
|
90 |
*
|
91 |
* @var string
|
92 |
*/
|
93 |
public $locale;
|
|
|
94 |
/**
|
95 |
* During creation of the order you can set custom metadata that is stored with
|
96 |
* the order, and given back whenever you retrieve that order.
|
@@ -98,24 +114,28 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
98 |
* @var object|mixed|null
|
99 |
*/
|
100 |
public $metadata;
|
|
|
101 |
/**
|
102 |
* Can this order be canceled?
|
103 |
*
|
104 |
* @var bool
|
105 |
*/
|
106 |
public $isCancelable;
|
|
|
107 |
/**
|
108 |
* Webhook URL set on this payment
|
109 |
*
|
110 |
* @var string|null
|
111 |
*/
|
112 |
public $webhookUrl;
|
|
|
113 |
/**
|
114 |
* Redirect URL set on this payment
|
115 |
*
|
116 |
* @var string
|
117 |
*/
|
118 |
public $redirectUrl;
|
|
|
119 |
/**
|
120 |
* UTC datetime the order was created in ISO-8601 format.
|
121 |
*
|
@@ -123,16 +143,19 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
123 |
* @var string|null
|
124 |
*/
|
125 |
public $createdAt;
|
|
|
126 |
/**
|
127 |
* The order lines contain the actual things the customer bought.
|
128 |
* @var array|object[]
|
129 |
*/
|
130 |
public $lines;
|
|
|
131 |
/**
|
132 |
* An object with several URL objects relevant to the customer. Every URL object will contain an href and a type field.
|
133 |
* @var object[]
|
134 |
*/
|
135 |
public $_links;
|
|
|
136 |
/**
|
137 |
* Is this order created?
|
138 |
*
|
@@ -140,8 +163,9 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
140 |
*/
|
141 |
public function isCreated()
|
142 |
{
|
143 |
-
return $this->status ===
|
144 |
}
|
|
|
145 |
/**
|
146 |
* Is this order paid for?
|
147 |
*
|
@@ -149,8 +173,9 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
149 |
*/
|
150 |
public function isPaid()
|
151 |
{
|
152 |
-
return $this->status ===
|
153 |
}
|
|
|
154 |
/**
|
155 |
* Is this order authorized?
|
156 |
*
|
@@ -158,8 +183,9 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
158 |
*/
|
159 |
public function isAuthorized()
|
160 |
{
|
161 |
-
return $this->status ===
|
162 |
}
|
|
|
163 |
/**
|
164 |
* Is this order canceled?
|
165 |
*
|
@@ -167,8 +193,9 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
167 |
*/
|
168 |
public function isCanceled()
|
169 |
{
|
170 |
-
return $this->status ===
|
171 |
}
|
|
|
172 |
/**
|
173 |
* Is this order refunded?
|
174 |
*
|
@@ -176,8 +203,9 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
176 |
*/
|
177 |
public function isRefunded()
|
178 |
{
|
179 |
-
return $this->status ===
|
180 |
}
|
|
|
181 |
/**
|
182 |
* Is this order shipping?
|
183 |
*
|
@@ -185,8 +213,9 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
185 |
*/
|
186 |
public function isShipping()
|
187 |
{
|
188 |
-
return $this->status ===
|
189 |
}
|
|
|
190 |
/**
|
191 |
* Is this order completed?
|
192 |
*
|
@@ -194,8 +223,9 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
194 |
*/
|
195 |
public function isCompleted()
|
196 |
{
|
197 |
-
return $this->status ===
|
198 |
}
|
|
|
199 |
/**
|
200 |
* Is this order expired?
|
201 |
*
|
@@ -203,8 +233,10 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
203 |
*/
|
204 |
public function isExpired()
|
205 |
{
|
206 |
-
return $this->status ===
|
207 |
}
|
|
|
|
|
208 |
/**
|
209 |
* Cancels this order.
|
210 |
* If the order was partially shipped, the status will be "completed" instead of
|
@@ -219,6 +251,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
219 |
{
|
220 |
return $this->client->orders->cancel($this->id);
|
221 |
}
|
|
|
222 |
/**
|
223 |
* Cancel a line for this order.
|
224 |
* The data array must contain a lines array.
|
@@ -232,6 +265,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
232 |
{
|
233 |
return $this->client->orderLines->cancelFor($this, $data);
|
234 |
}
|
|
|
235 |
/**
|
236 |
* Cancels all eligible lines for this order.
|
237 |
* Returns null if successful.
|
@@ -244,6 +278,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
244 |
$data['lines'] = [];
|
245 |
return $this->client->orderLines->cancelFor($this, $data);
|
246 |
}
|
|
|
247 |
/**
|
248 |
* Get the line value objects
|
249 |
*
|
@@ -251,12 +286,14 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
251 |
*/
|
252 |
public function lines()
|
253 |
{
|
254 |
-
$lines
|
255 |
foreach ($this->lines as $line) {
|
256 |
-
$lines->append(
|
257 |
}
|
|
|
258 |
return $lines;
|
259 |
}
|
|
|
260 |
/**
|
261 |
* Create a shipment for some order lines. You can provide an empty array for the
|
262 |
* "lines" option to include all unshipped lines for this order.
|
@@ -269,6 +306,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
269 |
{
|
270 |
return $this->client->shipments->createFor($this, $options);
|
271 |
}
|
|
|
272 |
/**
|
273 |
* Create a shipment for all unshipped order lines.
|
274 |
*
|
@@ -281,6 +319,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
281 |
$options['lines'] = [];
|
282 |
return $this->createShipment($options);
|
283 |
}
|
|
|
284 |
/**
|
285 |
* Retrieve a specific shipment for this order.
|
286 |
*
|
@@ -293,6 +332,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
293 |
{
|
294 |
return $this->client->shipments->getFor($this, $shipmentId, $parameters);
|
295 |
}
|
|
|
296 |
/**
|
297 |
* Get all shipments for this order.
|
298 |
*
|
@@ -304,6 +344,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
304 |
{
|
305 |
return $this->client->shipments->listFor($this, $parameters);
|
306 |
}
|
|
|
307 |
/**
|
308 |
* Get the checkout URL where the customer can complete the payment.
|
309 |
*
|
@@ -314,8 +355,10 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
314 |
if (empty($this->_links->checkout)) {
|
315 |
return null;
|
316 |
}
|
|
|
317 |
return $this->_links->checkout->href;
|
318 |
}
|
|
|
319 |
/**
|
320 |
* Refund specific order lines.
|
321 |
*
|
@@ -326,6 +369,7 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
326 |
{
|
327 |
return $this->client->orderRefunds->createFor($this, $data);
|
328 |
}
|
|
|
329 |
/**
|
330 |
* Refund all eligible order lines.
|
331 |
*
|
@@ -337,6 +381,8 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
337 |
$data['lines'] = [];
|
338 |
return $this->refund($data);
|
339 |
}
|
|
|
|
|
340 |
/**
|
341 |
* Retrieves all refunds associated with this order
|
342 |
*
|
@@ -346,13 +392,16 @@ class Order extends \Mollie\Api\Resources\BaseResource
|
|
346 |
public function refunds()
|
347 |
{
|
348 |
if (!isset($this->_links->refunds->href)) {
|
349 |
-
return new
|
350 |
}
|
351 |
-
|
352 |
-
$
|
|
|
|
|
353 |
foreach ($result->_embedded->refunds as $dataResult) {
|
354 |
-
$resourceCollection[] =
|
355 |
}
|
|
|
356 |
return $resourceCollection;
|
357 |
}
|
358 |
}
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\OrderStatus;
|
7 |
+
|
8 |
+
class Order extends BaseResource
|
9 |
{
|
10 |
/**
|
11 |
* @var string
|
12 |
*/
|
13 |
public $resource;
|
14 |
+
|
15 |
/**
|
16 |
* Id of the order.
|
17 |
*
|
19 |
* @var string
|
20 |
*/
|
21 |
public $id;
|
22 |
+
|
23 |
/**
|
24 |
* The profile ID this order belongs to.
|
25 |
*
|
27 |
* @var string
|
28 |
*/
|
29 |
public $profileId;
|
30 |
+
|
31 |
/**
|
32 |
* Either "live" or "test". Indicates this being a test or a live (verified) order.
|
33 |
*
|
34 |
* @var string
|
35 |
*/
|
36 |
public $mode;
|
37 |
+
|
38 |
/**
|
39 |
* Amount object containing the value and currency
|
40 |
*
|
41 |
* @var object
|
42 |
*/
|
43 |
public $amount;
|
44 |
+
|
45 |
/**
|
46 |
* The total amount captured, thus far.
|
47 |
*
|
48 |
* @var object
|
49 |
*/
|
50 |
public $amountCaptured;
|
51 |
+
|
52 |
/**
|
53 |
* The total amount refunded, thus far.
|
54 |
*
|
55 |
* @var object
|
56 |
*/
|
57 |
public $amountRefunded;
|
58 |
+
|
59 |
/**
|
60 |
* The status of the order.
|
61 |
*
|
62 |
* @var string
|
63 |
*/
|
64 |
public $status;
|
65 |
+
|
66 |
/**
|
67 |
* The person and the address the order is billed to.
|
68 |
*
|
69 |
* @var object
|
70 |
*/
|
71 |
public $billingAddress;
|
72 |
+
|
73 |
/**
|
74 |
* The date of birth of your customer, if available.
|
75 |
* @example 1976-08-21
|
76 |
* @var string|null
|
77 |
*/
|
78 |
public $consumerDateOfBirth;
|
79 |
+
|
80 |
/**
|
81 |
* The order number that was used when creating the order.
|
82 |
*
|
83 |
* @var string
|
84 |
*/
|
85 |
public $orderNumber;
|
86 |
+
|
87 |
/**
|
88 |
* The person and the address the order is billed to.
|
89 |
*
|
90 |
* @var object
|
91 |
*/
|
92 |
public $shippingAddress;
|
93 |
+
|
94 |
+
|
95 |
/**
|
96 |
* The payment method last used when paying for the order.
|
97 |
*
|
99 |
* @var string
|
100 |
*/
|
101 |
public $method;
|
102 |
+
|
103 |
/**
|
104 |
* The locale used for this order.
|
105 |
*
|
106 |
* @var string
|
107 |
*/
|
108 |
public $locale;
|
109 |
+
|
110 |
/**
|
111 |
* During creation of the order you can set custom metadata that is stored with
|
112 |
* the order, and given back whenever you retrieve that order.
|
114 |
* @var object|mixed|null
|
115 |
*/
|
116 |
public $metadata;
|
117 |
+
|
118 |
/**
|
119 |
* Can this order be canceled?
|
120 |
*
|
121 |
* @var bool
|
122 |
*/
|
123 |
public $isCancelable;
|
124 |
+
|
125 |
/**
|
126 |
* Webhook URL set on this payment
|
127 |
*
|
128 |
* @var string|null
|
129 |
*/
|
130 |
public $webhookUrl;
|
131 |
+
|
132 |
/**
|
133 |
* Redirect URL set on this payment
|
134 |
*
|
135 |
* @var string
|
136 |
*/
|
137 |
public $redirectUrl;
|
138 |
+
|
139 |
/**
|
140 |
* UTC datetime the order was created in ISO-8601 format.
|
141 |
*
|
143 |
* @var string|null
|
144 |
*/
|
145 |
public $createdAt;
|
146 |
+
|
147 |
/**
|
148 |
* The order lines contain the actual things the customer bought.
|
149 |
* @var array|object[]
|
150 |
*/
|
151 |
public $lines;
|
152 |
+
|
153 |
/**
|
154 |
* An object with several URL objects relevant to the customer. Every URL object will contain an href and a type field.
|
155 |
* @var object[]
|
156 |
*/
|
157 |
public $_links;
|
158 |
+
|
159 |
/**
|
160 |
* Is this order created?
|
161 |
*
|
163 |
*/
|
164 |
public function isCreated()
|
165 |
{
|
166 |
+
return $this->status === OrderStatus::STATUS_CREATED;
|
167 |
}
|
168 |
+
|
169 |
/**
|
170 |
* Is this order paid for?
|
171 |
*
|
173 |
*/
|
174 |
public function isPaid()
|
175 |
{
|
176 |
+
return $this->status === OrderStatus::STATUS_PAID;
|
177 |
}
|
178 |
+
|
179 |
/**
|
180 |
* Is this order authorized?
|
181 |
*
|
183 |
*/
|
184 |
public function isAuthorized()
|
185 |
{
|
186 |
+
return $this->status === OrderStatus::STATUS_AUTHORIZED;
|
187 |
}
|
188 |
+
|
189 |
/**
|
190 |
* Is this order canceled?
|
191 |
*
|
193 |
*/
|
194 |
public function isCanceled()
|
195 |
{
|
196 |
+
return $this->status === OrderStatus::STATUS_CANCELED;
|
197 |
}
|
198 |
+
|
199 |
/**
|
200 |
* Is this order refunded?
|
201 |
*
|
203 |
*/
|
204 |
public function isRefunded()
|
205 |
{
|
206 |
+
return $this->status === OrderStatus::STATUS_REFUNDED;
|
207 |
}
|
208 |
+
|
209 |
/**
|
210 |
* Is this order shipping?
|
211 |
*
|
213 |
*/
|
214 |
public function isShipping()
|
215 |
{
|
216 |
+
return $this->status === OrderStatus::STATUS_SHIPPING;
|
217 |
}
|
218 |
+
|
219 |
/**
|
220 |
* Is this order completed?
|
221 |
*
|
223 |
*/
|
224 |
public function isCompleted()
|
225 |
{
|
226 |
+
return $this->status === OrderStatus::STATUS_COMPLETED;
|
227 |
}
|
228 |
+
|
229 |
/**
|
230 |
* Is this order expired?
|
231 |
*
|
233 |
*/
|
234 |
public function isExpired()
|
235 |
{
|
236 |
+
return $this->status === OrderStatus::STATUS_EXPIRED;
|
237 |
}
|
238 |
+
|
239 |
+
|
240 |
/**
|
241 |
* Cancels this order.
|
242 |
* If the order was partially shipped, the status will be "completed" instead of
|
251 |
{
|
252 |
return $this->client->orders->cancel($this->id);
|
253 |
}
|
254 |
+
|
255 |
/**
|
256 |
* Cancel a line for this order.
|
257 |
* The data array must contain a lines array.
|
265 |
{
|
266 |
return $this->client->orderLines->cancelFor($this, $data);
|
267 |
}
|
268 |
+
|
269 |
/**
|
270 |
* Cancels all eligible lines for this order.
|
271 |
* Returns null if successful.
|
278 |
$data['lines'] = [];
|
279 |
return $this->client->orderLines->cancelFor($this, $data);
|
280 |
}
|
281 |
+
|
282 |
/**
|
283 |
* Get the line value objects
|
284 |
*
|
286 |
*/
|
287 |
public function lines()
|
288 |
{
|
289 |
+
$lines = new OrderLineCollection(count($this->lines), null);
|
290 |
foreach ($this->lines as $line) {
|
291 |
+
$lines->append(ResourceFactory::createFromApiResult($line, new OrderLine($this->client)));
|
292 |
}
|
293 |
+
|
294 |
return $lines;
|
295 |
}
|
296 |
+
|
297 |
/**
|
298 |
* Create a shipment for some order lines. You can provide an empty array for the
|
299 |
* "lines" option to include all unshipped lines for this order.
|
306 |
{
|
307 |
return $this->client->shipments->createFor($this, $options);
|
308 |
}
|
309 |
+
|
310 |
/**
|
311 |
* Create a shipment for all unshipped order lines.
|
312 |
*
|
319 |
$options['lines'] = [];
|
320 |
return $this->createShipment($options);
|
321 |
}
|
322 |
+
|
323 |
/**
|
324 |
* Retrieve a specific shipment for this order.
|
325 |
*
|
332 |
{
|
333 |
return $this->client->shipments->getFor($this, $shipmentId, $parameters);
|
334 |
}
|
335 |
+
|
336 |
/**
|
337 |
* Get all shipments for this order.
|
338 |
*
|
344 |
{
|
345 |
return $this->client->shipments->listFor($this, $parameters);
|
346 |
}
|
347 |
+
|
348 |
/**
|
349 |
* Get the checkout URL where the customer can complete the payment.
|
350 |
*
|
355 |
if (empty($this->_links->checkout)) {
|
356 |
return null;
|
357 |
}
|
358 |
+
|
359 |
return $this->_links->checkout->href;
|
360 |
}
|
361 |
+
|
362 |
/**
|
363 |
* Refund specific order lines.
|
364 |
*
|
369 |
{
|
370 |
return $this->client->orderRefunds->createFor($this, $data);
|
371 |
}
|
372 |
+
|
373 |
/**
|
374 |
* Refund all eligible order lines.
|
375 |
*
|
381 |
$data['lines'] = [];
|
382 |
return $this->refund($data);
|
383 |
}
|
384 |
+
|
385 |
+
|
386 |
/**
|
387 |
* Retrieves all refunds associated with this order
|
388 |
*
|
392 |
public function refunds()
|
393 |
{
|
394 |
if (!isset($this->_links->refunds->href)) {
|
395 |
+
return new RefundCollection($this->client, 0, null);
|
396 |
}
|
397 |
+
|
398 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->refunds->href);
|
399 |
+
|
400 |
+
$resourceCollection = new RefundCollection($this->client, $result->count, $result->_links);
|
401 |
foreach ($result->_embedded->refunds as $dataResult) {
|
402 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Refund($this->client));
|
403 |
}
|
404 |
+
|
405 |
return $resourceCollection;
|
406 |
}
|
407 |
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class OrderCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class OrderCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "orders";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class OrderCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "orders";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Order($this->client);
|
21 |
}
|
22 |
}
|
@@ -5,7 +5,8 @@ namespace Mollie\Api\Resources;
|
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\OrderLineStatus;
|
7 |
use Mollie\Api\Types\OrderLineType;
|
8 |
-
|
|
|
9 |
{
|
10 |
/**
|
11 |
* Always 'orderline'
|
@@ -13,12 +14,14 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
13 |
* @var string
|
14 |
*/
|
15 |
public $resource;
|
|
|
16 |
/**
|
17 |
* Id of the order line.
|
18 |
*
|
19 |
* @var string
|
20 |
*/
|
21 |
public $id;
|
|
|
22 |
/**
|
23 |
* The ID of the order this line belongs to.
|
24 |
*
|
@@ -26,6 +29,7 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
26 |
* @var string
|
27 |
*/
|
28 |
public $orderId;
|
|
|
29 |
/**
|
30 |
* The type of product bought.
|
31 |
*
|
@@ -33,6 +37,7 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
33 |
* @var string
|
34 |
*/
|
35 |
public $type;
|
|
|
36 |
/**
|
37 |
* A description of the order line.
|
38 |
*
|
@@ -40,42 +45,49 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
40 |
* @var string
|
41 |
*/
|
42 |
public $name;
|
|
|
43 |
/**
|
44 |
* The status of the order line.
|
45 |
*
|
46 |
* @var string
|
47 |
*/
|
48 |
public $status;
|
|
|
49 |
/**
|
50 |
* Can this order line be canceled?
|
51 |
*
|
52 |
* @var bool
|
53 |
*/
|
54 |
public $isCancelable;
|
|
|
55 |
/**
|
56 |
* The number of items in the order line.
|
57 |
*
|
58 |
* @var int
|
59 |
*/
|
60 |
public $quantity;
|
|
|
61 |
/**
|
62 |
* The price of a single item in the order line.
|
63 |
*
|
64 |
* @var object
|
65 |
*/
|
66 |
public $unitPrice;
|
|
|
67 |
/**
|
68 |
* Any discounts applied to the order line.
|
69 |
*
|
70 |
* @var object|null
|
71 |
*/
|
72 |
public $discountAmount;
|
|
|
73 |
/**
|
74 |
* The total amount of the line, including VAT and discounts.
|
75 |
*
|
76 |
* @var object
|
77 |
*/
|
78 |
public $totalAmount;
|
|
|
79 |
/**
|
80 |
* The VAT rate applied to the order line. It is defined as a string
|
81 |
* and not as a float to ensure the correct number of decimals are
|
@@ -85,30 +97,35 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
85 |
* @var string
|
86 |
*/
|
87 |
public $vatRate;
|
|
|
88 |
/**
|
89 |
* The amount of value-added tax on the line.
|
90 |
*
|
91 |
* @var object
|
92 |
*/
|
93 |
public $vatAmount;
|
|
|
94 |
/**
|
95 |
* The SKU, EAN, ISBN or UPC of the product sold.
|
96 |
*
|
97 |
* @var string|null
|
98 |
*/
|
99 |
public $sku;
|
|
|
100 |
/**
|
101 |
* A link pointing to an image of the product sold.
|
102 |
*
|
103 |
* @var string|null
|
104 |
*/
|
105 |
public $imageUrl;
|
|
|
106 |
/**
|
107 |
* A link pointing to the product page in your web shop of the product sold.
|
108 |
*
|
109 |
* @var string|null
|
110 |
*/
|
111 |
public $productUrl;
|
|
|
112 |
/**
|
113 |
* The order line's date and time of creation, in ISO 8601 format.
|
114 |
*
|
@@ -116,6 +133,7 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
116 |
* @var string
|
117 |
*/
|
118 |
public $createdAt;
|
|
|
119 |
/**
|
120 |
* Is this order line created?
|
121 |
*
|
@@ -123,8 +141,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
123 |
*/
|
124 |
public function isCreated()
|
125 |
{
|
126 |
-
return $this->status ===
|
127 |
}
|
|
|
128 |
/**
|
129 |
* Is this order line paid for?
|
130 |
*
|
@@ -132,8 +151,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
132 |
*/
|
133 |
public function isPaid()
|
134 |
{
|
135 |
-
return $this->status ===
|
136 |
}
|
|
|
137 |
/**
|
138 |
* Is this order line authorized?
|
139 |
*
|
@@ -141,8 +161,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
141 |
*/
|
142 |
public function isAuthorized()
|
143 |
{
|
144 |
-
return $this->status ===
|
145 |
}
|
|
|
146 |
/**
|
147 |
* Is this order line canceled?
|
148 |
*
|
@@ -150,8 +171,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
150 |
*/
|
151 |
public function isCanceled()
|
152 |
{
|
153 |
-
return $this->status ===
|
154 |
}
|
|
|
155 |
/**
|
156 |
* Is this order line refunded?
|
157 |
*
|
@@ -159,8 +181,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
159 |
*/
|
160 |
public function isRefunded()
|
161 |
{
|
162 |
-
return $this->status ===
|
163 |
}
|
|
|
164 |
/**
|
165 |
* Is this order line shipping?
|
166 |
*
|
@@ -168,8 +191,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
168 |
*/
|
169 |
public function isShipping()
|
170 |
{
|
171 |
-
return $this->status ===
|
172 |
}
|
|
|
173 |
/**
|
174 |
* Is this order line completed?
|
175 |
*
|
@@ -177,8 +201,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
177 |
*/
|
178 |
public function isCompleted()
|
179 |
{
|
180 |
-
return $this->status ===
|
181 |
}
|
|
|
182 |
/**
|
183 |
* Is this order line for a physical product?
|
184 |
*
|
@@ -186,8 +211,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
186 |
*/
|
187 |
public function isPhysical()
|
188 |
{
|
189 |
-
return $this->type ===
|
190 |
}
|
|
|
191 |
/**
|
192 |
* Is this order line for applying a discount?
|
193 |
*
|
@@ -195,8 +221,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
195 |
*/
|
196 |
public function isDiscount()
|
197 |
{
|
198 |
-
return $this->type ===
|
199 |
}
|
|
|
200 |
/**
|
201 |
* Is this order line for a digital product?
|
202 |
*
|
@@ -204,8 +231,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
204 |
*/
|
205 |
public function isDigital()
|
206 |
{
|
207 |
-
return $this->type ===
|
208 |
}
|
|
|
209 |
/**
|
210 |
* Is this order line for applying a shipping fee?
|
211 |
*
|
@@ -213,8 +241,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
213 |
*/
|
214 |
public function isShippingFee()
|
215 |
{
|
216 |
-
return $this->type ===
|
217 |
}
|
|
|
218 |
/**
|
219 |
* Is this order line for store credit?
|
220 |
*
|
@@ -222,8 +251,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
222 |
*/
|
223 |
public function isStoreCredit()
|
224 |
{
|
225 |
-
return $this->type ===
|
226 |
}
|
|
|
227 |
/**
|
228 |
* Is this order line for a gift card?
|
229 |
*
|
@@ -231,8 +261,9 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
231 |
*/
|
232 |
public function isGiftCard()
|
233 |
{
|
234 |
-
return $this->type ===
|
235 |
}
|
|
|
236 |
/**
|
237 |
* Is this order line for a surcharge?
|
238 |
*
|
@@ -240,6 +271,7 @@ class OrderLine extends \Mollie\Api\Resources\BaseResource
|
|
240 |
*/
|
241 |
public function isSurcharge()
|
242 |
{
|
243 |
-
return $this->type ===
|
244 |
}
|
|
|
245 |
}
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\OrderLineStatus;
|
7 |
use Mollie\Api\Types\OrderLineType;
|
8 |
+
|
9 |
+
class OrderLine extends BaseResource
|
10 |
{
|
11 |
/**
|
12 |
* Always 'orderline'
|
14 |
* @var string
|
15 |
*/
|
16 |
public $resource;
|
17 |
+
|
18 |
/**
|
19 |
* Id of the order line.
|
20 |
*
|
21 |
* @var string
|
22 |
*/
|
23 |
public $id;
|
24 |
+
|
25 |
/**
|
26 |
* The ID of the order this line belongs to.
|
27 |
*
|
29 |
* @var string
|
30 |
*/
|
31 |
public $orderId;
|
32 |
+
|
33 |
/**
|
34 |
* The type of product bought.
|
35 |
*
|
37 |
* @var string
|
38 |
*/
|
39 |
public $type;
|
40 |
+
|
41 |
/**
|
42 |
* A description of the order line.
|
43 |
*
|
45 |
* @var string
|
46 |
*/
|
47 |
public $name;
|
48 |
+
|
49 |
/**
|
50 |
* The status of the order line.
|
51 |
*
|
52 |
* @var string
|
53 |
*/
|
54 |
public $status;
|
55 |
+
|
56 |
/**
|
57 |
* Can this order line be canceled?
|
58 |
*
|
59 |
* @var bool
|
60 |
*/
|
61 |
public $isCancelable;
|
62 |
+
|
63 |
/**
|
64 |
* The number of items in the order line.
|
65 |
*
|
66 |
* @var int
|
67 |
*/
|
68 |
public $quantity;
|
69 |
+
|
70 |
/**
|
71 |
* The price of a single item in the order line.
|
72 |
*
|
73 |
* @var object
|
74 |
*/
|
75 |
public $unitPrice;
|
76 |
+
|
77 |
/**
|
78 |
* Any discounts applied to the order line.
|
79 |
*
|
80 |
* @var object|null
|
81 |
*/
|
82 |
public $discountAmount;
|
83 |
+
|
84 |
/**
|
85 |
* The total amount of the line, including VAT and discounts.
|
86 |
*
|
87 |
* @var object
|
88 |
*/
|
89 |
public $totalAmount;
|
90 |
+
|
91 |
/**
|
92 |
* The VAT rate applied to the order line. It is defined as a string
|
93 |
* and not as a float to ensure the correct number of decimals are
|
97 |
* @var string
|
98 |
*/
|
99 |
public $vatRate;
|
100 |
+
|
101 |
/**
|
102 |
* The amount of value-added tax on the line.
|
103 |
*
|
104 |
* @var object
|
105 |
*/
|
106 |
public $vatAmount;
|
107 |
+
|
108 |
/**
|
109 |
* The SKU, EAN, ISBN or UPC of the product sold.
|
110 |
*
|
111 |
* @var string|null
|
112 |
*/
|
113 |
public $sku;
|
114 |
+
|
115 |
/**
|
116 |
* A link pointing to an image of the product sold.
|
117 |
*
|
118 |
* @var string|null
|
119 |
*/
|
120 |
public $imageUrl;
|
121 |
+
|
122 |
/**
|
123 |
* A link pointing to the product page in your web shop of the product sold.
|
124 |
*
|
125 |
* @var string|null
|
126 |
*/
|
127 |
public $productUrl;
|
128 |
+
|
129 |
/**
|
130 |
* The order line's date and time of creation, in ISO 8601 format.
|
131 |
*
|
133 |
* @var string
|
134 |
*/
|
135 |
public $createdAt;
|
136 |
+
|
137 |
/**
|
138 |
* Is this order line created?
|
139 |
*
|
141 |
*/
|
142 |
public function isCreated()
|
143 |
{
|
144 |
+
return $this->status === OrderLineStatus::STATUS_CREATED;
|
145 |
}
|
146 |
+
|
147 |
/**
|
148 |
* Is this order line paid for?
|
149 |
*
|
151 |
*/
|
152 |
public function isPaid()
|
153 |
{
|
154 |
+
return $this->status === OrderLineStatus::STATUS_PAID;
|
155 |
}
|
156 |
+
|
157 |
/**
|
158 |
* Is this order line authorized?
|
159 |
*
|
161 |
*/
|
162 |
public function isAuthorized()
|
163 |
{
|
164 |
+
return $this->status === OrderLineStatus::STATUS_AUTHORIZED;
|
165 |
}
|
166 |
+
|
167 |
/**
|
168 |
* Is this order line canceled?
|
169 |
*
|
171 |
*/
|
172 |
public function isCanceled()
|
173 |
{
|
174 |
+
return $this->status === OrderLineStatus::STATUS_CANCELED;
|
175 |
}
|
176 |
+
|
177 |
/**
|
178 |
* Is this order line refunded?
|
179 |
*
|
181 |
*/
|
182 |
public function isRefunded()
|
183 |
{
|
184 |
+
return $this->status === OrderLineStatus::STATUS_REFUNDED;
|
185 |
}
|
186 |
+
|
187 |
/**
|
188 |
* Is this order line shipping?
|
189 |
*
|
191 |
*/
|
192 |
public function isShipping()
|
193 |
{
|
194 |
+
return $this->status === OrderLineStatus::STATUS_SHIPPING;
|
195 |
}
|
196 |
+
|
197 |
/**
|
198 |
* Is this order line completed?
|
199 |
*
|
201 |
*/
|
202 |
public function isCompleted()
|
203 |
{
|
204 |
+
return $this->status === OrderLineStatus::STATUS_COMPLETED;
|
205 |
}
|
206 |
+
|
207 |
/**
|
208 |
* Is this order line for a physical product?
|
209 |
*
|
211 |
*/
|
212 |
public function isPhysical()
|
213 |
{
|
214 |
+
return $this->type === OrderLineType::TYPE_PHYSICAL;
|
215 |
}
|
216 |
+
|
217 |
/**
|
218 |
* Is this order line for applying a discount?
|
219 |
*
|
221 |
*/
|
222 |
public function isDiscount()
|
223 |
{
|
224 |
+
return $this->type === OrderLineType::TYPE_DISCOUNT;
|
225 |
}
|
226 |
+
|
227 |
/**
|
228 |
* Is this order line for a digital product?
|
229 |
*
|
231 |
*/
|
232 |
public function isDigital()
|
233 |
{
|
234 |
+
return $this->type === OrderLineType::TYPE_DIGITAL;
|
235 |
}
|
236 |
+
|
237 |
/**
|
238 |
* Is this order line for applying a shipping fee?
|
239 |
*
|
241 |
*/
|
242 |
public function isShippingFee()
|
243 |
{
|
244 |
+
return $this->type === OrderLineType::TYPE_SHIPPING_FEE;
|
245 |
}
|
246 |
+
|
247 |
/**
|
248 |
* Is this order line for store credit?
|
249 |
*
|
251 |
*/
|
252 |
public function isStoreCredit()
|
253 |
{
|
254 |
+
return $this->type === OrderLineType::TYPE_STORE_CREDIT;
|
255 |
}
|
256 |
+
|
257 |
/**
|
258 |
* Is this order line for a gift card?
|
259 |
*
|
261 |
*/
|
262 |
public function isGiftCard()
|
263 |
{
|
264 |
+
return $this->type === OrderLineType::TYPE_GIFT_CARD;
|
265 |
}
|
266 |
+
|
267 |
/**
|
268 |
* Is this order line for a surcharge?
|
269 |
*
|
271 |
*/
|
272 |
public function isSurcharge()
|
273 |
{
|
274 |
+
return $this->type === OrderLineType::TYPE_SURCHARGE;
|
275 |
}
|
276 |
+
|
277 |
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class OrderLineCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string|null
|
@@ -11,6 +11,7 @@ class OrderLineCollection extends \Mollie\Api\Resources\BaseCollection
|
|
11 |
{
|
12 |
return null;
|
13 |
}
|
|
|
14 |
/**
|
15 |
* Get a specific order line.
|
16 |
* Returns null if the order line cannot be found.
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class OrderLineCollection extends BaseCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string|null
|
11 |
{
|
12 |
return null;
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* Get a specific order line.
|
17 |
* Returns null if the order line cannot be found.
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class Organization extends
|
6 |
{
|
7 |
/**
|
8 |
* Id of the payment method.
|
@@ -10,18 +10,21 @@ class Organization extends \Mollie\Api\Resources\BaseResource
|
|
10 |
* @var string
|
11 |
*/
|
12 |
public $id;
|
|
|
13 |
/**
|
14 |
* The name of the organization.
|
15 |
*
|
16 |
* @var string
|
17 |
*/
|
18 |
public $name;
|
|
|
19 |
/**
|
20 |
* The address of the organization.
|
21 |
*
|
22 |
* @var object
|
23 |
*/
|
24 |
public $address;
|
|
|
25 |
/**
|
26 |
* The registration number of the organization at the (local) chamber of
|
27 |
* commerce.
|
@@ -29,6 +32,7 @@ class Organization extends \Mollie\Api\Resources\BaseResource
|
|
29 |
* @var string
|
30 |
*/
|
31 |
public $registrationNumber;
|
|
|
32 |
/**
|
33 |
* The VAT number of the organization, if based in the European Union. The VAT
|
34 |
* number has been checked with the VIES by Mollie.
|
@@ -36,6 +40,7 @@ class Organization extends \Mollie\Api\Resources\BaseResource
|
|
36 |
* @var string
|
37 |
*/
|
38 |
public $vatNumber;
|
|
|
39 |
/**
|
40 |
* @var object[]
|
41 |
*/
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class Organization extends BaseResource
|
6 |
{
|
7 |
/**
|
8 |
* Id of the payment method.
|
10 |
* @var string
|
11 |
*/
|
12 |
public $id;
|
13 |
+
|
14 |
/**
|
15 |
* The name of the organization.
|
16 |
*
|
17 |
* @var string
|
18 |
*/
|
19 |
public $name;
|
20 |
+
|
21 |
/**
|
22 |
* The address of the organization.
|
23 |
*
|
24 |
* @var object
|
25 |
*/
|
26 |
public $address;
|
27 |
+
|
28 |
/**
|
29 |
* The registration number of the organization at the (local) chamber of
|
30 |
* commerce.
|
32 |
* @var string
|
33 |
*/
|
34 |
public $registrationNumber;
|
35 |
+
|
36 |
/**
|
37 |
* The VAT number of the organization, if based in the European Union. The VAT
|
38 |
* number has been checked with the VIES by Mollie.
|
40 |
* @var string
|
41 |
*/
|
42 |
public $vatNumber;
|
43 |
+
|
44 |
/**
|
45 |
* @var object[]
|
46 |
*/
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class OrganizationCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class OrganizationCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "organizations";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class OrganizationCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "organizations";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Organization($this->client);
|
21 |
}
|
22 |
}
|
@@ -6,18 +6,21 @@ use Mollie\Api\Exceptions\ApiException;
|
|
6 |
use Mollie\Api\MollieApiClient;
|
7 |
use Mollie\Api\Types\PaymentStatus;
|
8 |
use Mollie\Api\Types\SequenceType;
|
9 |
-
|
|
|
10 |
{
|
11 |
/**
|
12 |
* @var string
|
13 |
*/
|
14 |
public $resource;
|
|
|
15 |
/**
|
16 |
* Id of the payment (on the Mollie platform).
|
17 |
*
|
18 |
* @var string
|
19 |
*/
|
20 |
public $id;
|
|
|
21 |
/**
|
22 |
* Mode of the payment, either "live" or "test" depending on the API Key that was
|
23 |
* used.
|
@@ -25,18 +28,21 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
25 |
* @var string
|
26 |
*/
|
27 |
public $mode;
|
|
|
28 |
/**
|
29 |
* Amount object containing the value and currency
|
30 |
*
|
31 |
* @var object
|
32 |
*/
|
33 |
public $amount;
|
|
|
34 |
/**
|
35 |
* The amount that has been settled containing the value and currency
|
36 |
*
|
37 |
* @var object
|
38 |
*/
|
39 |
public $settlementAmount;
|
|
|
40 |
/**
|
41 |
* The amount of the payment that has been refunded to the consumer, in EURO with
|
42 |
* 2 decimals. This field will be null if the payment can not be refunded.
|
@@ -44,6 +50,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
44 |
* @var object|null
|
45 |
*/
|
46 |
public $amountRefunded;
|
|
|
47 |
/**
|
48 |
* The amount of a refunded payment that can still be refunded, in EURO with 2
|
49 |
* decimals. This field will be null if the payment can not be refunded.
|
@@ -55,6 +62,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
55 |
* @var object|null
|
56 |
*/
|
57 |
public $amountRemaining;
|
|
|
58 |
/**
|
59 |
* Description of the payment that is shown to the customer during the payment,
|
60 |
* and possibly on the bank or credit card statement.
|
@@ -62,6 +70,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
62 |
* @var string
|
63 |
*/
|
64 |
public $description;
|
|
|
65 |
/**
|
66 |
* If method is empty/null, the customer can pick his/her preferred payment
|
67 |
* method.
|
@@ -70,12 +79,14 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
70 |
* @var string|null
|
71 |
*/
|
72 |
public $method;
|
|
|
73 |
/**
|
74 |
* The status of the payment.
|
75 |
*
|
76 |
* @var string
|
77 |
*/
|
78 |
-
public $status =
|
|
|
79 |
/**
|
80 |
* UTC datetime the payment was created in ISO-8601 format.
|
81 |
*
|
@@ -83,6 +94,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
83 |
* @var string|null
|
84 |
*/
|
85 |
public $createdAt;
|
|
|
86 |
/**
|
87 |
* UTC datetime the payment was paid in ISO-8601 format.
|
88 |
*
|
@@ -90,6 +102,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
90 |
* @var string|null
|
91 |
*/
|
92 |
public $paidAt;
|
|
|
93 |
/**
|
94 |
* UTC datetime the payment was canceled in ISO-8601 format.
|
95 |
*
|
@@ -97,18 +110,21 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
97 |
* @var string|null
|
98 |
*/
|
99 |
public $canceledAt;
|
|
|
100 |
/**
|
101 |
* UTC datetime the payment expired in ISO-8601 format.
|
102 |
*
|
103 |
* @var string|null
|
104 |
*/
|
105 |
public $expiresAt;
|
|
|
106 |
/**
|
107 |
* UTC datetime the payment failed in ISO-8601 format.
|
108 |
*
|
109 |
* @var string|null
|
110 |
*/
|
111 |
public $failedAt;
|
|
|
112 |
/**
|
113 |
* The profile ID this payment belongs to.
|
114 |
*
|
@@ -116,24 +132,28 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
116 |
* @var string
|
117 |
*/
|
118 |
public $profileId;
|
|
|
119 |
/**
|
120 |
* Either "first", "recurring", or "oneoff" for regular payments.
|
121 |
*
|
122 |
* @var string|null
|
123 |
*/
|
124 |
public $sequenceType;
|
|
|
125 |
/**
|
126 |
* Redirect URL set on this payment
|
127 |
*
|
128 |
* @var string
|
129 |
*/
|
130 |
public $redirectUrl;
|
|
|
131 |
/**
|
132 |
* Webhook URL set on this payment
|
133 |
*
|
134 |
* @var string|null
|
135 |
*/
|
136 |
public $webhookUrl;
|
|
|
137 |
/**
|
138 |
* The mandate ID this payment is performed with.
|
139 |
*
|
@@ -141,6 +161,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
141 |
* @var string|null
|
142 |
*/
|
143 |
public $mandateId;
|
|
|
144 |
/**
|
145 |
* The subscription ID this payment belongs to.
|
146 |
*
|
@@ -148,6 +169,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
148 |
* @var string|null
|
149 |
*/
|
150 |
public $subscriptionId;
|
|
|
151 |
/**
|
152 |
* The order ID this payment belongs to.
|
153 |
*
|
@@ -155,6 +177,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
155 |
* @var string|null
|
156 |
*/
|
157 |
public $orderId;
|
|
|
158 |
/**
|
159 |
* The settlement ID this payment belongs to.
|
160 |
*
|
@@ -162,12 +185,14 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
162 |
* @var string|null
|
163 |
*/
|
164 |
public $settlementId;
|
|
|
165 |
/**
|
166 |
* The locale used for this payment.
|
167 |
*
|
168 |
* @var string|null
|
169 |
*/
|
170 |
public $locale;
|
|
|
171 |
/**
|
172 |
* During creation of the payment you can set custom metadata that is stored with
|
173 |
* the payment, and given back whenever you retrieve that payment.
|
@@ -175,6 +200,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
175 |
* @var object|mixed|null
|
176 |
*/
|
177 |
public $metadata;
|
|
|
178 |
/**
|
179 |
* Details of a successfully paid payment are set here. For example, the iDEAL
|
180 |
* payment method will set $details->consumerName and $details->consumerAccount.
|
@@ -182,16 +208,19 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
182 |
* @var object
|
183 |
*/
|
184 |
public $details;
|
|
|
185 |
/**
|
186 |
* @var object[]
|
187 |
*/
|
188 |
public $_links;
|
|
|
189 |
/**
|
190 |
* Whether or not this payment can be canceled.
|
191 |
*
|
192 |
* @var bool|null
|
193 |
*/
|
194 |
public $isCancelable;
|
|
|
195 |
/**
|
196 |
* Is this payment canceled?
|
197 |
*
|
@@ -199,8 +228,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
199 |
*/
|
200 |
public function isCanceled()
|
201 |
{
|
202 |
-
return $this->status ===
|
203 |
}
|
|
|
204 |
/**
|
205 |
* Is this payment expired?
|
206 |
*
|
@@ -208,8 +238,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
208 |
*/
|
209 |
public function isExpired()
|
210 |
{
|
211 |
-
return $this->status ===
|
212 |
}
|
|
|
213 |
/**
|
214 |
* Is this payment still open / ongoing?
|
215 |
*
|
@@ -217,8 +248,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
217 |
*/
|
218 |
public function isOpen()
|
219 |
{
|
220 |
-
return $this->status ===
|
221 |
}
|
|
|
222 |
/**
|
223 |
* Is this payment pending?
|
224 |
*
|
@@ -226,8 +258,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
226 |
*/
|
227 |
public function isPending()
|
228 |
{
|
229 |
-
return $this->status ===
|
230 |
}
|
|
|
231 |
/**
|
232 |
* Is this payment authorized?
|
233 |
*
|
@@ -235,8 +268,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
235 |
*/
|
236 |
public function isAuthorized()
|
237 |
{
|
238 |
-
return $this->status ===
|
239 |
}
|
|
|
240 |
/**
|
241 |
* Is this payment paid for?
|
242 |
*
|
@@ -246,6 +280,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
246 |
{
|
247 |
return !empty($this->paidAt);
|
248 |
}
|
|
|
249 |
/**
|
250 |
* Does the payment have refunds
|
251 |
*
|
@@ -255,6 +290,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
255 |
{
|
256 |
return !empty($this->_links->refunds);
|
257 |
}
|
|
|
258 |
/**
|
259 |
* Does this payment has chargebacks
|
260 |
*
|
@@ -264,6 +300,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
264 |
{
|
265 |
return !empty($this->_links->chargebacks);
|
266 |
}
|
|
|
267 |
/**
|
268 |
* Is this payment failing?
|
269 |
*
|
@@ -271,8 +308,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
271 |
*/
|
272 |
public function isFailed()
|
273 |
{
|
274 |
-
return $this->status ===
|
275 |
}
|
|
|
276 |
/**
|
277 |
* Check whether 'sequenceType' is set to 'first'. If a 'first' payment has been
|
278 |
* completed successfully, the consumer's account may be charged automatically
|
@@ -282,8 +320,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
282 |
*/
|
283 |
public function hasSequenceTypeFirst()
|
284 |
{
|
285 |
-
return $this->sequenceType ===
|
286 |
}
|
|
|
287 |
/**
|
288 |
* Check whether 'sequenceType' is set to 'recurring'. This type of payment is
|
289 |
* processed without involving
|
@@ -293,8 +332,9 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
293 |
*/
|
294 |
public function hasSequenceTypeRecurring()
|
295 |
{
|
296 |
-
return $this->sequenceType ===
|
297 |
}
|
|
|
298 |
/**
|
299 |
* Get the checkout URL where the customer can complete the payment.
|
300 |
*
|
@@ -305,8 +345,10 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
305 |
if (empty($this->_links->checkout)) {
|
306 |
return null;
|
307 |
}
|
|
|
308 |
return $this->_links->checkout->href;
|
309 |
}
|
|
|
310 |
/**
|
311 |
* @return bool
|
312 |
*/
|
@@ -314,6 +356,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
314 |
{
|
315 |
return $this->amountRemaining !== null;
|
316 |
}
|
|
|
317 |
/**
|
318 |
* @return bool
|
319 |
*/
|
@@ -321,6 +364,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
321 |
{
|
322 |
return $this->canBeRefunded();
|
323 |
}
|
|
|
324 |
/**
|
325 |
* Get the amount that is already refunded
|
326 |
*
|
@@ -329,10 +373,12 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
329 |
public function getAmountRefunded()
|
330 |
{
|
331 |
if ($this->amountRefunded) {
|
332 |
-
return (
|
333 |
}
|
|
|
334 |
return 0.0;
|
335 |
}
|
|
|
336 |
/**
|
337 |
* Get the remaining amount that can be refunded. For some payment methods this
|
338 |
* amount can be higher than the payment amount. This is possible to reimburse
|
@@ -343,10 +389,12 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
343 |
public function getAmountRemaining()
|
344 |
{
|
345 |
if ($this->amountRemaining) {
|
346 |
-
return (
|
347 |
}
|
|
|
348 |
return 0.0;
|
349 |
}
|
|
|
350 |
/**
|
351 |
* Retrieves all refunds associated with this payment
|
352 |
*
|
@@ -356,15 +404,30 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
356 |
public function refunds()
|
357 |
{
|
358 |
if (!isset($this->_links->refunds->href)) {
|
359 |
-
return new
|
360 |
}
|
361 |
-
|
362 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
363 |
foreach ($result->_embedded->refunds as $dataResult) {
|
364 |
-
$resourceCollection[] =
|
|
|
|
|
|
|
365 |
}
|
|
|
366 |
return $resourceCollection;
|
367 |
}
|
|
|
368 |
/**
|
369 |
* @param string $refundId
|
370 |
* @param array $parameters
|
@@ -375,6 +438,7 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
375 |
{
|
376 |
return $this->client->paymentRefunds->getFor($this, $refundId, $parameters);
|
377 |
}
|
|
|
378 |
/**
|
379 |
* Retrieves all captures associated with this payment
|
380 |
*
|
@@ -384,15 +448,30 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
384 |
public function captures()
|
385 |
{
|
386 |
if (!isset($this->_links->captures->href)) {
|
387 |
-
return new
|
388 |
}
|
389 |
-
|
390 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
foreach ($result->_embedded->captures as $dataResult) {
|
392 |
-
$resourceCollection[] =
|
|
|
|
|
|
|
393 |
}
|
|
|
394 |
return $resourceCollection;
|
395 |
}
|
|
|
396 |
/**
|
397 |
* @param string $captureId
|
398 |
* @param array $parameters
|
@@ -401,8 +480,13 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
401 |
*/
|
402 |
public function getCapture($captureId, array $parameters = [])
|
403 |
{
|
404 |
-
return $this->client->paymentCaptures->getFor(
|
|
|
|
|
|
|
|
|
405 |
}
|
|
|
406 |
/**
|
407 |
* Retrieves all chargebacks associated with this payment
|
408 |
*
|
@@ -412,15 +496,30 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
412 |
public function chargebacks()
|
413 |
{
|
414 |
if (!isset($this->_links->chargebacks->href)) {
|
415 |
-
return new
|
416 |
}
|
417 |
-
|
418 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
419 |
foreach ($result->_embedded->chargebacks as $dataResult) {
|
420 |
-
$resourceCollection[] =
|
|
|
|
|
|
|
421 |
}
|
|
|
422 |
return $resourceCollection;
|
423 |
}
|
|
|
424 |
/**
|
425 |
* Retrieves a specific chargeback for this payment.
|
426 |
*
|
@@ -431,8 +530,13 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
431 |
*/
|
432 |
public function getChargeback($chargebackId, array $parameters = [])
|
433 |
{
|
434 |
-
return $this->client->paymentChargebacks->getFor(
|
|
|
|
|
|
|
|
|
435 |
}
|
|
|
436 |
/**
|
437 |
* Issue a refund for this payment.
|
438 |
*
|
@@ -446,12 +550,22 @@ class Payment extends \Mollie\Api\Resources\BaseResource
|
|
446 |
*/
|
447 |
public function refund($data = [])
|
448 |
{
|
449 |
-
$resource = "payments/" .
|
|
|
450 |
$body = null;
|
451 |
-
if (
|
452 |
-
$body =
|
453 |
}
|
454 |
-
|
455 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
456 |
}
|
457 |
}
|
6 |
use Mollie\Api\MollieApiClient;
|
7 |
use Mollie\Api\Types\PaymentStatus;
|
8 |
use Mollie\Api\Types\SequenceType;
|
9 |
+
|
10 |
+
class Payment extends BaseResource
|
11 |
{
|
12 |
/**
|
13 |
* @var string
|
14 |
*/
|
15 |
public $resource;
|
16 |
+
|
17 |
/**
|
18 |
* Id of the payment (on the Mollie platform).
|
19 |
*
|
20 |
* @var string
|
21 |
*/
|
22 |
public $id;
|
23 |
+
|
24 |
/**
|
25 |
* Mode of the payment, either "live" or "test" depending on the API Key that was
|
26 |
* used.
|
28 |
* @var string
|
29 |
*/
|
30 |
public $mode;
|
31 |
+
|
32 |
/**
|
33 |
* Amount object containing the value and currency
|
34 |
*
|
35 |
* @var object
|
36 |
*/
|
37 |
public $amount;
|
38 |
+
|
39 |
/**
|
40 |
* The amount that has been settled containing the value and currency
|
41 |
*
|
42 |
* @var object
|
43 |
*/
|
44 |
public $settlementAmount;
|
45 |
+
|
46 |
/**
|
47 |
* The amount of the payment that has been refunded to the consumer, in EURO with
|
48 |
* 2 decimals. This field will be null if the payment can not be refunded.
|
50 |
* @var object|null
|
51 |
*/
|
52 |
public $amountRefunded;
|
53 |
+
|
54 |
/**
|
55 |
* The amount of a refunded payment that can still be refunded, in EURO with 2
|
56 |
* decimals. This field will be null if the payment can not be refunded.
|
62 |
* @var object|null
|
63 |
*/
|
64 |
public $amountRemaining;
|
65 |
+
|
66 |
/**
|
67 |
* Description of the payment that is shown to the customer during the payment,
|
68 |
* and possibly on the bank or credit card statement.
|
70 |
* @var string
|
71 |
*/
|
72 |
public $description;
|
73 |
+
|
74 |
/**
|
75 |
* If method is empty/null, the customer can pick his/her preferred payment
|
76 |
* method.
|
79 |
* @var string|null
|
80 |
*/
|
81 |
public $method;
|
82 |
+
|
83 |
/**
|
84 |
* The status of the payment.
|
85 |
*
|
86 |
* @var string
|
87 |
*/
|
88 |
+
public $status = PaymentStatus::STATUS_OPEN;
|
89 |
+
|
90 |
/**
|
91 |
* UTC datetime the payment was created in ISO-8601 format.
|
92 |
*
|
94 |
* @var string|null
|
95 |
*/
|
96 |
public $createdAt;
|
97 |
+
|
98 |
/**
|
99 |
* UTC datetime the payment was paid in ISO-8601 format.
|
100 |
*
|
102 |
* @var string|null
|
103 |
*/
|
104 |
public $paidAt;
|
105 |
+
|
106 |
/**
|
107 |
* UTC datetime the payment was canceled in ISO-8601 format.
|
108 |
*
|
110 |
* @var string|null
|
111 |
*/
|
112 |
public $canceledAt;
|
113 |
+
|
114 |
/**
|
115 |
* UTC datetime the payment expired in ISO-8601 format.
|
116 |
*
|
117 |
* @var string|null
|
118 |
*/
|
119 |
public $expiresAt;
|
120 |
+
|
121 |
/**
|
122 |
* UTC datetime the payment failed in ISO-8601 format.
|
123 |
*
|
124 |
* @var string|null
|
125 |
*/
|
126 |
public $failedAt;
|
127 |
+
|
128 |
/**
|
129 |
* The profile ID this payment belongs to.
|
130 |
*
|
132 |
* @var string
|
133 |
*/
|
134 |
public $profileId;
|
135 |
+
|
136 |
/**
|
137 |
* Either "first", "recurring", or "oneoff" for regular payments.
|
138 |
*
|
139 |
* @var string|null
|
140 |
*/
|
141 |
public $sequenceType;
|
142 |
+
|
143 |
/**
|
144 |
* Redirect URL set on this payment
|
145 |
*
|
146 |
* @var string
|
147 |
*/
|
148 |
public $redirectUrl;
|
149 |
+
|
150 |
/**
|
151 |
* Webhook URL set on this payment
|
152 |
*
|
153 |
* @var string|null
|
154 |
*/
|
155 |
public $webhookUrl;
|
156 |
+
|
157 |
/**
|
158 |
* The mandate ID this payment is performed with.
|
159 |
*
|
161 |
* @var string|null
|
162 |
*/
|
163 |
public $mandateId;
|
164 |
+
|
165 |
/**
|
166 |
* The subscription ID this payment belongs to.
|
167 |
*
|
169 |
* @var string|null
|
170 |
*/
|
171 |
public $subscriptionId;
|
172 |
+
|
173 |
/**
|
174 |
* The order ID this payment belongs to.
|
175 |
*
|
177 |
* @var string|null
|
178 |
*/
|
179 |
public $orderId;
|
180 |
+
|
181 |
/**
|
182 |
* The settlement ID this payment belongs to.
|
183 |
*
|
185 |
* @var string|null
|
186 |
*/
|
187 |
public $settlementId;
|
188 |
+
|
189 |
/**
|
190 |
* The locale used for this payment.
|
191 |
*
|
192 |
* @var string|null
|
193 |
*/
|
194 |
public $locale;
|
195 |
+
|
196 |
/**
|
197 |
* During creation of the payment you can set custom metadata that is stored with
|
198 |
* the payment, and given back whenever you retrieve that payment.
|
200 |
* @var object|mixed|null
|
201 |
*/
|
202 |
public $metadata;
|
203 |
+
|
204 |
/**
|
205 |
* Details of a successfully paid payment are set here. For example, the iDEAL
|
206 |
* payment method will set $details->consumerName and $details->consumerAccount.
|
208 |
* @var object
|
209 |
*/
|
210 |
public $details;
|
211 |
+
|
212 |
/**
|
213 |
* @var object[]
|
214 |
*/
|
215 |
public $_links;
|
216 |
+
|
217 |
/**
|
218 |
* Whether or not this payment can be canceled.
|
219 |
*
|
220 |
* @var bool|null
|
221 |
*/
|
222 |
public $isCancelable;
|
223 |
+
|
224 |
/**
|
225 |
* Is this payment canceled?
|
226 |
*
|
228 |
*/
|
229 |
public function isCanceled()
|
230 |
{
|
231 |
+
return $this->status === PaymentStatus::STATUS_CANCELED;
|
232 |
}
|
233 |
+
|
234 |
/**
|
235 |
* Is this payment expired?
|
236 |
*
|
238 |
*/
|
239 |
public function isExpired()
|
240 |
{
|
241 |
+
return $this->status === PaymentStatus::STATUS_EXPIRED;
|
242 |
}
|
243 |
+
|
244 |
/**
|
245 |
* Is this payment still open / ongoing?
|
246 |
*
|
248 |
*/
|
249 |
public function isOpen()
|
250 |
{
|
251 |
+
return $this->status === PaymentStatus::STATUS_OPEN;
|
252 |
}
|
253 |
+
|
254 |
/**
|
255 |
* Is this payment pending?
|
256 |
*
|
258 |
*/
|
259 |
public function isPending()
|
260 |
{
|
261 |
+
return $this->status === PaymentStatus::STATUS_PENDING;
|
262 |
}
|
263 |
+
|
264 |
/**
|
265 |
* Is this payment authorized?
|
266 |
*
|
268 |
*/
|
269 |
public function isAuthorized()
|
270 |
{
|
271 |
+
return $this->status === PaymentStatus::STATUS_AUTHORIZED;
|
272 |
}
|
273 |
+
|
274 |
/**
|
275 |
* Is this payment paid for?
|
276 |
*
|
280 |
{
|
281 |
return !empty($this->paidAt);
|
282 |
}
|
283 |
+
|
284 |
/**
|
285 |
* Does the payment have refunds
|
286 |
*
|
290 |
{
|
291 |
return !empty($this->_links->refunds);
|
292 |
}
|
293 |
+
|
294 |
/**
|
295 |
* Does this payment has chargebacks
|
296 |
*
|
300 |
{
|
301 |
return !empty($this->_links->chargebacks);
|
302 |
}
|
303 |
+
|
304 |
/**
|
305 |
* Is this payment failing?
|
306 |
*
|
308 |
*/
|
309 |
public function isFailed()
|
310 |
{
|
311 |
+
return $this->status === PaymentStatus::STATUS_FAILED;
|
312 |
}
|
313 |
+
|
314 |
/**
|
315 |
* Check whether 'sequenceType' is set to 'first'. If a 'first' payment has been
|
316 |
* completed successfully, the consumer's account may be charged automatically
|
320 |
*/
|
321 |
public function hasSequenceTypeFirst()
|
322 |
{
|
323 |
+
return $this->sequenceType === SequenceType::SEQUENCETYPE_FIRST;
|
324 |
}
|
325 |
+
|
326 |
/**
|
327 |
* Check whether 'sequenceType' is set to 'recurring'. This type of payment is
|
328 |
* processed without involving
|
332 |
*/
|
333 |
public function hasSequenceTypeRecurring()
|
334 |
{
|
335 |
+
return $this->sequenceType === SequenceType::SEQUENCETYPE_RECURRING;
|
336 |
}
|
337 |
+
|
338 |
/**
|
339 |
* Get the checkout URL where the customer can complete the payment.
|
340 |
*
|
345 |
if (empty($this->_links->checkout)) {
|
346 |
return null;
|
347 |
}
|
348 |
+
|
349 |
return $this->_links->checkout->href;
|
350 |
}
|
351 |
+
|
352 |
/**
|
353 |
* @return bool
|
354 |
*/
|
356 |
{
|
357 |
return $this->amountRemaining !== null;
|
358 |
}
|
359 |
+
|
360 |
/**
|
361 |
* @return bool
|
362 |
*/
|
364 |
{
|
365 |
return $this->canBeRefunded();
|
366 |
}
|
367 |
+
|
368 |
/**
|
369 |
* Get the amount that is already refunded
|
370 |
*
|
373 |
public function getAmountRefunded()
|
374 |
{
|
375 |
if ($this->amountRefunded) {
|
376 |
+
return (float)$this->amountRefunded->value;
|
377 |
}
|
378 |
+
|
379 |
return 0.0;
|
380 |
}
|
381 |
+
|
382 |
/**
|
383 |
* Get the remaining amount that can be refunded. For some payment methods this
|
384 |
* amount can be higher than the payment amount. This is possible to reimburse
|
389 |
public function getAmountRemaining()
|
390 |
{
|
391 |
if ($this->amountRemaining) {
|
392 |
+
return (float)$this->amountRemaining->value;
|
393 |
}
|
394 |
+
|
395 |
return 0.0;
|
396 |
}
|
397 |
+
|
398 |
/**
|
399 |
* Retrieves all refunds associated with this payment
|
400 |
*
|
404 |
public function refunds()
|
405 |
{
|
406 |
if (!isset($this->_links->refunds->href)) {
|
407 |
+
return new RefundCollection($this->client, 0, null);
|
408 |
}
|
409 |
+
|
410 |
+
$result = $this->client->performHttpCallToFullUrl(
|
411 |
+
MollieApiClient::HTTP_GET,
|
412 |
+
$this->_links->refunds->href
|
413 |
+
);
|
414 |
+
|
415 |
+
$resourceCollection = new RefundCollection(
|
416 |
+
$this->client,
|
417 |
+
$result->count,
|
418 |
+
$result->_links
|
419 |
+
);
|
420 |
+
|
421 |
foreach ($result->_embedded->refunds as $dataResult) {
|
422 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult(
|
423 |
+
$dataResult,
|
424 |
+
new Refund($this->client)
|
425 |
+
);
|
426 |
}
|
427 |
+
|
428 |
return $resourceCollection;
|
429 |
}
|
430 |
+
|
431 |
/**
|
432 |
* @param string $refundId
|
433 |
* @param array $parameters
|
438 |
{
|
439 |
return $this->client->paymentRefunds->getFor($this, $refundId, $parameters);
|
440 |
}
|
441 |
+
|
442 |
/**
|
443 |
* Retrieves all captures associated with this payment
|
444 |
*
|
448 |
public function captures()
|
449 |
{
|
450 |
if (!isset($this->_links->captures->href)) {
|
451 |
+
return new CaptureCollection($this->client, 0, null);
|
452 |
}
|
453 |
+
|
454 |
+
$result = $this->client->performHttpCallToFullUrl(
|
455 |
+
MollieApiClient::HTTP_GET,
|
456 |
+
$this->_links->captures->href
|
457 |
+
);
|
458 |
+
|
459 |
+
$resourceCollection = new CaptureCollection(
|
460 |
+
$this->client,
|
461 |
+
$result->count,
|
462 |
+
$result->_links
|
463 |
+
);
|
464 |
+
|
465 |
foreach ($result->_embedded->captures as $dataResult) {
|
466 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult(
|
467 |
+
$dataResult,
|
468 |
+
new Capture($this->client)
|
469 |
+
);
|
470 |
}
|
471 |
+
|
472 |
return $resourceCollection;
|
473 |
}
|
474 |
+
|
475 |
/**
|
476 |
* @param string $captureId
|
477 |
* @param array $parameters
|
480 |
*/
|
481 |
public function getCapture($captureId, array $parameters = [])
|
482 |
{
|
483 |
+
return $this->client->paymentCaptures->getFor(
|
484 |
+
$this,
|
485 |
+
$captureId,
|
486 |
+
$parameters
|
487 |
+
);
|
488 |
}
|
489 |
+
|
490 |
/**
|
491 |
* Retrieves all chargebacks associated with this payment
|
492 |
*
|
496 |
public function chargebacks()
|
497 |
{
|
498 |
if (!isset($this->_links->chargebacks->href)) {
|
499 |
+
return new ChargebackCollection($this->client, 0, null);
|
500 |
}
|
501 |
+
|
502 |
+
$result = $this->client->performHttpCallToFullUrl(
|
503 |
+
MollieApiClient::HTTP_GET,
|
504 |
+
$this->_links->chargebacks->href
|
505 |
+
);
|
506 |
+
|
507 |
+
$resourceCollection = new ChargebackCollection(
|
508 |
+
$this->client,
|
509 |
+
$result->count,
|
510 |
+
$result->_links
|
511 |
+
);
|
512 |
+
|
513 |
foreach ($result->_embedded->chargebacks as $dataResult) {
|
514 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult(
|
515 |
+
$dataResult,
|
516 |
+
new Chargeback($this->client)
|
517 |
+
);
|
518 |
}
|
519 |
+
|
520 |
return $resourceCollection;
|
521 |
}
|
522 |
+
|
523 |
/**
|
524 |
* Retrieves a specific chargeback for this payment.
|
525 |
*
|
530 |
*/
|
531 |
public function getChargeback($chargebackId, array $parameters = [])
|
532 |
{
|
533 |
+
return $this->client->paymentChargebacks->getFor(
|
534 |
+
$this,
|
535 |
+
$chargebackId,
|
536 |
+
$parameters
|
537 |
+
);
|
538 |
}
|
539 |
+
|
540 |
/**
|
541 |
* Issue a refund for this payment.
|
542 |
*
|
550 |
*/
|
551 |
public function refund($data = [])
|
552 |
{
|
553 |
+
$resource = "payments/" . urlencode($this->id) . "/refunds";
|
554 |
+
|
555 |
$body = null;
|
556 |
+
if (count($data) > 0) {
|
557 |
+
$body = json_encode($data);
|
558 |
}
|
559 |
+
|
560 |
+
$result = $this->client->performHttpCall(
|
561 |
+
MollieApiClient::HTTP_POST,
|
562 |
+
$resource,
|
563 |
+
$body
|
564 |
+
);
|
565 |
+
|
566 |
+
return ResourceFactory::createFromApiResult(
|
567 |
+
$result,
|
568 |
+
new Refund($this->client)
|
569 |
+
);
|
570 |
}
|
571 |
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class PaymentCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class PaymentCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "payments";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class PaymentCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "payments";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Payment($this->client);
|
21 |
}
|
22 |
}
|
@@ -2,25 +2,29 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class Permission extends
|
6 |
{
|
7 |
/**
|
8 |
* @var string
|
9 |
*/
|
10 |
public $resource;
|
|
|
11 |
/**
|
12 |
* @var string
|
13 |
* @example payments.read
|
14 |
*/
|
15 |
public $id;
|
|
|
16 |
/**
|
17 |
* @var string
|
18 |
*/
|
19 |
public $description;
|
|
|
20 |
/**
|
21 |
* @var bool
|
22 |
*/
|
23 |
public $granted;
|
|
|
24 |
/**
|
25 |
* @var object[]
|
26 |
*/
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class Permission extends BaseResource
|
6 |
{
|
7 |
/**
|
8 |
* @var string
|
9 |
*/
|
10 |
public $resource;
|
11 |
+
|
12 |
/**
|
13 |
* @var string
|
14 |
* @example payments.read
|
15 |
*/
|
16 |
public $id;
|
17 |
+
|
18 |
/**
|
19 |
* @var string
|
20 |
*/
|
21 |
public $description;
|
22 |
+
|
23 |
/**
|
24 |
* @var bool
|
25 |
*/
|
26 |
public $granted;
|
27 |
+
|
28 |
/**
|
29 |
* @var object[]
|
30 |
*/
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class PermissionCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class PermissionCollection extends BaseCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -5,52 +5,63 @@ namespace Mollie\Api\Resources;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\MollieApiClient;
|
7 |
use Mollie\Api\Types\ProfileStatus;
|
8 |
-
|
|
|
9 |
{
|
10 |
/**
|
11 |
* @var string
|
12 |
*/
|
13 |
public $resource;
|
|
|
14 |
/**
|
15 |
* @var string
|
16 |
*/
|
17 |
public $id;
|
|
|
18 |
/**
|
19 |
* Test or live mode
|
20 |
*
|
21 |
* @var string
|
22 |
*/
|
23 |
public $mode;
|
|
|
24 |
/**
|
25 |
* @var string
|
26 |
*/
|
27 |
public $name;
|
|
|
28 |
/**
|
29 |
* @var string
|
30 |
*/
|
31 |
public $website;
|
|
|
32 |
/**
|
33 |
* @var string
|
34 |
*/
|
35 |
public $email;
|
|
|
36 |
/**
|
37 |
* @var string
|
38 |
*/
|
39 |
public $phone;
|
|
|
40 |
/**
|
41 |
* See https://docs.mollie.com/reference/v2/profiles-api/get-profile
|
42 |
*
|
43 |
* @var int
|
44 |
*/
|
45 |
public $categoryCode;
|
|
|
46 |
/**
|
47 |
* @var string
|
48 |
*/
|
49 |
public $status;
|
|
|
50 |
/**
|
51 |
* @var object
|
52 |
*/
|
53 |
public $review;
|
|
|
54 |
/**
|
55 |
* UTC datetime the profile was created in ISO-8601 format.
|
56 |
*
|
@@ -58,31 +69,36 @@ class Profile extends \Mollie\Api\Resources\BaseResource
|
|
58 |
* @var string
|
59 |
*/
|
60 |
public $createdAt;
|
|
|
61 |
/**
|
62 |
* @var object[]
|
63 |
*/
|
64 |
public $_links;
|
|
|
65 |
/**
|
66 |
* @return bool
|
67 |
*/
|
68 |
public function isUnverified()
|
69 |
{
|
70 |
-
return $this->status ==
|
71 |
}
|
|
|
72 |
/**
|
73 |
* @return bool
|
74 |
*/
|
75 |
public function isVerified()
|
76 |
{
|
77 |
-
return $this->status ==
|
78 |
}
|
|
|
79 |
/**
|
80 |
* @return bool
|
81 |
*/
|
82 |
public function isBlocked()
|
83 |
{
|
84 |
-
return $this->status ==
|
85 |
}
|
|
|
86 |
/**
|
87 |
* @return Profile
|
88 |
*/
|
@@ -91,10 +107,21 @@ class Profile extends \Mollie\Api\Resources\BaseResource
|
|
91 |
if (!isset($this->_links->self->href)) {
|
92 |
return $this;
|
93 |
}
|
94 |
-
|
95 |
-
$
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
}
|
|
|
98 |
/**
|
99 |
* Retrieves all chargebacks associated with this profile
|
100 |
*
|
@@ -104,15 +131,19 @@ class Profile extends \Mollie\Api\Resources\BaseResource
|
|
104 |
public function chargebacks()
|
105 |
{
|
106 |
if (!isset($this->_links->chargebacks->href)) {
|
107 |
-
return new
|
108 |
}
|
109 |
-
|
110 |
-
$
|
|
|
|
|
111 |
foreach ($result->_embedded->chargebacks as $dataResult) {
|
112 |
-
$resourceCollection[] =
|
113 |
}
|
|
|
114 |
return $resourceCollection;
|
115 |
}
|
|
|
116 |
/**
|
117 |
* Retrieves all methods activated on this profile
|
118 |
*
|
@@ -122,15 +153,19 @@ class Profile extends \Mollie\Api\Resources\BaseResource
|
|
122 |
public function methods()
|
123 |
{
|
124 |
if (!isset($this->_links->methods->href)) {
|
125 |
-
return new
|
126 |
}
|
127 |
-
|
128 |
-
$
|
|
|
|
|
129 |
foreach ($result->_embedded->methods as $dataResult) {
|
130 |
-
$resourceCollection[] =
|
131 |
}
|
|
|
132 |
return $resourceCollection;
|
133 |
}
|
|
|
134 |
/**
|
135 |
* Retrieves all payments associated with this profile
|
136 |
*
|
@@ -140,15 +175,19 @@ class Profile extends \Mollie\Api\Resources\BaseResource
|
|
140 |
public function payments()
|
141 |
{
|
142 |
if (!isset($this->_links->payments->href)) {
|
143 |
-
return new
|
144 |
}
|
145 |
-
|
146 |
-
$
|
|
|
|
|
147 |
foreach ($result->_embedded->payments as $dataResult) {
|
148 |
-
$resourceCollection[] =
|
149 |
}
|
|
|
150 |
return $resourceCollection;
|
151 |
}
|
|
|
152 |
/**
|
153 |
* Retrieves all refunds associated with this profile
|
154 |
*
|
@@ -158,13 +197,16 @@ class Profile extends \Mollie\Api\Resources\BaseResource
|
|
158 |
public function refunds()
|
159 |
{
|
160 |
if (!isset($this->_links->refunds->href)) {
|
161 |
-
return new
|
162 |
}
|
163 |
-
|
164 |
-
$
|
|
|
|
|
165 |
foreach ($result->_embedded->refunds as $dataResult) {
|
166 |
-
$resourceCollection[] =
|
167 |
}
|
|
|
168 |
return $resourceCollection;
|
169 |
}
|
170 |
-
}
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\MollieApiClient;
|
7 |
use Mollie\Api\Types\ProfileStatus;
|
8 |
+
|
9 |
+
class Profile extends BaseResource
|
10 |
{
|
11 |
/**
|
12 |
* @var string
|
13 |
*/
|
14 |
public $resource;
|
15 |
+
|
16 |
/**
|
17 |
* @var string
|
18 |
*/
|
19 |
public $id;
|
20 |
+
|
21 |
/**
|
22 |
* Test or live mode
|
23 |
*
|
24 |
* @var string
|
25 |
*/
|
26 |
public $mode;
|
27 |
+
|
28 |
/**
|
29 |
* @var string
|
30 |
*/
|
31 |
public $name;
|
32 |
+
|
33 |
/**
|
34 |
* @var string
|
35 |
*/
|
36 |
public $website;
|
37 |
+
|
38 |
/**
|
39 |
* @var string
|
40 |
*/
|
41 |
public $email;
|
42 |
+
|
43 |
/**
|
44 |
* @var string
|
45 |
*/
|
46 |
public $phone;
|
47 |
+
|
48 |
/**
|
49 |
* See https://docs.mollie.com/reference/v2/profiles-api/get-profile
|
50 |
*
|
51 |
* @var int
|
52 |
*/
|
53 |
public $categoryCode;
|
54 |
+
|
55 |
/**
|
56 |
* @var string
|
57 |
*/
|
58 |
public $status;
|
59 |
+
|
60 |
/**
|
61 |
* @var object
|
62 |
*/
|
63 |
public $review;
|
64 |
+
|
65 |
/**
|
66 |
* UTC datetime the profile was created in ISO-8601 format.
|
67 |
*
|
69 |
* @var string
|
70 |
*/
|
71 |
public $createdAt;
|
72 |
+
|
73 |
/**
|
74 |
* @var object[]
|
75 |
*/
|
76 |
public $_links;
|
77 |
+
|
78 |
/**
|
79 |
* @return bool
|
80 |
*/
|
81 |
public function isUnverified()
|
82 |
{
|
83 |
+
return $this->status == ProfileStatus::STATUS_UNVERIFIED;
|
84 |
}
|
85 |
+
|
86 |
/**
|
87 |
* @return bool
|
88 |
*/
|
89 |
public function isVerified()
|
90 |
{
|
91 |
+
return $this->status == ProfileStatus::STATUS_VERIFIED;
|
92 |
}
|
93 |
+
|
94 |
/**
|
95 |
* @return bool
|
96 |
*/
|
97 |
public function isBlocked()
|
98 |
{
|
99 |
+
return $this->status == ProfileStatus::STATUS_BLOCKED;
|
100 |
}
|
101 |
+
|
102 |
/**
|
103 |
* @return Profile
|
104 |
*/
|
107 |
if (!isset($this->_links->self->href)) {
|
108 |
return $this;
|
109 |
}
|
110 |
+
|
111 |
+
$body = json_encode(array(
|
112 |
+
"name" => $this->name,
|
113 |
+
"website" => $this->website,
|
114 |
+
"email" => $this->email,
|
115 |
+
"phone" => $this->phone,
|
116 |
+
"categoryCode" => $this->categoryCode,
|
117 |
+
"mode" => $this->mode,
|
118 |
+
));
|
119 |
+
|
120 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_PATCH, $this->_links->self->href, $body);
|
121 |
+
|
122 |
+
return ResourceFactory::createFromApiResult($result, new Profile($this->client));
|
123 |
}
|
124 |
+
|
125 |
/**
|
126 |
* Retrieves all chargebacks associated with this profile
|
127 |
*
|
131 |
public function chargebacks()
|
132 |
{
|
133 |
if (!isset($this->_links->chargebacks->href)) {
|
134 |
+
return new ChargebackCollection($this->client, 0, null);
|
135 |
}
|
136 |
+
|
137 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->chargebacks->href);
|
138 |
+
|
139 |
+
$resourceCollection = new ChargebackCollection($this->client, $result->count, $result->_links);
|
140 |
foreach ($result->_embedded->chargebacks as $dataResult) {
|
141 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Chargeback($this->client));
|
142 |
}
|
143 |
+
|
144 |
return $resourceCollection;
|
145 |
}
|
146 |
+
|
147 |
/**
|
148 |
* Retrieves all methods activated on this profile
|
149 |
*
|
153 |
public function methods()
|
154 |
{
|
155 |
if (!isset($this->_links->methods->href)) {
|
156 |
+
return new MethodCollection(0, null);
|
157 |
}
|
158 |
+
|
159 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->methods->href);
|
160 |
+
|
161 |
+
$resourceCollection = new MethodCollection($result->count, $result->_links);
|
162 |
foreach ($result->_embedded->methods as $dataResult) {
|
163 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Method($this->client));
|
164 |
}
|
165 |
+
|
166 |
return $resourceCollection;
|
167 |
}
|
168 |
+
|
169 |
/**
|
170 |
* Retrieves all payments associated with this profile
|
171 |
*
|
175 |
public function payments()
|
176 |
{
|
177 |
if (!isset($this->_links->payments->href)) {
|
178 |
+
return new PaymentCollection($this->client, 0, null);
|
179 |
}
|
180 |
+
|
181 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->payments->href);
|
182 |
+
|
183 |
+
$resourceCollection = new PaymentCollection($this->client, $result->count, $result->_links);
|
184 |
foreach ($result->_embedded->payments as $dataResult) {
|
185 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Payment($this->client));
|
186 |
}
|
187 |
+
|
188 |
return $resourceCollection;
|
189 |
}
|
190 |
+
|
191 |
/**
|
192 |
* Retrieves all refunds associated with this profile
|
193 |
*
|
197 |
public function refunds()
|
198 |
{
|
199 |
if (!isset($this->_links->refunds->href)) {
|
200 |
+
return new RefundCollection($this->client, 0, null);
|
201 |
}
|
202 |
+
|
203 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->refunds->href);
|
204 |
+
|
205 |
+
$resourceCollection = new RefundCollection($this->client, $result->count, $result->_links);
|
206 |
foreach ($result->_embedded->refunds as $dataResult) {
|
207 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Refund($this->client));
|
208 |
}
|
209 |
+
|
210 |
return $resourceCollection;
|
211 |
}
|
212 |
+
}
|
@@ -2,8 +2,9 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class ProfileCollection extends
|
6 |
{
|
|
|
7 |
/**
|
8 |
* @return string
|
9 |
*/
|
@@ -11,11 +12,12 @@ class ProfileCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "profiles";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class ProfileCollection extends CursorCollection
|
6 |
{
|
7 |
+
|
8 |
/**
|
9 |
* @return string
|
10 |
*/
|
12 |
{
|
13 |
return "profiles";
|
14 |
}
|
15 |
+
|
16 |
/**
|
17 |
* @return BaseResource
|
18 |
*/
|
19 |
protected function createResourceObject()
|
20 |
{
|
21 |
+
return new Profile($this->client);
|
22 |
}
|
23 |
+
}
|
@@ -4,24 +4,28 @@ namespace Mollie\Api\Resources;
|
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\RefundStatus;
|
7 |
-
|
|
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
public $resource;
|
|
|
13 |
/**
|
14 |
* Id of the payment method.
|
15 |
*
|
16 |
* @var string
|
17 |
*/
|
18 |
public $id;
|
|
|
19 |
/**
|
20 |
* The $amount that was refunded.
|
21 |
*
|
22 |
* @var object
|
23 |
*/
|
24 |
public $amount;
|
|
|
25 |
/**
|
26 |
* UTC datetime the payment was created in ISO-8601 format.
|
27 |
*
|
@@ -29,24 +33,28 @@ class Refund extends \Mollie\Api\Resources\BaseResource
|
|
29 |
* @var string
|
30 |
*/
|
31 |
public $createdAt;
|
|
|
32 |
/**
|
33 |
* The refund's description, if available.
|
34 |
*
|
35 |
* @var string|null
|
36 |
*/
|
37 |
public $description;
|
|
|
38 |
/**
|
39 |
* The payment id that was refunded.
|
40 |
*
|
41 |
* @var string
|
42 |
*/
|
43 |
public $paymentId;
|
|
|
44 |
/**
|
45 |
* The order id that was refunded.
|
46 |
*
|
47 |
* @var string|null
|
48 |
*/
|
49 |
public $orderId;
|
|
|
50 |
/**
|
51 |
* The order lines contain the actual things the customer ordered.
|
52 |
* The lines will show the quantity, discountAmount, vatAmount and totalAmount
|
@@ -55,22 +63,26 @@ class Refund extends \Mollie\Api\Resources\BaseResource
|
|
55 |
* @var array|object[]|null
|
56 |
*/
|
57 |
public $lines;
|
|
|
58 |
/**
|
59 |
* The settlement amount
|
60 |
*
|
61 |
* @var object
|
62 |
*/
|
63 |
public $settlementAmount;
|
|
|
64 |
/**
|
65 |
* The refund status
|
66 |
*
|
67 |
* @var string
|
68 |
*/
|
69 |
public $status;
|
|
|
70 |
/**
|
71 |
* @var object[]
|
72 |
*/
|
73 |
public $_links;
|
|
|
74 |
/**
|
75 |
* Is this refund queued?
|
76 |
*
|
@@ -78,8 +90,9 @@ class Refund extends \Mollie\Api\Resources\BaseResource
|
|
78 |
*/
|
79 |
public function isQueued()
|
80 |
{
|
81 |
-
return $this->status ===
|
82 |
}
|
|
|
83 |
/**
|
84 |
* Is this refund pending?
|
85 |
*
|
@@ -87,8 +100,9 @@ class Refund extends \Mollie\Api\Resources\BaseResource
|
|
87 |
*/
|
88 |
public function isPending()
|
89 |
{
|
90 |
-
return $this->status ===
|
91 |
}
|
|
|
92 |
/**
|
93 |
* Is this refund processing?
|
94 |
*
|
@@ -96,8 +110,9 @@ class Refund extends \Mollie\Api\Resources\BaseResource
|
|
96 |
*/
|
97 |
public function isProcessing()
|
98 |
{
|
99 |
-
return $this->status ===
|
100 |
}
|
|
|
101 |
/**
|
102 |
* Is this refund transferred to consumer?
|
103 |
*
|
@@ -105,8 +120,9 @@ class Refund extends \Mollie\Api\Resources\BaseResource
|
|
105 |
*/
|
106 |
public function isTransferred()
|
107 |
{
|
108 |
-
return $this->status ===
|
109 |
}
|
|
|
110 |
/**
|
111 |
* Cancel the refund.
|
112 |
* Returns null if successful.
|
@@ -116,7 +132,11 @@ class Refund extends \Mollie\Api\Resources\BaseResource
|
|
116 |
*/
|
117 |
public function cancel()
|
118 |
{
|
119 |
-
$this->client->performHttpCallToFullUrl(
|
|
|
|
|
|
|
|
|
120 |
return null;
|
121 |
}
|
122 |
}
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\RefundStatus;
|
7 |
+
|
8 |
+
class Refund extends BaseResource
|
9 |
{
|
10 |
/**
|
11 |
* @var string
|
12 |
*/
|
13 |
public $resource;
|
14 |
+
|
15 |
/**
|
16 |
* Id of the payment method.
|
17 |
*
|
18 |
* @var string
|
19 |
*/
|
20 |
public $id;
|
21 |
+
|
22 |
/**
|
23 |
* The $amount that was refunded.
|
24 |
*
|
25 |
* @var object
|
26 |
*/
|
27 |
public $amount;
|
28 |
+
|
29 |
/**
|
30 |
* UTC datetime the payment was created in ISO-8601 format.
|
31 |
*
|
33 |
* @var string
|
34 |
*/
|
35 |
public $createdAt;
|
36 |
+
|
37 |
/**
|
38 |
* The refund's description, if available.
|
39 |
*
|
40 |
* @var string|null
|
41 |
*/
|
42 |
public $description;
|
43 |
+
|
44 |
/**
|
45 |
* The payment id that was refunded.
|
46 |
*
|
47 |
* @var string
|
48 |
*/
|
49 |
public $paymentId;
|
50 |
+
|
51 |
/**
|
52 |
* The order id that was refunded.
|
53 |
*
|
54 |
* @var string|null
|
55 |
*/
|
56 |
public $orderId;
|
57 |
+
|
58 |
/**
|
59 |
* The order lines contain the actual things the customer ordered.
|
60 |
* The lines will show the quantity, discountAmount, vatAmount and totalAmount
|
63 |
* @var array|object[]|null
|
64 |
*/
|
65 |
public $lines;
|
66 |
+
|
67 |
/**
|
68 |
* The settlement amount
|
69 |
*
|
70 |
* @var object
|
71 |
*/
|
72 |
public $settlementAmount;
|
73 |
+
|
74 |
/**
|
75 |
* The refund status
|
76 |
*
|
77 |
* @var string
|
78 |
*/
|
79 |
public $status;
|
80 |
+
|
81 |
/**
|
82 |
* @var object[]
|
83 |
*/
|
84 |
public $_links;
|
85 |
+
|
86 |
/**
|
87 |
* Is this refund queued?
|
88 |
*
|
90 |
*/
|
91 |
public function isQueued()
|
92 |
{
|
93 |
+
return $this->status === RefundStatus::STATUS_QUEUED;
|
94 |
}
|
95 |
+
|
96 |
/**
|
97 |
* Is this refund pending?
|
98 |
*
|
100 |
*/
|
101 |
public function isPending()
|
102 |
{
|
103 |
+
return $this->status === RefundStatus::STATUS_PENDING;
|
104 |
}
|
105 |
+
|
106 |
/**
|
107 |
* Is this refund processing?
|
108 |
*
|
110 |
*/
|
111 |
public function isProcessing()
|
112 |
{
|
113 |
+
return $this->status === RefundStatus::STATUS_PROCESSING;
|
114 |
}
|
115 |
+
|
116 |
/**
|
117 |
* Is this refund transferred to consumer?
|
118 |
*
|
120 |
*/
|
121 |
public function isTransferred()
|
122 |
{
|
123 |
+
return $this->status === RefundStatus::STATUS_REFUNDED;
|
124 |
}
|
125 |
+
|
126 |
/**
|
127 |
* Cancel the refund.
|
128 |
* Returns null if successful.
|
132 |
*/
|
133 |
public function cancel()
|
134 |
{
|
135 |
+
$this->client->performHttpCallToFullUrl(
|
136 |
+
MollieApiClient::HTTP_DELETE,
|
137 |
+
$this->_links->self->href
|
138 |
+
);
|
139 |
+
|
140 |
return null;
|
141 |
}
|
142 |
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class RefundCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class RefundCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "refunds";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class RefundCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "refunds";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Refund($this->client);
|
21 |
}
|
22 |
}
|
@@ -12,11 +12,13 @@ class ResourceFactory
|
|
12 |
*
|
13 |
* @return BaseResource
|
14 |
*/
|
15 |
-
public static function createFromApiResult($apiResult,
|
16 |
{
|
17 |
foreach ($apiResult as $property => $value) {
|
18 |
$resource->{$property} = $value;
|
19 |
}
|
|
|
20 |
return $resource;
|
21 |
}
|
22 |
-
|
|
12 |
*
|
13 |
* @return BaseResource
|
14 |
*/
|
15 |
+
public static function createFromApiResult($apiResult, BaseResource $resource)
|
16 |
{
|
17 |
foreach ($apiResult as $property => $value) {
|
18 |
$resource->{$property} = $value;
|
19 |
}
|
20 |
+
|
21 |
return $resource;
|
22 |
}
|
23 |
+
|
24 |
+
}
|
@@ -5,24 +5,28 @@ namespace Mollie\Api\Resources;
|
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\MollieApiClient;
|
7 |
use Mollie\Api\Types\SettlementStatus;
|
8 |
-
|
|
|
9 |
{
|
10 |
/**
|
11 |
* @var string
|
12 |
*/
|
13 |
public $resource;
|
|
|
14 |
/**
|
15 |
* Id of the settlement.
|
16 |
*
|
17 |
* @var string
|
18 |
*/
|
19 |
public $id;
|
|
|
20 |
/**
|
21 |
* The settlement reference. This corresponds to an invoice that's in your Dashboard.
|
22 |
*
|
23 |
* @var string
|
24 |
*/
|
25 |
public $reference;
|
|
|
26 |
/**
|
27 |
* UTC datetime the payment was created in ISO-8601 format.
|
28 |
*
|
@@ -30,34 +34,40 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
30 |
* @var string
|
31 |
*/
|
32 |
public $createdAt;
|
|
|
33 |
/**
|
34 |
* Status of the settlement.
|
35 |
*
|
36 |
* @var string
|
37 |
*/
|
38 |
public $status;
|
|
|
39 |
/**
|
40 |
* Total settlement amount in euros.
|
41 |
*
|
42 |
* @var object
|
43 |
*/
|
44 |
public $amount;
|
|
|
45 |
/**
|
46 |
* Revenues and costs nested per year, per month, and per payment method.
|
47 |
*
|
48 |
* @var object
|
49 |
*/
|
50 |
public $periods;
|
|
|
51 |
/**
|
52 |
* The ID of the invoice on which this settlement is invoiced, if it has been invoiced.
|
53 |
*
|
54 |
* @var string|null
|
55 |
*/
|
56 |
public $invoiceId;
|
|
|
57 |
/**
|
58 |
* @var object[]
|
59 |
*/
|
60 |
public $_links;
|
|
|
61 |
/**
|
62 |
* Is this settlement still open?
|
63 |
*
|
@@ -65,8 +75,9 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
65 |
*/
|
66 |
public function isOpen()
|
67 |
{
|
68 |
-
return $this->status ===
|
69 |
}
|
|
|
70 |
/**
|
71 |
* Is this settlement pending?
|
72 |
*
|
@@ -74,8 +85,9 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
74 |
*/
|
75 |
public function isPending()
|
76 |
{
|
77 |
-
return $this->status ===
|
78 |
}
|
|
|
79 |
/**
|
80 |
* Is this settlement paidout?
|
81 |
*
|
@@ -83,8 +95,9 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
83 |
*/
|
84 |
public function isPaidout()
|
85 |
{
|
86 |
-
return $this->status ===
|
87 |
}
|
|
|
88 |
/**
|
89 |
* Is this settlement failed?
|
90 |
*
|
@@ -92,8 +105,9 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
92 |
*/
|
93 |
public function isFailed()
|
94 |
{
|
95 |
-
return $this->status ===
|
96 |
}
|
|
|
97 |
/**
|
98 |
* Retrieves all payments associated with this settlement
|
99 |
*
|
@@ -103,15 +117,19 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
103 |
public function payments()
|
104 |
{
|
105 |
if (!isset($this->_links->payments->href)) {
|
106 |
-
return new
|
107 |
}
|
108 |
-
|
109 |
-
$
|
|
|
|
|
110 |
foreach ($result->_embedded->payments as $dataResult) {
|
111 |
-
$resourceCollection[] =
|
112 |
}
|
|
|
113 |
return $resourceCollection;
|
114 |
}
|
|
|
115 |
/**
|
116 |
* Retrieves all refunds associated with this settlement
|
117 |
*
|
@@ -121,15 +139,19 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
121 |
public function refunds()
|
122 |
{
|
123 |
if (!isset($this->_links->refunds->href)) {
|
124 |
-
return new
|
125 |
}
|
126 |
-
|
127 |
-
$
|
|
|
|
|
128 |
foreach ($result->_embedded->refunds as $dataResult) {
|
129 |
-
$resourceCollection[] =
|
130 |
}
|
|
|
131 |
return $resourceCollection;
|
132 |
}
|
|
|
133 |
/**
|
134 |
* Retrieves all chargebacks associated with this settlement
|
135 |
*
|
@@ -139,13 +161,16 @@ class Settlement extends \Mollie\Api\Resources\BaseResource
|
|
139 |
public function chargebacks()
|
140 |
{
|
141 |
if (!isset($this->_links->chargebacks->href)) {
|
142 |
-
return new
|
143 |
}
|
144 |
-
|
145 |
-
$
|
|
|
|
|
146 |
foreach ($result->_embedded->chargebacks as $dataResult) {
|
147 |
-
$resourceCollection[] =
|
148 |
}
|
|
|
149 |
return $resourceCollection;
|
150 |
}
|
151 |
-
}
|
5 |
use Mollie\Api\Exceptions\ApiException;
|
6 |
use Mollie\Api\MollieApiClient;
|
7 |
use Mollie\Api\Types\SettlementStatus;
|
8 |
+
|
9 |
+
class Settlement extends BaseResource
|
10 |
{
|
11 |
/**
|
12 |
* @var string
|
13 |
*/
|
14 |
public $resource;
|
15 |
+
|
16 |
/**
|
17 |
* Id of the settlement.
|
18 |
*
|
19 |
* @var string
|
20 |
*/
|
21 |
public $id;
|
22 |
+
|
23 |
/**
|
24 |
* The settlement reference. This corresponds to an invoice that's in your Dashboard.
|
25 |
*
|
26 |
* @var string
|
27 |
*/
|
28 |
public $reference;
|
29 |
+
|
30 |
/**
|
31 |
* UTC datetime the payment was created in ISO-8601 format.
|
32 |
*
|
34 |
* @var string
|
35 |
*/
|
36 |
public $createdAt;
|
37 |
+
|
38 |
/**
|
39 |
* Status of the settlement.
|
40 |
*
|
41 |
* @var string
|
42 |
*/
|
43 |
public $status;
|
44 |
+
|
45 |
/**
|
46 |
* Total settlement amount in euros.
|
47 |
*
|
48 |
* @var object
|
49 |
*/
|
50 |
public $amount;
|
51 |
+
|
52 |
/**
|
53 |
* Revenues and costs nested per year, per month, and per payment method.
|
54 |
*
|
55 |
* @var object
|
56 |
*/
|
57 |
public $periods;
|
58 |
+
|
59 |
/**
|
60 |
* The ID of the invoice on which this settlement is invoiced, if it has been invoiced.
|
61 |
*
|
62 |
* @var string|null
|
63 |
*/
|
64 |
public $invoiceId;
|
65 |
+
|
66 |
/**
|
67 |
* @var object[]
|
68 |
*/
|
69 |
public $_links;
|
70 |
+
|
71 |
/**
|
72 |
* Is this settlement still open?
|
73 |
*
|
75 |
*/
|
76 |
public function isOpen()
|
77 |
{
|
78 |
+
return $this->status === SettlementStatus::STATUS_OPEN;
|
79 |
}
|
80 |
+
|
81 |
/**
|
82 |
* Is this settlement pending?
|
83 |
*
|
85 |
*/
|
86 |
public function isPending()
|
87 |
{
|
88 |
+
return $this->status === SettlementStatus::STATUS_PENDING;
|
89 |
}
|
90 |
+
|
91 |
/**
|
92 |
* Is this settlement paidout?
|
93 |
*
|
95 |
*/
|
96 |
public function isPaidout()
|
97 |
{
|
98 |
+
return $this->status === SettlementStatus::STATUS_PAIDOUT;
|
99 |
}
|
100 |
+
|
101 |
/**
|
102 |
* Is this settlement failed?
|
103 |
*
|
105 |
*/
|
106 |
public function isFailed()
|
107 |
{
|
108 |
+
return $this->status === SettlementStatus::STATUS_FAILED;
|
109 |
}
|
110 |
+
|
111 |
/**
|
112 |
* Retrieves all payments associated with this settlement
|
113 |
*
|
117 |
public function payments()
|
118 |
{
|
119 |
if (!isset($this->_links->payments->href)) {
|
120 |
+
return new PaymentCollection($this->client, 0, null);
|
121 |
}
|
122 |
+
|
123 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->payments->href);
|
124 |
+
|
125 |
+
$resourceCollection = new PaymentCollection($this->client, $result->count, $result->_links);
|
126 |
foreach ($result->_embedded->payments as $dataResult) {
|
127 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Payment($this->client));
|
128 |
}
|
129 |
+
|
130 |
return $resourceCollection;
|
131 |
}
|
132 |
+
|
133 |
/**
|
134 |
* Retrieves all refunds associated with this settlement
|
135 |
*
|
139 |
public function refunds()
|
140 |
{
|
141 |
if (!isset($this->_links->refunds->href)) {
|
142 |
+
return new RefundCollection($this->client, 0, null);
|
143 |
}
|
144 |
+
|
145 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->refunds->href);
|
146 |
+
|
147 |
+
$resourceCollection = new RefundCollection($this->client, $result->count, $result->_links);
|
148 |
foreach ($result->_embedded->refunds as $dataResult) {
|
149 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Refund($this->client));
|
150 |
}
|
151 |
+
|
152 |
return $resourceCollection;
|
153 |
}
|
154 |
+
|
155 |
/**
|
156 |
* Retrieves all chargebacks associated with this settlement
|
157 |
*
|
161 |
public function chargebacks()
|
162 |
{
|
163 |
if (!isset($this->_links->chargebacks->href)) {
|
164 |
+
return new ChargebackCollection($this->client, 0, null);
|
165 |
}
|
166 |
+
|
167 |
+
$result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->chargebacks->href);
|
168 |
+
|
169 |
+
$resourceCollection = new ChargebackCollection($this->client, $result->count, $result->_links);
|
170 |
foreach ($result->_embedded->chargebacks as $dataResult) {
|
171 |
+
$resourceCollection[] = ResourceFactory::createFromApiResult($dataResult, new Chargeback($this->client));
|
172 |
}
|
173 |
+
|
174 |
return $resourceCollection;
|
175 |
}
|
176 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class SettlementCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -11,11 +11,12 @@ class SettlementCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "settlements";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class SettlementCollection extends CursorCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
11 |
{
|
12 |
return "settlements";
|
13 |
}
|
14 |
+
|
15 |
/**
|
16 |
* @return BaseResource
|
17 |
*/
|
18 |
protected function createResourceObject()
|
19 |
{
|
20 |
+
return new Settlement($this->client);
|
21 |
}
|
22 |
+
}
|
@@ -3,12 +3,14 @@
|
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
-
|
|
|
7 |
{
|
8 |
/**
|
9 |
* @var string
|
10 |
*/
|
11 |
public $resource;
|
|
|
12 |
/**
|
13 |
* The shipment’s unique identifier,
|
14 |
*
|
@@ -16,6 +18,7 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
16 |
* @var string
|
17 |
*/
|
18 |
public $id;
|
|
|
19 |
/**
|
20 |
* Id of the order.
|
21 |
*
|
@@ -23,6 +26,7 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
23 |
* @var string
|
24 |
*/
|
25 |
public $orderId;
|
|
|
26 |
/**
|
27 |
* UTC datetime the shipment was created in ISO-8601 format.
|
28 |
*
|
@@ -30,21 +34,26 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
30 |
* @var string|null
|
31 |
*/
|
32 |
public $createdAt;
|
|
|
33 |
/**
|
34 |
* The order object lines contain the actual things the customer bought.
|
35 |
* @var array|object[]
|
36 |
*/
|
37 |
public $lines;
|
|
|
|
|
38 |
/**
|
39 |
* An object containing tracking details for the shipment, if available.
|
40 |
* @var object|null
|
41 |
*/
|
42 |
public $tracking;
|
|
|
43 |
/**
|
44 |
* An object with several URL objects relevant to the customer. Every URL object will contain an href and a type field.
|
45 |
* @var object[]
|
46 |
*/
|
47 |
public $_links;
|
|
|
48 |
/**
|
49 |
* Does this shipment offer track and trace?
|
50 |
*
|
@@ -54,6 +63,7 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
54 |
{
|
55 |
return $this->tracking !== null;
|
56 |
}
|
|
|
57 |
/**
|
58 |
* Does this shipment offer a track and trace code?
|
59 |
*
|
@@ -63,6 +73,7 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
63 |
{
|
64 |
return $this->hasTracking() && !empty($this->tracking->url);
|
65 |
}
|
|
|
66 |
/**
|
67 |
* Retrieve the track and trace url. Returns null if there is no url available.
|
68 |
*
|
@@ -75,6 +86,7 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
75 |
}
|
76 |
return $this->tracking->url;
|
77 |
}
|
|
|
78 |
/**
|
79 |
* Get the line value objects
|
80 |
*
|
@@ -82,12 +94,14 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
82 |
*/
|
83 |
public function lines()
|
84 |
{
|
85 |
-
$lines
|
86 |
foreach ($this->lines as $line) {
|
87 |
-
$lines->append(
|
88 |
}
|
|
|
89 |
return $lines;
|
90 |
}
|
|
|
91 |
/**
|
92 |
* Get the Order object for this shipment
|
93 |
*
|
@@ -97,6 +111,7 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
97 |
{
|
98 |
return $this->client->orders->get($this->orderId);
|
99 |
}
|
|
|
100 |
/**
|
101 |
* Save changes made to this shipment.
|
102 |
*
|
@@ -108,8 +123,17 @@ class Shipment extends \Mollie\Api\Resources\BaseResource
|
|
108 |
if (!isset($this->_links->self->href)) {
|
109 |
return $this;
|
110 |
}
|
111 |
-
|
112 |
-
$
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
}
|
115 |
}
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
+
|
7 |
+
class Shipment extends BaseResource
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
public $resource;
|
13 |
+
|
14 |
/**
|
15 |
* The shipment’s unique identifier,
|
16 |
*
|
18 |
* @var string
|
19 |
*/
|
20 |
public $id;
|
21 |
+
|
22 |
/**
|
23 |
* Id of the order.
|
24 |
*
|
26 |
* @var string
|
27 |
*/
|
28 |
public $orderId;
|
29 |
+
|
30 |
/**
|
31 |
* UTC datetime the shipment was created in ISO-8601 format.
|
32 |
*
|
34 |
* @var string|null
|
35 |
*/
|
36 |
public $createdAt;
|
37 |
+
|
38 |
/**
|
39 |
* The order object lines contain the actual things the customer bought.
|
40 |
* @var array|object[]
|
41 |
*/
|
42 |
public $lines;
|
43 |
+
|
44 |
+
|
45 |
/**
|
46 |
* An object containing tracking details for the shipment, if available.
|
47 |
* @var object|null
|
48 |
*/
|
49 |
public $tracking;
|
50 |
+
|
51 |
/**
|
52 |
* An object with several URL objects relevant to the customer. Every URL object will contain an href and a type field.
|
53 |
* @var object[]
|
54 |
*/
|
55 |
public $_links;
|
56 |
+
|
57 |
/**
|
58 |
* Does this shipment offer track and trace?
|
59 |
*
|
63 |
{
|
64 |
return $this->tracking !== null;
|
65 |
}
|
66 |
+
|
67 |
/**
|
68 |
* Does this shipment offer a track and trace code?
|
69 |
*
|
73 |
{
|
74 |
return $this->hasTracking() && !empty($this->tracking->url);
|
75 |
}
|
76 |
+
|
77 |
/**
|
78 |
* Retrieve the track and trace url. Returns null if there is no url available.
|
79 |
*
|
86 |
}
|
87 |
return $this->tracking->url;
|
88 |
}
|
89 |
+
|
90 |
/**
|
91 |
* Get the line value objects
|
92 |
*
|
94 |
*/
|
95 |
public function lines()
|
96 |
{
|
97 |
+
$lines = new OrderLineCollection(count($this->lines), null);
|
98 |
foreach ($this->lines as $line) {
|
99 |
+
$lines->append(ResourceFactory::createFromApiResult($line, new OrderLine($this->client)));
|
100 |
}
|
101 |
+
|
102 |
return $lines;
|
103 |
}
|
104 |
+
|
105 |
/**
|
106 |
* Get the Order object for this shipment
|
107 |
*
|
111 |
{
|
112 |
return $this->client->orders->get($this->orderId);
|
113 |
}
|
114 |
+
|
115 |
/**
|
116 |
* Save changes made to this shipment.
|
117 |
*
|
123 |
if (!isset($this->_links->self->href)) {
|
124 |
return $this;
|
125 |
}
|
126 |
+
|
127 |
+
$body = json_encode([
|
128 |
+
"tracking" => $this->tracking,
|
129 |
+
]);
|
130 |
+
|
131 |
+
$result = $this->client->performHttpCallToFullUrl(
|
132 |
+
MollieApiClient::HTTP_PATCH,
|
133 |
+
$this->_links->self->href,
|
134 |
+
$body
|
135 |
+
);
|
136 |
+
|
137 |
+
return ResourceFactory::createFromApiResult($result, new Shipment($this->client));
|
138 |
}
|
139 |
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class ShipmentCollection extends
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class ShipmentCollection extends BaseCollection
|
6 |
{
|
7 |
/**
|
8 |
* @return string
|
@@ -4,82 +4,99 @@ namespace Mollie\Api\Resources;
|
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\SubscriptionStatus;
|
7 |
-
|
|
|
8 |
{
|
9 |
/**
|
10 |
* @var string
|
11 |
*/
|
12 |
public $resource;
|
|
|
13 |
/**
|
14 |
* @var string
|
15 |
*/
|
16 |
public $id;
|
|
|
17 |
/**
|
18 |
* @var string
|
19 |
*/
|
20 |
public $customerId;
|
|
|
21 |
/**
|
22 |
* Either "live" or "test" depending on the customer's mode.
|
23 |
*
|
24 |
* @var string
|
25 |
*/
|
26 |
public $mode;
|
|
|
27 |
/**
|
28 |
* UTC datetime the subscription created in ISO-8601 format.
|
29 |
*
|
30 |
* @var string
|
31 |
*/
|
32 |
public $createdAt;
|
|
|
33 |
/**
|
34 |
* @var string
|
35 |
*/
|
36 |
public $status;
|
|
|
37 |
/**
|
38 |
* @var object
|
39 |
*/
|
40 |
public $amount;
|
|
|
41 |
/**
|
42 |
* @var int|null
|
43 |
*/
|
44 |
public $times;
|
|
|
45 |
/**
|
46 |
* @var string
|
47 |
*/
|
48 |
public $interval;
|
|
|
49 |
/**
|
50 |
* @var string
|
51 |
*/
|
52 |
public $description;
|
|
|
53 |
/**
|
54 |
* @var string|null
|
55 |
*/
|
56 |
public $method;
|
|
|
57 |
/**
|
58 |
* @var string|null
|
59 |
*/
|
60 |
public $mandateId;
|
|
|
61 |
/**
|
62 |
* UTC datetime the subscription canceled in ISO-8601 format.
|
63 |
*
|
64 |
* @var string|null
|
65 |
*/
|
66 |
public $canceledAt;
|
|
|
67 |
/**
|
68 |
* Date the subscription started. For example: 2018-04-24
|
69 |
*
|
70 |
* @var string|null
|
71 |
*/
|
72 |
public $startDate;
|
|
|
73 |
/**
|
74 |
* Contains an optional 'webhookUrl'.
|
75 |
*
|
76 |
* @var object|null
|
77 |
*/
|
78 |
public $webhookUrl;
|
|
|
79 |
/**
|
80 |
* @var object[]
|
81 |
*/
|
82 |
public $_links;
|
|
|
83 |
/**
|
84 |
* @return BaseResource|Subscription
|
85 |
* @throws \Mollie\Api\Exceptions\ApiException
|
@@ -89,10 +106,26 @@ class Subscription extends \Mollie\Api\Resources\BaseResource
|
|
89 |
if (!isset($this->_links->self->href)) {
|
90 |
return $this;
|
91 |
}
|
92 |
-
|
93 |
-
$
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
|
|
|
|
96 |
/**
|
97 |
* Returns whether the Subscription is active or not.
|
98 |
*
|
@@ -100,8 +133,9 @@ class Subscription extends \Mollie\Api\Resources\BaseResource
|
|
100 |
*/
|
101 |
public function isActive()
|
102 |
{
|
103 |
-
return $this->status ===
|
104 |
}
|
|
|
105 |
/**
|
106 |
* Returns whether the Subscription is pending or not.
|
107 |
*
|
@@ -109,8 +143,9 @@ class Subscription extends \Mollie\Api\Resources\BaseResource
|
|
109 |
*/
|
110 |
public function isPending()
|
111 |
{
|
112 |
-
return $this->status ===
|
113 |
}
|
|
|
114 |
/**
|
115 |
* Returns whether the Subscription is canceled or not.
|
116 |
*
|
@@ -118,8 +153,9 @@ class Subscription extends \Mollie\Api\Resources\BaseResource
|
|
118 |
*/
|
119 |
public function isCanceled()
|
120 |
{
|
121 |
-
return $this->status ===
|
122 |
}
|
|
|
123 |
/**
|
124 |
* Returns whether the Subscription is suspended or not.
|
125 |
*
|
@@ -127,8 +163,9 @@ class Subscription extends \Mollie\Api\Resources\BaseResource
|
|
127 |
*/
|
128 |
public function isSuspended()
|
129 |
{
|
130 |
-
return $this->status ===
|
131 |
}
|
|
|
132 |
/**
|
133 |
* Returns whether the Subscription is completed or not.
|
134 |
*
|
@@ -136,8 +173,9 @@ class Subscription extends \Mollie\Api\Resources\BaseResource
|
|
136 |
*/
|
137 |
public function isCompleted()
|
138 |
{
|
139 |
-
return $this->status ===
|
140 |
}
|
|
|
141 |
/**
|
142 |
* Cancels this subscription
|
143 |
*
|
@@ -148,11 +186,20 @@ class Subscription extends \Mollie\Api\Resources\BaseResource
|
|
148 |
if (!isset($this->_links->self->href)) {
|
149 |
return $this;
|
150 |
}
|
|
|
151 |
$body = null;
|
152 |
-
if
|
153 |
-
$body =
|
|
|
|
|
154 |
}
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
}
|
158 |
}
|
4 |
|
5 |
use Mollie\Api\MollieApiClient;
|
6 |
use Mollie\Api\Types\SubscriptionStatus;
|
7 |
+
|
8 |
+
class Subscription extends BaseResource
|
9 |
{
|
10 |
/**
|
11 |
* @var string
|
12 |
*/
|
13 |
public $resource;
|
14 |
+
|
15 |
/**
|
16 |
* @var string
|
17 |
*/
|
18 |
public $id;
|
19 |
+
|
20 |
/**
|
21 |
* @var string
|
22 |
*/
|
23 |
public $customerId;
|
24 |
+
|
25 |
/**
|
26 |
* Either "live" or "test" depending on the customer's mode.
|
27 |
*
|
28 |
* @var string
|
29 |
*/
|
30 |
public $mode;
|
31 |
+
|
32 |
/**
|
33 |
* UTC datetime the subscription created in ISO-8601 format.
|
34 |
*
|
35 |
* @var string
|
36 |
*/
|
37 |
public $createdAt;
|
38 |
+
|
39 |
/**
|
40 |
* @var string
|
41 |
*/
|
42 |
public $status;
|
43 |
+
|
44 |
/**
|
45 |
* @var object
|
46 |
*/
|
47 |
public $amount;
|
48 |
+
|
49 |
/**
|
50 |
* @var int|null
|
51 |
*/
|
52 |
public $times;
|
53 |
+
|
54 |
/**
|
55 |
* @var string
|
56 |
*/
|
57 |
public $interval;
|
58 |
+
|
59 |
/**
|
60 |
* @var string
|
61 |
*/
|
62 |
public $description;
|
63 |
+
|
64 |
/**
|
65 |
* @var string|null
|
66 |
*/
|
67 |
public $method;
|
68 |
+
|
69 |
/**
|
70 |
* @var string|null
|
71 |
*/
|
72 |
public $mandateId;
|
73 |
+
|
74 |
/**
|
75 |
* UTC datetime the subscription canceled in ISO-8601 format.
|
76 |
*
|
77 |
* @var string|null
|
78 |
*/
|
79 |
public $canceledAt;
|
80 |
+
|
81 |
/**
|
82 |
* Date the subscription started. For example: 2018-04-24
|
83 |
*
|
84 |
* @var string|null
|
85 |
*/
|
86 |
public $startDate;
|
87 |
+
|
88 |
/**
|
89 |
* Contains an optional 'webhookUrl'.
|
90 |
*
|
91 |
* @var object|null
|
92 |
*/
|
93 |
public $webhookUrl;
|
94 |
+
|
95 |
/**
|
96 |
* @var object[]
|
97 |
*/
|
98 |
public $_links;
|
99 |
+
|
100 |
/**
|
101 |
* @return BaseResource|Subscription
|
102 |
* @throws \Mollie\Api\Exceptions\ApiException
|
106 |
if (!isset($this->_links->self->href)) {
|
107 |
return $this;
|
108 |
}
|
109 |
+
|
110 |
+
$body = json_encode([
|
111 |
+
"amount" => $this->amount,
|
112 |
+
"times" => $this->times,
|
113 |
+
"startDate" => $this->startDate,
|
114 |
+
"webhookUrl" => $this->webhookUrl,
|
115 |
+
"description" => $this->description,
|
116 |
+
"mandateId" => $this->mandateId,
|
117 |
+
]);
|
118 |
+
|
119 |
+
$result = $this->client->performHttpCallToFullUrl(
|
120 |
+
MollieApiClient::HTTP_PATCH,
|
121 |
+
$this->_links->self->href,
|
122 |
+
$body
|
123 |
+
);
|
124 |
+
|
125 |
+
return ResourceFactory::createFromApiResult($result, new Subscription($this->client));
|
126 |
}
|
127 |
+
|
128 |
+
|
129 |
/**
|
130 |
* Returns whether the Subscription is active or not.
|
131 |
*
|
133 |
*/
|
134 |
public function isActive()
|
135 |
{
|
136 |
+
return $this->status === SubscriptionStatus::STATUS_ACTIVE;
|
137 |
}
|
138 |
+
|
139 |
/**
|
140 |
* Returns whether the Subscription is pending or not.
|
141 |
*
|
143 |
*/
|
144 |
public function isPending()
|
145 |
{
|
146 |
+
return $this->status === SubscriptionStatus::STATUS_PENDING;
|
147 |
}
|
148 |
+
|
149 |
/**
|
150 |
* Returns whether the Subscription is canceled or not.
|
151 |
*
|
153 |
*/
|
154 |
public function isCanceled()
|
155 |
{
|
156 |
+
return $this->status === SubscriptionStatus::STATUS_CANCELED;
|
157 |
}
|
158 |
+
|
159 |
/**
|
160 |
* Returns whether the Subscription is suspended or not.
|
161 |
*
|
163 |
*/
|
164 |
public function isSuspended()
|
165 |
{
|
166 |
+
return $this->status === SubscriptionStatus::STATUS_SUSPENDED;
|
167 |
}
|
168 |
+
|
169 |
/**
|
170 |
* Returns whether the Subscription is completed or not.
|
171 |
*
|
173 |
*/
|
174 |
public function isCompleted()
|
175 |
{
|
176 |
+
return $this->status === SubscriptionStatus::STATUS_COMPLETED;
|
177 |
}
|
178 |
+
|
179 |
/**
|
180 |
* Cancels this subscription
|
181 |
*
|
186 |
if (!isset($this->_links->self->href)) {
|
187 |
return $this;
|
188 |
}
|
189 |
+
|
190 |
$body = null;
|
191 |
+
if($this->client->usesOAuth()) {
|
192 |
+
$body = json_encode([
|
193 |
+
"testmode" => $this->mode === "test" ? true : false
|
194 |
+
]);
|
195 |
}
|
196 |
+
|
197 |
+
$result = $this->client->performHttpCallToFullUrl(
|
198 |
+
MollieApiClient::HTTP_DELETE,
|
199 |
+
$this->_links->self->href,
|
200 |
+
$body
|
201 |
+
);
|
202 |
+
|
203 |
+
return ResourceFactory::createFromApiResult($result, new Subscription($this->client));
|
204 |
}
|
205 |
}
|
@@ -2,8 +2,9 @@
|
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
-
class SubscriptionCollection extends
|
6 |
{
|
|
|
7 |
/**
|
8 |
* @return string
|
9 |
*/
|
@@ -11,11 +12,12 @@ class SubscriptionCollection extends \Mollie\Api\Resources\CursorCollection
|
|
11 |
{
|
12 |
return "subscriptions";
|
13 |
}
|
|
|
14 |
/**
|
15 |
* @return BaseResource
|
16 |
*/
|
17 |
protected function createResourceObject()
|
18 |
{
|
19 |
-
return new
|
20 |
}
|
21 |
-
}
|
2 |
|
3 |
namespace Mollie\Api\Resources;
|
4 |
|
5 |
+
class SubscriptionCollection extends CursorCollection
|
6 |
{
|
7 |
+
|
8 |
/**
|
9 |
* @return string
|
10 |
*/
|
12 |
{
|
13 |
return "subscriptions";
|
14 |
}
|
15 |
+
|
16 |
/**
|
17 |
* @return BaseResource
|
18 |
*/
|
19 |
protected function createResourceObject()
|
20 |
{
|
21 |
+
return new Subscription($this->client);
|
22 |
}
|
23 |
+
}
|
@@ -8,12 +8,14 @@ class InvoiceStatus
|
|
8 |
* The invoice is not paid yet.
|
9 |
*/
|
10 |
const STATUS_OPEN = "open";
|
|
|
11 |
/**
|
12 |
* The invoice is paid.
|
13 |
*/
|
14 |
const STATUS_PAID = "paid";
|
|
|
15 |
/**
|
16 |
* Payment of the invoice is overdue.
|
17 |
*/
|
18 |
const STATUS_OVERDUE = "overdue";
|
19 |
-
}
|
8 |
* The invoice is not paid yet.
|
9 |
*/
|
10 |
const STATUS_OPEN = "open";
|
11 |
+
|
12 |
/**
|
13 |
* The invoice is paid.
|
14 |
*/
|
15 |
const STATUS_PAID = "paid";
|
16 |
+
|
17 |
/**
|
18 |
* Payment of the invoice is overdue.
|
19 |
*/
|
20 |
const STATUS_OVERDUE = "overdue";
|
21 |
+
}
|
@@ -5,4 +5,4 @@ namespace Mollie\Api\Types;
|
|
5 |
class MandateMethod
|
6 |
{
|
7 |
const DIRECTDEBIT = "directdebit";
|
8 |
-
}
|
5 |
class MandateMethod
|
6 |
{
|
7 |
const DIRECTDEBIT = "directdebit";
|
8 |
+
}
|
@@ -5,6 +5,6 @@ namespace Mollie\Api\Types;
|
|
5 |
class MandateStatus
|
6 |
{
|
7 |
const STATUS_PENDING = "pending";
|
8 |
-
const STATUS_VALID
|
9 |
const STATUS_INVALID = "invalid";
|
10 |
-
}
|
5 |
class MandateStatus
|
6 |
{
|
7 |
const STATUS_PENDING = "pending";
|
8 |
+
const STATUS_VALID = "valid";
|
9 |
const STATUS_INVALID = "invalid";
|
10 |
+
}
|
@@ -8,26 +8,32 @@ class OrderLineStatus
|
|
8 |
* The order line has just been created.
|
9 |
*/
|
10 |
const STATUS_CREATED = "created";
|
|
|
11 |
/**
|
12 |
* The order line has been paid.
|
13 |
*/
|
14 |
const STATUS_PAID = "paid";
|
|
|
15 |
/**
|
16 |
* The order line has been authorized.
|
17 |
*/
|
18 |
const STATUS_AUTHORIZED = "authorized";
|
|
|
19 |
/**
|
20 |
* The order line has been canceled.
|
21 |
*/
|
22 |
const STATUS_CANCELED = "canceled";
|
|
|
23 |
/**
|
24 |
* The order line has been refunded.
|
25 |
*/
|
26 |
const STATUS_REFUNDED = "refunded";
|
|
|
27 |
/**
|
28 |
* The order line is shipping.
|
29 |
*/
|
30 |
const STATUS_SHIPPING = "shipping";
|
|
|
31 |
/**
|
32 |
* The order line is completed.
|
33 |
*/
|
8 |
* The order line has just been created.
|
9 |
*/
|
10 |
const STATUS_CREATED = "created";
|
11 |
+
|
12 |
/**
|
13 |
* The order line has been paid.
|
14 |
*/
|
15 |
const STATUS_PAID = "paid";
|
16 |
+
|
17 |
/**
|
18 |
* The order line has been authorized.
|
19 |
*/
|
20 |
const STATUS_AUTHORIZED = "authorized";
|
21 |
+
|
22 |
/**
|
23 |
* The order line has been canceled.
|
24 |
*/
|
25 |
const STATUS_CANCELED = "canceled";
|
26 |
+
|
27 |
/**
|
28 |
* The order line has been refunded.
|
29 |
*/
|
30 |
const STATUS_REFUNDED = "refunded";
|
31 |
+
|
32 |
/**
|
33 |
* The order line is shipping.
|
34 |
*/
|
35 |
const STATUS_SHIPPING = "shipping";
|
36 |
+
|
37 |
/**
|
38 |
* The order line is completed.
|
39 |
*/
|
@@ -8,30 +8,37 @@ class OrderStatus
|
|
8 |
* The order has just been created.
|
9 |
*/
|
10 |
const STATUS_CREATED = "created";
|
|
|
11 |
/**
|
12 |
* The order has been paid.
|
13 |
*/
|
14 |
const STATUS_PAID = "paid";
|
|
|
15 |
/**
|
16 |
* The order has been authorized.
|
17 |
*/
|
18 |
const STATUS_AUTHORIZED = "authorized";
|
|
|
19 |
/**
|
20 |
* The order has been canceled.
|
21 |
*/
|
22 |
const STATUS_CANCELED = "canceled";
|
|
|
23 |
/**
|
24 |
* The order has been refunded.
|
25 |
*/
|
26 |
const STATUS_REFUNDED = "refunded";
|
|
|
27 |
/**
|
28 |
* The order is shipping.
|
29 |
*/
|
30 |
const STATUS_SHIPPING = "shipping";
|
|
|
31 |
/**
|
32 |
* The order is completed.
|
33 |
*/
|
34 |
const STATUS_COMPLETED = "completed";
|
|
|
35 |
/**
|
36 |
* The order is expired.
|
37 |
*/
|
8 |
* The order has just been created.
|
9 |
*/
|
10 |
const STATUS_CREATED = "created";
|
11 |
+
|
12 |
/**
|
13 |
* The order has been paid.
|
14 |
*/
|
15 |
const STATUS_PAID = "paid";
|
16 |
+
|
17 |
/**
|
18 |
* The order has been authorized.
|
19 |
*/
|
20 |
const STATUS_AUTHORIZED = "authorized";
|
21 |
+
|
22 |
/**
|
23 |
* The order has been canceled.
|
24 |
*/
|
25 |
const STATUS_CANCELED = "canceled";
|
26 |
+
|
27 |
/**
|
28 |
* The order has been refunded.
|
29 |
*/
|
30 |
const STATUS_REFUNDED = "refunded";
|
31 |
+
|
32 |
/**
|
33 |
* The order is shipping.
|
34 |
*/
|
35 |
const STATUS_SHIPPING = "shipping";
|
36 |
+
|
37 |
/**
|
38 |
* The order is completed.
|
39 |
*/
|
40 |
const STATUS_COMPLETED = "completed";
|
41 |
+
|
42 |
/**
|
43 |
* The order is expired.
|
44 |
*/
|
@@ -8,71 +8,88 @@ class PaymentMethod
|
|
8 |
* @link https://www.mollie.com/en/payments/bancontact
|
9 |
*/
|
10 |
const BANCONTACT = "bancontact";
|
|
|
11 |
/**
|
12 |
* @link https://www.mollie.com/en/payments/bank-transfer
|
13 |
*/
|
14 |
const BANKTRANSFER = "banktransfer";
|
|
|
15 |
/**
|
16 |
* @link https://www.mollie.com/en/payments/belfius
|
17 |
*/
|
18 |
const BELFIUS = "belfius";
|
|
|
19 |
/**
|
20 |
* @link https://www.mollie.com/en/payments/bitcoin
|
21 |
*/
|
22 |
const BITCOIN = "bitcoin";
|
|
|
23 |
/**
|
24 |
* @link https://www.mollie.com/en/payments/credit-card
|
25 |
*/
|
26 |
const CREDITCARD = "creditcard";
|
|
|
27 |
/**
|
28 |
* @link https://www.mollie.com/en/payments/direct-debit
|
29 |
*/
|
30 |
const DIRECTDEBIT = "directdebit";
|
|
|
31 |
/**
|
32 |
* @link https://www.mollie.com/en/payments/eps
|
33 |
*/
|
34 |
const EPS = "eps";
|
|
|
35 |
/**
|
36 |
* @link https://www.mollie.com/en/payments/gift-cards
|
37 |
*/
|
38 |
const GIFTCARD = "giftcard";
|
|
|
39 |
/**
|
40 |
* @link https://www.mollie.com/en/payments/giropay
|
41 |
*/
|
42 |
const GIROPAY = "giropay";
|
|
|
43 |
/**
|
44 |
* @link https://www.mollie.com/en/payments/ideal
|
45 |
*/
|
46 |
const IDEAL = "ideal";
|
|
|
47 |
/**
|
48 |
* @link https://www.mollie.com/en/payments/ing-homepay
|
49 |
*/
|
50 |
const INGHOMEPAY = "inghomepay";
|
|
|
51 |
/**
|
52 |
* @link https://www.mollie.com/en/payments/kbc-cbc
|
53 |
*/
|
54 |
const KBC = "kbc";
|
|
|
55 |
/**
|
56 |
* @link https://www.mollie.com/en/payments/paypal
|
57 |
*/
|
58 |
const PAYPAL = "paypal";
|
|
|
59 |
/**
|
60 |
* @link https://www.mollie.com/en/payments/paysafecard
|
61 |
*/
|
62 |
const PAYSAFECARD = "paysafecard";
|
|
|
63 |
/**
|
64 |
* @deprecated
|
65 |
* @link https://www.mollie.com/en/payments/gift-cards
|
66 |
*/
|
67 |
const PODIUMCADEAUKAART = "podiumcadeaukaart";
|
|
|
68 |
/**
|
69 |
* @link https://www.mollie.com/en/payments/sofort
|
70 |
*/
|
71 |
const SOFORT = "sofort";
|
|
|
72 |
/**
|
73 |
* @link https://www.mollie.com/en/payments/klarna
|
74 |
*/
|
75 |
const KLARNA_PAY_LATER = "klarnapaylater";
|
|
|
76 |
/**
|
77 |
* @link https://www.mollie.com/en/payments/klarna
|
78 |
*/
|
8 |
* @link https://www.mollie.com/en/payments/bancontact
|
9 |
*/
|
10 |
const BANCONTACT = "bancontact";
|
11 |
+
|
12 |
/**
|
13 |
* @link https://www.mollie.com/en/payments/bank-transfer
|
14 |
*/
|
15 |
const BANKTRANSFER = "banktransfer";
|
16 |
+
|
17 |
/**
|
18 |
* @link https://www.mollie.com/en/payments/belfius
|
19 |
*/
|
20 |
const BELFIUS = "belfius";
|
21 |
+
|
22 |
/**
|
23 |
* @link https://www.mollie.com/en/payments/bitcoin
|
24 |
*/
|
25 |
const BITCOIN = "bitcoin";
|
26 |
+
|
27 |
/**
|
28 |
* @link https://www.mollie.com/en/payments/credit-card
|
29 |
*/
|
30 |
const CREDITCARD = "creditcard";
|
31 |
+
|
32 |
/**
|
33 |
* @link https://www.mollie.com/en/payments/direct-debit
|
34 |
*/
|
35 |
const DIRECTDEBIT = "directdebit";
|
36 |
+
|
37 |
/**
|
38 |
* @link https://www.mollie.com/en/payments/eps
|
39 |
*/
|
40 |
const EPS = "eps";
|
41 |
+
|
42 |
/**
|
43 |
* @link https://www.mollie.com/en/payments/gift-cards
|
44 |
*/
|
45 |
const GIFTCARD = "giftcard";
|
46 |
+
|
47 |
/**
|
48 |
* @link https://www.mollie.com/en/payments/giropay
|
49 |
*/
|
50 |
const GIROPAY = "giropay";
|
51 |
+
|
52 |
/**
|
53 |
* @link https://www.mollie.com/en/payments/ideal
|
54 |
*/
|
55 |
const IDEAL = "ideal";
|
56 |
+
|
57 |
/**
|
58 |
* @link https://www.mollie.com/en/payments/ing-homepay
|
59 |
*/
|
60 |
const INGHOMEPAY = "inghomepay";
|
61 |
+
|
62 |
/**
|
63 |
* @link https://www.mollie.com/en/payments/kbc-cbc
|
64 |
*/
|
65 |
const KBC = "kbc";
|
66 |
+
|
67 |
/**
|
68 |
* @link https://www.mollie.com/en/payments/paypal
|
69 |
*/
|
70 |
const PAYPAL = "paypal";
|
71 |
+
|
72 |
/**
|
73 |
* @link https://www.mollie.com/en/payments/paysafecard
|
74 |
*/
|
75 |
const PAYSAFECARD = "paysafecard";
|
76 |
+
|
77 |
/**
|
78 |
* @deprecated
|
79 |
* @link https://www.mollie.com/en/payments/gift-cards
|
80 |
*/
|
81 |
const PODIUMCADEAUKAART = "podiumcadeaukaart";
|
82 |
+
|
83 |
/**
|
84 |
* @link https://www.mollie.com/en/payments/sofort
|
85 |
*/
|
86 |
const SOFORT = "sofort";
|
87 |
+
|
88 |
/**
|
89 |
* @link https://www.mollie.com/en/payments/klarna
|
90 |
*/
|
91 |
const KLARNA_PAY_LATER = "klarnapaylater";
|
92 |
+
|
93 |
/**
|
94 |
* @link https://www.mollie.com/en/payments/klarna
|
95 |
*/
|
@@ -8,10 +8,12 @@ class PaymentStatus
|
|
8 |
* The payment has just been created, no action has happened on it yet.
|
9 |
*/
|
10 |
const STATUS_OPEN = "open";
|
|
|
11 |
/**
|
12 |
* The payment has just been started, no final confirmation yet.
|
13 |
*/
|
14 |
const STATUS_PENDING = "pending";
|
|
|
15 |
/**
|
16 |
* The payment is authorized, but captures still need to be created in order to receive the money.
|
17 |
*
|
@@ -21,18 +23,22 @@ class PaymentStatus
|
|
21 |
* @see https://docs.mollie.com/reference/v2/shipments-api/create-shipment
|
22 |
*/
|
23 |
const STATUS_AUTHORIZED = "authorized";
|
|
|
24 |
/**
|
25 |
* The customer has canceled the payment.
|
26 |
*/
|
27 |
const STATUS_CANCELED = "canceled";
|
|
|
28 |
/**
|
29 |
* The payment has expired due to inaction of the customer.
|
30 |
*/
|
31 |
const STATUS_EXPIRED = "expired";
|
|
|
32 |
/**
|
33 |
* The payment has been paid.
|
34 |
*/
|
35 |
const STATUS_PAID = "paid";
|
|
|
36 |
/**
|
37 |
* The payment has failed.
|
38 |
*/
|
8 |
* The payment has just been created, no action has happened on it yet.
|
9 |
*/
|
10 |
const STATUS_OPEN = "open";
|
11 |
+
|
12 |
/**
|
13 |
* The payment has just been started, no final confirmation yet.
|
14 |
*/
|
15 |
const STATUS_PENDING = "pending";
|
16 |
+
|
17 |
/**
|
18 |
* The payment is authorized, but captures still need to be created in order to receive the money.
|
19 |
*
|
23 |
* @see https://docs.mollie.com/reference/v2/shipments-api/create-shipment
|
24 |
*/
|
25 |
const STATUS_AUTHORIZED = "authorized";
|
26 |
+
|
27 |
/**
|
28 |
* The customer has canceled the payment.
|
29 |
*/
|
30 |
const STATUS_CANCELED = "canceled";
|
31 |
+
|
32 |
/**
|
33 |
* The payment has expired due to inaction of the customer.
|
34 |
*/
|
35 |
const STATUS_EXPIRED = "expired";
|
36 |
+
|
37 |
/**
|
38 |
* The payment has been paid.
|
39 |
*/
|
40 |
const STATUS_PAID = "paid";
|
41 |
+
|
42 |
/**
|
43 |
* The payment has failed.
|
44 |
*/
|
@@ -8,12 +8,14 @@ class ProfileStatus
|
|
8 |
* The profile has not been verified yet and can only be used to create test payments.
|
9 |
*/
|
10 |
const STATUS_UNVERIFIED = 'unverified';
|
|
|
11 |
/**
|
12 |
* The profile has been verified and can be used to create live payments and test payments.
|
13 |
*/
|
14 |
const STATUS_VERIFIED = 'verified';
|
|
|
15 |
/**
|
16 |
* The profile is blocked and can thus no longer be used or changed.
|
17 |
*/
|
18 |
const STATUS_BLOCKED = 'blocked';
|
19 |
-
}
|
8 |
* The profile has not been verified yet and can only be used to create test payments.
|
9 |
*/
|
10 |
const STATUS_UNVERIFIED = 'unverified';
|
11 |
+
|
12 |
/**
|
13 |
* The profile has been verified and can be used to create live payments and test payments.
|
14 |
*/
|
15 |
const STATUS_VERIFIED = 'verified';
|
16 |
+
|
17 |
/**
|
18 |
* The profile is blocked and can thus no longer be used or changed.
|
19 |
*/
|
20 |
const STATUS_BLOCKED = 'blocked';
|
21 |
+
}
|
@@ -8,14 +8,17 @@ class RefundStatus
|
|
8 |
* The refund is queued until there is enough balance to process te refund. You can still cancel the refund.
|
9 |
*/
|
10 |
const STATUS_QUEUED = 'queued';
|
|
|
11 |
/**
|
12 |
* The refund will be sent to the bank on the next business day. You can still cancel the refund.
|
13 |
*/
|
14 |
const STATUS_PENDING = 'pending';
|
|
|
15 |
/**
|
16 |
* The refund has been sent to the bank. The refund amount will be transferred to the consumer account as soon as possible.
|
17 |
*/
|
18 |
const STATUS_PROCESSING = 'processing';
|
|
|
19 |
/**
|
20 |
* The refund amount has been transferred to the consumer.
|
21 |
*/
|
8 |
* The refund is queued until there is enough balance to process te refund. You can still cancel the refund.
|
9 |
*/
|
10 |
const STATUS_QUEUED = 'queued';
|
11 |
+
|
12 |
/**
|
13 |
* The refund will be sent to the bank on the next business day. You can still cancel the refund.
|
14 |
*/
|
15 |
const STATUS_PENDING = 'pending';
|
16 |
+
|
17 |
/**
|
18 |
* The refund has been sent to the bank. The refund amount will be transferred to the consumer account as soon as possible.
|
19 |
*/
|
20 |
const STATUS_PROCESSING = 'processing';
|
21 |
+
|
22 |
/**
|
23 |
* The refund amount has been transferred to the consumer.
|
24 |
*/
|
@@ -8,14 +8,17 @@ class SettlementStatus
|
|
8 |
* The settlement has not been closed yet.
|
9 |
*/
|
10 |
const STATUS_OPEN = 'open';
|
|
|
11 |
/**
|
12 |
* The settlement has been closed and is being processed.
|
13 |
*/
|
14 |
const STATUS_PENDING = 'pending';
|
|
|
15 |
/**
|
16 |
* The settlement has been paid out.
|
17 |
*/
|
18 |
const STATUS_PAIDOUT = 'paidout';
|
|
|
19 |
/**
|
20 |
* The settlement could not be paid out.
|
21 |
*/
|
8 |
* The settlement has not been closed yet.
|
9 |
*/
|
10 |
const STATUS_OPEN = 'open';
|
11 |
+
|
12 |
/**
|
13 |
* The settlement has been closed and is being processed.
|
14 |
*/
|
15 |
const STATUS_PENDING = 'pending';
|
16 |
+
|
17 |
/**
|
18 |
* The settlement has been paid out.
|
19 |
*/
|
20 |
const STATUS_PAIDOUT = 'paidout';
|
21 |
+
|
22 |
/**
|
23 |
* The settlement could not be paid out.
|
24 |
*/
|
@@ -4,11 +4,9 @@ namespace Mollie\Api\Types;
|
|
4 |
|
5 |
class SubscriptionStatus
|
6 |
{
|
7 |
-
const STATUS_ACTIVE
|
8 |
-
const STATUS_PENDING
|
9 |
-
|
10 |
-
const
|
11 |
-
const STATUS_SUSPENDED = "suspended";
|
12 |
-
// Active, but mandate became invalid.
|
13 |
const STATUS_COMPLETED = "completed";
|
14 |
-
}
|
4 |
|
5 |
class SubscriptionStatus
|
6 |
{
|
7 |
+
const STATUS_ACTIVE = "active";
|
8 |
+
const STATUS_PENDING = "pending"; // Waiting for a valid mandate.
|
9 |
+
const STATUS_CANCELED = "canceled";
|
10 |
+
const STATUS_SUSPENDED = "suspended"; // Active, but mandate became invalid.
|
|
|
|
|
11 |
const STATUS_COMPLETED = "completed";
|
12 |
+
}
|
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInitc9ac1131b10cd7a0dbf25c3dce68c45d::getLoader();
|
@@ -1,7 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload.php @generated by Composer
|
4 |
-
|
5 |
-
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
-
|
7 |
-
return ComposerAutoloaderInita3126e82b6f8a8825a16880fe8b70058::getLoader();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -6,10 +6,10 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
-
'
|
10 |
-
'_PhpScoper5bbb1f4b001f3\\GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
11 |
-
'_PhpScoper5bbb1f4b001f3\\GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
12 |
-
'_PhpScoper5bbb1f4b001f3\\GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
13 |
-
'_PhpScoper5bbb1f4b001f3\\Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
|
14 |
'Mollie\\Api\\' => array($baseDir . '/src'),
|
|
|
|
|
|
|
|
|
15 |
);
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
+
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
|
|
|
|
|
|
|
|
10 |
'Mollie\\Api\\' => array($baseDir . '/src'),
|
11 |
+
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
12 |
+
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
13 |
+
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
14 |
+
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
|
15 |
);
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitc506fc7062188e972f0e524a810da0c2
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
-
call_user_func(\Composer\Autoload\
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
@@ -48,19 +48,19 @@ class ComposerAutoloaderInitc506fc7062188e972f0e524a810da0c2
|
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
-
$includeFiles = Composer\Autoload\
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
-
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
-
function
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInitc9ac1131b10cd7a0dbf25c3dce68c45d
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInitc9ac1131b10cd7a0dbf25c3dce68c45d', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInitc9ac1131b10cd7a0dbf25c3dce68c45d', 'loadClassLoader'));
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInitc9ac1131b10cd7a0dbf25c3dce68c45d::getInitializer($loader));
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
+
$includeFiles = Composer\Autoload\ComposerStaticInitc9ac1131b10cd7a0dbf25c3dce68c45d::$files;
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
+
composerRequirec9ac1131b10cd7a0dbf25c3dce68c45d($fileIdentifier, $file);
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
+
function composerRequirec9ac1131b10cd7a0dbf25c3dce68c45d($fileIdentifier, $file)
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
@@ -13,52 +13,58 @@ class ComposerStaticInitc506fc7062188e972f0e524a810da0c2
|
|
13 |
);
|
14 |
|
15 |
public static $prefixLengthsPsr4 = array (
|
16 |
-
'
|
17 |
array (
|
18 |
-
'
|
19 |
-
'_PhpScoper5bbb1f4b001f3\\GuzzleHttp\\Psr7\\' => 40,
|
20 |
-
'_PhpScoper5bbb1f4b001f3\\GuzzleHttp\\Promise\\' => 43,
|
21 |
-
'_PhpScoper5bbb1f4b001f3\\GuzzleHttp\\' => 35,
|
22 |
-
'_PhpScoper5bbb1f4b001f3\\Composer\\CaBundle\\' => 42,
|
23 |
),
|
24 |
'M' =>
|
25 |
array (
|
26 |
'Mollie\\Api\\' => 11,
|
27 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
);
|
29 |
|
30 |
public static $prefixDirsPsr4 = array (
|
31 |
-
'
|
32 |
array (
|
33 |
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
34 |
),
|
35 |
-
'
|
|
|
|
|
|
|
|
|
36 |
array (
|
37 |
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
38 |
),
|
39 |
-
'
|
40 |
array (
|
41 |
0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
|
42 |
),
|
43 |
-
'
|
44 |
array (
|
45 |
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
46 |
),
|
47 |
-
'
|
48 |
array (
|
49 |
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
|
50 |
),
|
51 |
-
'Mollie\\Api\\' =>
|
52 |
-
array (
|
53 |
-
0 => __DIR__ . '/../..' . '/src',
|
54 |
-
),
|
55 |
);
|
56 |
|
57 |
public static function getInitializer(ClassLoader $loader)
|
58 |
{
|
59 |
return \Closure::bind(function () use ($loader) {
|
60 |
-
$loader->prefixLengthsPsr4 =
|
61 |
-
$loader->prefixDirsPsr4 =
|
62 |
|
63 |
}, null, ClassLoader::class);
|
64 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInitc9ac1131b10cd7a0dbf25c3dce68c45d
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
13 |
);
|
14 |
|
15 |
public static $prefixLengthsPsr4 = array (
|
16 |
+
'P' =>
|
17 |
array (
|
18 |
+
'Psr\\Http\\Message\\' => 17,
|
|
|
|
|
|
|
|
|
19 |
),
|
20 |
'M' =>
|
21 |
array (
|
22 |
'Mollie\\Api\\' => 11,
|
23 |
),
|
24 |
+
'G' =>
|
25 |
+
array (
|
26 |
+
'GuzzleHttp\\Psr7\\' => 16,
|
27 |
+
'GuzzleHttp\\Promise\\' => 19,
|
28 |
+
'GuzzleHttp\\' => 11,
|
29 |
+
),
|
30 |
+
'C' =>
|
31 |
+
array (
|
32 |
+
'Composer\\CaBundle\\' => 18,
|
33 |
+
),
|
34 |
);
|
35 |
|
36 |
public static $prefixDirsPsr4 = array (
|
37 |
+
'Psr\\Http\\Message\\' =>
|
38 |
array (
|
39 |
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
40 |
),
|
41 |
+
'Mollie\\Api\\' =>
|
42 |
+
array (
|
43 |
+
0 => __DIR__ . '/../..' . '/src',
|
44 |
+
),
|
45 |
+
'GuzzleHttp\\Psr7\\' =>
|
46 |
array (
|
47 |
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
48 |
),
|
49 |
+
'GuzzleHttp\\Promise\\' =>
|
50 |
array (
|
51 |
0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
|
52 |
),
|
53 |
+
'GuzzleHttp\\' =>
|
54 |
array (
|
55 |
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
56 |
),
|
57 |
+
'Composer\\CaBundle\\' =>
|
58 |
array (
|
59 |
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
|
60 |
),
|
|
|
|
|
|
|
|
|
61 |
);
|
62 |
|
63 |
public static function getInitializer(ClassLoader $loader)
|
64 |
{
|
65 |
return \Closure::bind(function () use ($loader) {
|
66 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInitc9ac1131b10cd7a0dbf25c3dce68c45d::$prefixLengthsPsr4;
|
67 |
+
$loader->prefixDirsPsr4 = ComposerStaticInitc9ac1131b10cd7a0dbf25c3dce68c45d::$prefixDirsPsr4;
|
68 |
|
69 |
}, null, ClassLoader::class);
|
70 |
}
|
@@ -1,5 +1,5 @@
|
|
1 |
{
|
2 |
-
"name": "composer
|
3 |
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
|
4 |
"type": "library",
|
5 |
"license": "MIT",
|
@@ -14,12 +14,12 @@
|
|
14 |
{
|
15 |
"name": "Jordi Boggiano",
|
16 |
"email": "j.boggiano@seld.be",
|
17 |
-
"homepage": "http
|
18 |
}
|
19 |
],
|
20 |
"support": {
|
21 |
-
"irc": "irc
|
22 |
-
"issues": "https
|
23 |
},
|
24 |
"require": {
|
25 |
"ext-openssl": "*",
|
@@ -27,18 +27,18 @@
|
|
27 |
"php": "^5.3.2 || ^7.0"
|
28 |
},
|
29 |
"require-dev": {
|
30 |
-
"phpunit
|
31 |
-
"psr
|
32 |
-
"symfony
|
33 |
},
|
34 |
"autoload": {
|
35 |
"psr-4": {
|
36 |
-
"
|
37 |
}
|
38 |
},
|
39 |
"autoload-dev": {
|
40 |
"psr-4": {
|
41 |
-
"
|
42 |
}
|
43 |
},
|
44 |
"extra": {
|
@@ -51,4 +51,4 @@
|
|
51 |
"php": "5.3.9"
|
52 |
}
|
53 |
}
|
54 |
-
}
|
1 |
{
|
2 |
+
"name": "composer/ca-bundle",
|
3 |
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
|
4 |
"type": "library",
|
5 |
"license": "MIT",
|
14 |
{
|
15 |
"name": "Jordi Boggiano",
|
16 |
"email": "j.boggiano@seld.be",
|
17 |
+
"homepage": "http://seld.be"
|
18 |
}
|
19 |
],
|
20 |
"support": {
|
21 |
+
"irc": "irc://irc.freenode.org/composer",
|
22 |
+
"issues": "https://github.com/composer/ca-bundle/issues"
|
23 |
},
|
24 |
"require": {
|
25 |
"ext-openssl": "*",
|
27 |
"php": "^5.3.2 || ^7.0"
|
28 |
},
|
29 |
"require-dev": {
|
30 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
31 |
+
"psr/log": "^1.0",
|
32 |
+
"symfony/process": "^2.5 || ^3.0 || ^4.0"
|
33 |
},
|
34 |
"autoload": {
|
35 |
"psr-4": {
|
36 |
+
"Composer\\CaBundle\\": "src"
|
37 |
}
|
38 |
},
|
39 |
"autoload-dev": {
|
40 |
"psr-4": {
|
41 |
+
"Composer\\CaBundle\\": "tests"
|
42 |
}
|
43 |
},
|
44 |
"extra": {
|
51 |
"php": "5.3.9"
|
52 |
}
|
53 |
}
|
54 |
+
}
|
@@ -8,10 +8,12 @@
|
|
8 |
* For the full copyright and license information, please view
|
9 |
* the LICENSE file that was distributed with this source code.
|
10 |
*/
|
11 |
-
namespace _PhpScoper5bbb1f4b001f3\Composer\CaBundle;
|
12 |
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
15 |
/**
|
16 |
* @author Chris Smith <chris@cs278.org>
|
17 |
* @author Jordi Boggiano <j.boggiano@seld.be>
|
@@ -21,6 +23,7 @@ class CaBundle
|
|
21 |
private static $caPath;
|
22 |
private static $caFileValidity = array();
|
23 |
private static $useOpensslParse;
|
|
|
24 |
/**
|
25 |
* Returns the system CA bundle path, or a path to the bundled one
|
26 |
*
|
@@ -58,68 +61,66 @@ class CaBundle
|
|
58 |
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
59 |
* @return string path to a CA bundle file or directory
|
60 |
*/
|
61 |
-
public static function getSystemCaRootBundlePath(
|
62 |
{
|
63 |
if (self::$caPath !== null) {
|
64 |
return self::$caPath;
|
65 |
}
|
|
|
66 |
// If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
|
67 |
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
68 |
-
$envCertFile =
|
69 |
-
if ($envCertFile &&
|
70 |
return self::$caPath = $envCertFile;
|
71 |
}
|
|
|
72 |
// If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
|
73 |
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
74 |
-
$envCertDir =
|
75 |
-
if ($envCertDir &&
|
76 |
return self::$caPath = $envCertDir;
|
77 |
}
|
78 |
-
|
79 |
-
|
|
|
80 |
return self::$caPath = $configured;
|
81 |
}
|
82 |
-
|
83 |
-
|
|
|
84 |
return self::$caPath = $configured;
|
85 |
}
|
|
|
86 |
$caBundlePaths = array(
|
87 |
-
'/etc/pki/tls/certs/ca-bundle.crt',
|
88 |
-
//
|
89 |
-
'/etc/ssl/
|
90 |
-
|
91 |
-
'/
|
92 |
-
//
|
93 |
-
'/usr/local/share/
|
94 |
-
//
|
95 |
-
'/
|
96 |
-
//
|
97 |
-
'/
|
98 |
-
// OS X macports, curl-ca-bundle package
|
99 |
-
'/usr/local/share/curl/curl-ca-bundle.crt',
|
100 |
-
// Default cURL CA bunde path (without --with-ca-bundle option)
|
101 |
-
'/usr/share/ssl/certs/ca-bundle.crt',
|
102 |
-
// Really old RedHat?
|
103 |
-
'/etc/ssl/cert.pem',
|
104 |
-
// OpenBSD
|
105 |
-
'/usr/local/etc/ssl/cert.pem',
|
106 |
-
// FreeBSD 10.x
|
107 |
-
'/usr/local/etc/openssl/cert.pem',
|
108 |
);
|
|
|
109 |
foreach ($caBundlePaths as $caBundle) {
|
110 |
-
if (
|
111 |
return self::$caPath = $caBundle;
|
112 |
}
|
113 |
}
|
|
|
114 |
foreach ($caBundlePaths as $caBundle) {
|
115 |
-
$caBundle =
|
116 |
-
if (
|
117 |
return self::$caPath = $caBundle;
|
118 |
}
|
119 |
}
|
120 |
-
|
121 |
-
// Bundled CA file, last resort
|
122 |
}
|
|
|
123 |
/**
|
124 |
* Returns the path to the bundled CA file
|
125 |
*
|
@@ -129,18 +130,26 @@ class CaBundle
|
|
129 |
*/
|
130 |
public static function getBundledCaBundlePath()
|
131 |
{
|
132 |
-
$caBundleFile = __DIR__
|
|
|
133 |
// cURL does not understand 'phar://' paths
|
134 |
// see https://github.com/composer/ca-bundle/issues/10
|
135 |
-
if (0 ===
|
136 |
-
|
137 |
-
|
138 |
-
|
|
|
|
|
|
|
|
|
139 |
});
|
|
|
140 |
$caBundleFile = $tempCaBundleFile;
|
141 |
}
|
|
|
142 |
return $caBundleFile;
|
143 |
}
|
|
|
144 |
/**
|
145 |
* Validates a CA file using opensl_x509_parse only if it is safe to use
|
146 |
*
|
@@ -149,29 +158,39 @@ class CaBundle
|
|
149 |
*
|
150 |
* @return bool
|
151 |
*/
|
152 |
-
public static function validateCaFile($filename,
|
153 |
{
|
154 |
-
static $warned =
|
|
|
155 |
if (isset(self::$caFileValidity[$filename])) {
|
156 |
return self::$caFileValidity[$filename];
|
157 |
}
|
158 |
-
|
|
|
|
|
159 |
// assume the CA is valid if php is vulnerable to
|
160 |
// https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
|
161 |
if (!static::isOpensslParseSafe()) {
|
162 |
if (!$warned && $logger) {
|
163 |
-
$logger->warning(
|
164 |
-
|
|
|
|
|
|
|
165 |
}
|
|
|
166 |
$isValid = !empty($contents);
|
167 |
} else {
|
168 |
-
$isValid = (bool)
|
169 |
}
|
|
|
170 |
if ($logger) {
|
171 |
-
$logger->debug('Checked CA file '
|
172 |
}
|
|
|
173 |
return self::$caFileValidity[$filename] = $isValid;
|
174 |
}
|
|
|
175 |
/**
|
176 |
* Test if it is safe to use the PHP function openssl_x509_parse().
|
177 |
*
|
@@ -185,42 +204,60 @@ class CaBundle
|
|
185 |
if (null !== self::$useOpensslParse) {
|
186 |
return self::$useOpensslParse;
|
187 |
}
|
188 |
-
|
189 |
-
|
|
|
190 |
}
|
|
|
191 |
// Vulnerable:
|
192 |
// PHP 5.3.0 - PHP 5.3.27
|
193 |
// PHP 5.4.0 - PHP 5.4.22
|
194 |
// PHP 5.5.0 - PHP 5.5.6
|
195 |
-
if (
|
|
|
|
|
|
|
|
|
196 |
// This version of PHP has the fix for CVE-2013-6420 applied.
|
197 |
-
return self::$useOpensslParse =
|
198 |
}
|
199 |
-
|
|
|
200 |
// Windows is probably insecure in this case.
|
201 |
-
return self::$useOpensslParse =
|
202 |
}
|
|
|
203 |
$compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
|
204 |
-
$regex = '{^'
|
205 |
-
|
206 |
-
|
|
|
207 |
}
|
208 |
-
|
|
|
209 |
};
|
|
|
210 |
// Hard coded list of PHP distributions with the fix backported.
|
211 |
-
if (
|
212 |
-
|
|
|
|
|
|
|
|
|
213 |
}
|
|
|
214 |
// Symfony Process component is missing so we assume it is unsafe at this point
|
215 |
-
if (
|
216 |
-
return self::$useOpensslParse =
|
217 |
}
|
|
|
218 |
// This is where things get crazy, because distros backport security
|
219 |
// fixes the chances are on NIX systems the fix has been applied but
|
220 |
// it's not possible to verify that from the PHP version.
|
221 |
//
|
222 |
// To verify exec a new PHP process and run the issue testcase with
|
223 |
// known safe input that replicates the bug.
|
|
|
224 |
// Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
|
225 |
// changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
|
226 |
$cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
|
@@ -231,23 +268,34 @@ $info = openssl_x509_parse(base64_decode('%s'));
|
|
231 |
var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
|
232 |
|
233 |
EOT;
|
234 |
-
$script = '<'
|
|
|
235 |
try {
|
236 |
-
$process = new
|
237 |
$process->mustRun();
|
238 |
} catch (\Exception $e) {
|
239 |
// In the case of any exceptions just accept it is not possible to
|
240 |
// determine the safety of openssl_x509_parse and bail out.
|
241 |
-
return self::$useOpensslParse =
|
242 |
}
|
243 |
-
|
244 |
-
$
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
// This PHP has the fix backported probably by a distro security team.
|
247 |
-
return self::$useOpensslParse =
|
248 |
}
|
249 |
-
|
|
|
250 |
}
|
|
|
251 |
/**
|
252 |
* Resets the static caches
|
253 |
*/
|
8 |
* For the full copyright and license information, please view
|
9 |
* the LICENSE file that was distributed with this source code.
|
10 |
*/
|
|
|
11 |
|
12 |
+
namespace Composer\CaBundle;
|
13 |
+
|
14 |
+
use Psr\Log\LoggerInterface;
|
15 |
+
use Symfony\Component\Process\PhpProcess;
|
16 |
+
|
17 |
/**
|
18 |
* @author Chris Smith <chris@cs278.org>
|
19 |
* @author Jordi Boggiano <j.boggiano@seld.be>
|
23 |
private static $caPath;
|
24 |
private static $caFileValidity = array();
|
25 |
private static $useOpensslParse;
|
26 |
+
|
27 |
/**
|
28 |
* Returns the system CA bundle path, or a path to the bundled one
|
29 |
*
|
61 |
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
|
62 |
* @return string path to a CA bundle file or directory
|
63 |
*/
|
64 |
+
public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
|
65 |
{
|
66 |
if (self::$caPath !== null) {
|
67 |
return self::$caPath;
|
68 |
}
|
69 |
+
|
70 |
// If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
|
71 |
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
72 |
+
$envCertFile = getenv('SSL_CERT_FILE');
|
73 |
+
if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
|
74 |
return self::$caPath = $envCertFile;
|
75 |
}
|
76 |
+
|
77 |
// If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
|
78 |
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
|
79 |
+
$envCertDir = getenv('SSL_CERT_DIR');
|
80 |
+
if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
|
81 |
return self::$caPath = $envCertDir;
|
82 |
}
|
83 |
+
|
84 |
+
$configured = ini_get('openssl.cafile');
|
85 |
+
if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
|
86 |
return self::$caPath = $configured;
|
87 |
}
|
88 |
+
|
89 |
+
$configured = ini_get('openssl.capath');
|
90 |
+
if ($configured && is_dir($configured) && is_readable($configured)) {
|
91 |
return self::$caPath = $configured;
|
92 |
}
|
93 |
+
|
94 |
$caBundlePaths = array(
|
95 |
+
'/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
|
96 |
+
'/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
|
97 |
+
'/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
|
98 |
+
'/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
|
99 |
+
'/usr/ssl/certs/ca-bundle.crt', // Cygwin
|
100 |
+
'/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
|
101 |
+
'/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
|
102 |
+
'/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
|
103 |
+
'/etc/ssl/cert.pem', // OpenBSD
|
104 |
+
'/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
|
105 |
+
'/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
);
|
107 |
+
|
108 |
foreach ($caBundlePaths as $caBundle) {
|
109 |
+
if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
|
110 |
return self::$caPath = $caBundle;
|
111 |
}
|
112 |
}
|
113 |
+
|
114 |
foreach ($caBundlePaths as $caBundle) {
|
115 |
+
$caBundle = dirname($caBundle);
|
116 |
+
if (@is_dir($caBundle) && glob($caBundle.'/*')) {
|
117 |
return self::$caPath = $caBundle;
|
118 |
}
|
119 |
}
|
120 |
+
|
121 |
+
return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
|
122 |
}
|
123 |
+
|
124 |
/**
|
125 |
* Returns the path to the bundled CA file
|
126 |
*
|
130 |
*/
|
131 |
public static function getBundledCaBundlePath()
|
132 |
{
|
133 |
+
$caBundleFile = __DIR__.'/../res/cacert.pem';
|
134 |
+
|
135 |
// cURL does not understand 'phar://' paths
|
136 |
// see https://github.com/composer/ca-bundle/issues/10
|
137 |
+
if (0 === strpos($caBundleFile, 'phar://')) {
|
138 |
+
file_put_contents(
|
139 |
+
$tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
|
140 |
+
file_get_contents($caBundleFile)
|
141 |
+
);
|
142 |
+
|
143 |
+
register_shutdown_function(function() use ($tempCaBundleFile) {
|
144 |
+
@unlink($tempCaBundleFile);
|
145 |
});
|
146 |
+
|
147 |
$caBundleFile = $tempCaBundleFile;
|
148 |
}
|
149 |
+
|
150 |
return $caBundleFile;
|
151 |
}
|
152 |
+
|
153 |
/**
|
154 |
* Validates a CA file using opensl_x509_parse only if it is safe to use
|
155 |
*
|
158 |
*
|
159 |
* @return bool
|
160 |
*/
|
161 |
+
public static function validateCaFile($filename, LoggerInterface $logger = null)
|
162 |
{
|
163 |
+
static $warned = false;
|
164 |
+
|
165 |
if (isset(self::$caFileValidity[$filename])) {
|
166 |
return self::$caFileValidity[$filename];
|
167 |
}
|
168 |
+
|
169 |
+
$contents = file_get_contents($filename);
|
170 |
+
|
171 |
// assume the CA is valid if php is vulnerable to
|
172 |
// https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
|
173 |
if (!static::isOpensslParseSafe()) {
|
174 |
if (!$warned && $logger) {
|
175 |
+
$logger->warning(sprintf(
|
176 |
+
'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
|
177 |
+
PHP_VERSION
|
178 |
+
));
|
179 |
+
$warned = true;
|
180 |
}
|
181 |
+
|
182 |
$isValid = !empty($contents);
|
183 |
} else {
|
184 |
+
$isValid = (bool) openssl_x509_parse($contents);
|
185 |
}
|
186 |
+
|
187 |
if ($logger) {
|
188 |
+
$logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
|
189 |
}
|
190 |
+
|
191 |
return self::$caFileValidity[$filename] = $isValid;
|
192 |
}
|
193 |
+
|
194 |
/**
|
195 |
* Test if it is safe to use the PHP function openssl_x509_parse().
|
196 |
*
|
204 |
if (null !== self::$useOpensslParse) {
|
205 |
return self::$useOpensslParse;
|
206 |
}
|
207 |
+
|
208 |
+
if (PHP_VERSION_ID >= 50600) {
|
209 |
+
return self::$useOpensslParse = true;
|
210 |
}
|
211 |
+
|
212 |
// Vulnerable:
|
213 |
// PHP 5.3.0 - PHP 5.3.27
|
214 |
// PHP 5.4.0 - PHP 5.4.22
|
215 |
// PHP 5.5.0 - PHP 5.5.6
|
216 |
+
if (
|
217 |
+
(PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
|
218 |
+
|| (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
|
219 |
+
|| (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
|
220 |
+
) {
|
221 |
// This version of PHP has the fix for CVE-2013-6420 applied.
|
222 |
+
return self::$useOpensslParse = true;
|
223 |
}
|
224 |
+
|
225 |
+
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
226 |
// Windows is probably insecure in this case.
|
227 |
+
return self::$useOpensslParse = false;
|
228 |
}
|
229 |
+
|
230 |
$compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
|
231 |
+
$regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
|
232 |
+
|
233 |
+
if (preg_match($regex, PHP_VERSION, $m)) {
|
234 |
+
return ((int) $m[1]) >= $fixedVersion;
|
235 |
}
|
236 |
+
|
237 |
+
return false;
|
238 |
};
|
239 |
+
|
240 |
// Hard coded list of PHP distributions with the fix backported.
|
241 |
+
if (
|
242 |
+
$compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
|
243 |
+
|| $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
|
244 |
+
|| $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
|
245 |
+
) {
|
246 |
+
return self::$useOpensslParse = true;
|
247 |
}
|
248 |
+
|
249 |
// Symfony Process component is missing so we assume it is unsafe at this point
|
250 |
+
if (!class_exists('Symfony\Component\Process\PhpProcess')) {
|
251 |
+
return self::$useOpensslParse = false;
|
252 |
}
|
253 |
+
|
254 |
// This is where things get crazy, because distros backport security
|
255 |
// fixes the chances are on NIX systems the fix has been applied but
|
256 |
// it's not possible to verify that from the PHP version.
|
257 |
//
|
258 |
// To verify exec a new PHP process and run the issue testcase with
|
259 |
// known safe input that replicates the bug.
|
260 |
+
|
261 |
// Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
|
262 |
// changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
|
263 |
$cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
|
268 |
var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
|
269 |
|
270 |
EOT;
|
271 |
+
$script = '<'."?php\n".sprintf($script, $cert);
|
272 |
+
|
273 |
try {
|
274 |
+
$process = new PhpProcess($script);
|
275 |
$process->mustRun();
|
276 |
} catch (\Exception $e) {
|
277 |
// In the case of any exceptions just accept it is not possible to
|
278 |
// determine the safety of openssl_x509_parse and bail out.
|
279 |
+
return self::$useOpensslParse = false;
|
280 |
}
|
281 |
+
|
282 |
+
$output = preg_split('{\r?\n}', trim($process->getOutput()));
|
283 |
+
$errorOutput = trim($process->getErrorOutput());
|
284 |
+
|
285 |
+
if (
|
286 |
+
count($output) === 3
|
287 |
+
&& $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
|
288 |
+
&& $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
|
289 |
+
&& $output[2] === 'int(-1)'
|
290 |
+
&& preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
|
291 |
+
) {
|
292 |
// This PHP has the fix backported probably by a distro security team.
|
293 |
+
return self::$useOpensslParse = true;
|
294 |
}
|
295 |
+
|
296 |
+
return self::$useOpensslParse = false;
|
297 |
}
|
298 |
+
|
299 |
/**
|
300 |
* Resets the static caches
|
301 |
*/
|
@@ -34,7 +34,7 @@
|
|
34 |
"installation-source": "dist",
|
35 |
"autoload": {
|
36 |
"psr-4": {
|
37 |
-
"
|
38 |
}
|
39 |
},
|
40 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -98,7 +98,7 @@
|
|
98 |
"src/functions_include.php"
|
99 |
],
|
100 |
"psr-4": {
|
101 |
-
"
|
102 |
}
|
103 |
},
|
104 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -155,7 +155,7 @@
|
|
155 |
"installation-source": "dist",
|
156 |
"autoload": {
|
157 |
"psr-4": {
|
158 |
-
"
|
159 |
},
|
160 |
"files": [
|
161 |
"src/functions_include.php"
|
@@ -212,7 +212,7 @@
|
|
212 |
"installation-source": "dist",
|
213 |
"autoload": {
|
214 |
"psr-4": {
|
215 |
-
"
|
216 |
},
|
217 |
"files": [
|
218 |
"src/functions_include.php"
|
@@ -272,7 +272,7 @@
|
|
272 |
"installation-source": "dist",
|
273 |
"autoload": {
|
274 |
"psr-4": {
|
275 |
-
"
|
276 |
}
|
277 |
},
|
278 |
"notification-url": "https://packagist.org/downloads/",
|
34 |
"installation-source": "dist",
|
35 |
"autoload": {
|
36 |
"psr-4": {
|
37 |
+
"Composer\\CaBundle\\": "src"
|
38 |
}
|
39 |
},
|
40 |
"notification-url": "https://packagist.org/downloads/",
|
98 |
"src/functions_include.php"
|
99 |
],
|
100 |
"psr-4": {
|
101 |
+
"GuzzleHttp\\": "src/"
|
102 |
}
|
103 |
},
|
104 |
"notification-url": "https://packagist.org/downloads/",
|
155 |
"installation-source": "dist",
|
156 |
"autoload": {
|
157 |
"psr-4": {
|
158 |
+
"GuzzleHttp\\Promise\\": "src/"
|
159 |
},
|
160 |
"files": [
|
161 |
"src/functions_include.php"
|
212 |
"installation-source": "dist",
|
213 |
"autoload": {
|
214 |
"psr-4": {
|
215 |
+
"GuzzleHttp\\Psr7\\": "src/"
|
216 |
},
|
217 |
"files": [
|
218 |
"src/functions_include.php"
|
272 |
"installation-source": "dist",
|
273 |
"autoload": {
|
274 |
"psr-4": {
|
275 |
+
"Psr\\Http\\Message\\": "src/"
|
276 |
}
|
277 |
},
|
278 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -1,54 +1,44 @@
|
|
1 |
{
|
2 |
-
"name": "guzzlehttp
|
3 |
"type": "library",
|
4 |
"description": "Guzzle is a PHP HTTP client library",
|
5 |
-
"keywords": [
|
6 |
-
|
7 |
-
"http",
|
8 |
-
"rest",
|
9 |
-
"web service",
|
10 |
-
"curl",
|
11 |
-
"client",
|
12 |
-
"HTTP client"
|
13 |
-
],
|
14 |
-
"homepage": "http:\/\/guzzlephp.org\/",
|
15 |
"license": "MIT",
|
16 |
"authors": [
|
17 |
{
|
18 |
"name": "Michael Dowling",
|
19 |
"email": "mtdowling@gmail.com",
|
20 |
-
"homepage": "https
|
21 |
}
|
22 |
],
|
23 |
"require": {
|
24 |
"php": ">=5.5",
|
25 |
-
"guzzlehttp
|
26 |
-
"guzzlehttp
|
27 |
},
|
28 |
"require-dev": {
|
29 |
"ext-curl": "*",
|
30 |
-
"phpunit
|
31 |
-
"psr
|
32 |
},
|
33 |
"autoload": {
|
34 |
-
"files": [
|
35 |
-
"src\/functions_include.php"
|
36 |
-
],
|
37 |
"psr-4": {
|
38 |
-
"
|
39 |
}
|
40 |
},
|
41 |
"autoload-dev": {
|
42 |
"psr-4": {
|
43 |
-
"
|
44 |
}
|
45 |
},
|
46 |
"suggest": {
|
47 |
-
"psr
|
48 |
},
|
49 |
"extra": {
|
50 |
"branch-alias": {
|
51 |
"dev-master": "6.3-dev"
|
52 |
}
|
53 |
}
|
54 |
-
}
|
1 |
{
|
2 |
+
"name": "guzzlehttp/guzzle",
|
3 |
"type": "library",
|
4 |
"description": "Guzzle is a PHP HTTP client library",
|
5 |
+
"keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"],
|
6 |
+
"homepage": "http://guzzlephp.org/",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
"license": "MIT",
|
8 |
"authors": [
|
9 |
{
|
10 |
"name": "Michael Dowling",
|
11 |
"email": "mtdowling@gmail.com",
|
12 |
+
"homepage": "https://github.com/mtdowling"
|
13 |
}
|
14 |
],
|
15 |
"require": {
|
16 |
"php": ">=5.5",
|
17 |
+
"guzzlehttp/psr7": "^1.4",
|
18 |
+
"guzzlehttp/promises": "^1.0"
|
19 |
},
|
20 |
"require-dev": {
|
21 |
"ext-curl": "*",
|
22 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
|
23 |
+
"psr/log": "^1.0"
|
24 |
},
|
25 |
"autoload": {
|
26 |
+
"files": ["src/functions_include.php"],
|
|
|
|
|
27 |
"psr-4": {
|
28 |
+
"GuzzleHttp\\": "src/"
|
29 |
}
|
30 |
},
|
31 |
"autoload-dev": {
|
32 |
"psr-4": {
|
33 |
+
"GuzzleHttp\\Tests\\": "tests/"
|
34 |
}
|
35 |
},
|
36 |
"suggest": {
|
37 |
+
"psr/log": "Required for using the Log middleware"
|
38 |
},
|
39 |
"extra": {
|
40 |
"branch-alias": {
|
41 |
"dev-master": "6.3-dev"
|
42 |
}
|
43 |
}
|
44 |
+
}
|
@@ -1,13 +1,13 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJar;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
10 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
11 |
/**
|
12 |
* @method ResponseInterface get(string|UriInterface $uri, array $options = [])
|
13 |
* @method ResponseInterface head(string|UriInterface $uri, array $options = [])
|
@@ -22,10 +22,11 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
|
22 |
* @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
|
23 |
* @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
|
24 |
*/
|
25 |
-
class Client implements
|
26 |
{
|
27 |
/** @var array Default request options */
|
28 |
private $config;
|
|
|
29 |
/**
|
30 |
* Clients accept an array of constructor parameters.
|
31 |
*
|
@@ -61,36 +62,50 @@ class Client implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\ClientInterface
|
|
61 |
public function __construct(array $config = [])
|
62 |
{
|
63 |
if (!isset($config['handler'])) {
|
64 |
-
$config['handler'] =
|
65 |
-
} elseif (
|
66 |
throw new \InvalidArgumentException('handler must be a callable');
|
67 |
}
|
|
|
68 |
// Convert the base_uri to a UriInterface
|
69 |
if (isset($config['base_uri'])) {
|
70 |
-
$config['base_uri'] =
|
71 |
}
|
|
|
72 |
$this->configureDefaults($config);
|
73 |
}
|
|
|
74 |
public function __call($method, $args)
|
75 |
{
|
76 |
-
if (
|
77 |
throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
|
78 |
}
|
|
|
79 |
$uri = $args[0];
|
80 |
$opts = isset($args[1]) ? $args[1] : [];
|
81 |
-
|
|
|
|
|
|
|
82 |
}
|
83 |
-
|
|
|
84 |
{
|
85 |
// Merge the base URI into the request URI if needed.
|
86 |
$options = $this->prepareDefaults($options);
|
87 |
-
|
|
|
|
|
|
|
|
|
88 |
}
|
89 |
-
|
|
|
90 |
{
|
91 |
-
$options[
|
92 |
return $this->sendAsync($request, $options)->wait();
|
93 |
}
|
|
|
94 |
public function requestAsync($method, $uri = '', array $options = [])
|
95 |
{
|
96 |
$options = $this->prepareDefaults($options);
|
@@ -100,32 +115,41 @@ class Client implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\ClientInterface
|
|
100 |
$version = isset($options['version']) ? $options['version'] : '1.1';
|
101 |
// Merge the URI into the base URI.
|
102 |
$uri = $this->buildUri($uri, $options);
|
103 |
-
if (
|
104 |
$this->invalidBody();
|
105 |
}
|
106 |
-
$request = new
|
107 |
// Remove the option so that they are not doubly-applied.
|
108 |
unset($options['headers'], $options['body'], $options['version']);
|
|
|
109 |
return $this->transfer($request, $options);
|
110 |
}
|
|
|
111 |
public function request($method, $uri = '', array $options = [])
|
112 |
{
|
113 |
-
$options[
|
114 |
return $this->requestAsync($method, $uri, $options)->wait();
|
115 |
}
|
|
|
116 |
public function getConfig($option = null)
|
117 |
{
|
118 |
-
return $option === null
|
|
|
|
|
119 |
}
|
|
|
120 |
private function buildUri($uri, array $config)
|
121 |
{
|
122 |
// for BC we accept null which would otherwise fail in uri_for
|
123 |
-
$uri =
|
|
|
124 |
if (isset($config['base_uri'])) {
|
125 |
-
$uri =
|
126 |
}
|
|
|
127 |
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
|
128 |
}
|
|
|
129 |
/**
|
130 |
* Configures the default options for a client.
|
131 |
*
|
@@ -133,38 +157,52 @@ class Client implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\ClientInterface
|
|
133 |
*/
|
134 |
private function configureDefaults(array $config)
|
135 |
{
|
136 |
-
$defaults = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
|
|
|
138 |
// We can only trust the HTTP_PROXY environment variable in a CLI
|
139 |
// process due to the fact that PHP has no reliable mechanism to
|
140 |
// get environment variables that start with "HTTP_".
|
141 |
-
if (
|
142 |
-
$defaults['proxy']['http'] =
|
143 |
}
|
144 |
-
|
|
|
145 |
$defaults['proxy']['https'] = $proxy;
|
146 |
}
|
147 |
-
|
148 |
-
|
149 |
-
$
|
|
|
150 |
}
|
|
|
151 |
$this->config = $config + $defaults;
|
152 |
-
|
153 |
-
|
|
|
154 |
}
|
|
|
155 |
// Add the default user-agent header.
|
156 |
if (!isset($this->config['headers'])) {
|
157 |
$this->config['headers'] = ['User-Agent' => default_user_agent()];
|
158 |
} else {
|
159 |
// Add the User-Agent header if one was not already set.
|
160 |
-
foreach (
|
161 |
-
if (
|
162 |
return;
|
163 |
}
|
164 |
}
|
165 |
$this->config['headers']['User-Agent'] = default_user_agent();
|
166 |
}
|
167 |
}
|
|
|
168 |
/**
|
169 |
* Merges default options into the array.
|
170 |
*
|
@@ -175,32 +213,38 @@ class Client implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\ClientInterface
|
|
175 |
private function prepareDefaults($options)
|
176 |
{
|
177 |
$defaults = $this->config;
|
|
|
178 |
if (!empty($defaults['headers'])) {
|
179 |
// Default headers are only added if they are not present.
|
180 |
$defaults['_conditional'] = $defaults['headers'];
|
181 |
unset($defaults['headers']);
|
182 |
}
|
|
|
183 |
// Special handling for headers is required as they are added as
|
184 |
// conditional headers and as headers passed to a request ctor.
|
185 |
-
if (
|
186 |
// Allows default headers to be unset.
|
187 |
if ($options['headers'] === null) {
|
188 |
$defaults['_conditional'] = null;
|
189 |
unset($options['headers']);
|
190 |
-
} elseif (
|
191 |
throw new \InvalidArgumentException('headers must be an array');
|
192 |
}
|
193 |
}
|
|
|
194 |
// Shallow merge defaults underneath options.
|
195 |
$result = $options + $defaults;
|
|
|
196 |
// Remove null values.
|
197 |
foreach ($result as $k => $v) {
|
198 |
if ($v === null) {
|
199 |
unset($result[$k]);
|
200 |
}
|
201 |
}
|
|
|
202 |
return $result;
|
203 |
}
|
|
|
204 |
/**
|
205 |
* Transfers the given request and applies request options.
|
206 |
*
|
@@ -212,26 +256,30 @@ class Client implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\ClientInterface
|
|
212 |
*
|
213 |
* @return Promise\PromiseInterface
|
214 |
*/
|
215 |
-
private function transfer(
|
216 |
{
|
217 |
// save_to -> sink
|
218 |
if (isset($options['save_to'])) {
|
219 |
$options['sink'] = $options['save_to'];
|
220 |
unset($options['save_to']);
|
221 |
}
|
|
|
222 |
// exceptions -> http_errors
|
223 |
if (isset($options['exceptions'])) {
|
224 |
$options['http_errors'] = $options['exceptions'];
|
225 |
unset($options['exceptions']);
|
226 |
}
|
|
|
227 |
$request = $this->applyOptions($request, $options);
|
228 |
$handler = $options['handler'];
|
|
|
229 |
try {
|
230 |
-
return
|
231 |
} catch (\Exception $e) {
|
232 |
-
return
|
233 |
}
|
234 |
}
|
|
|
235 |
/**
|
236 |
* Applies the array of request options to a request.
|
237 |
*
|
@@ -240,91 +288,112 @@ class Client implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\ClientInterface
|
|
240 |
*
|
241 |
* @return RequestInterface
|
242 |
*/
|
243 |
-
private function applyOptions(
|
244 |
{
|
245 |
-
$modify = [
|
|
|
|
|
|
|
246 |
if (isset($options['headers'])) {
|
247 |
$modify['set_headers'] = $options['headers'];
|
248 |
unset($options['headers']);
|
249 |
}
|
|
|
250 |
if (isset($options['form_params'])) {
|
251 |
if (isset($options['multipart'])) {
|
252 |
-
throw new \InvalidArgumentException('You cannot use '
|
|
|
|
|
|
|
|
|
253 |
}
|
254 |
-
$options['body'] =
|
255 |
unset($options['form_params']);
|
256 |
// Ensure that we don't have the header in different case and set the new value.
|
257 |
-
$options['_conditional'] =
|
258 |
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
259 |
}
|
|
|
260 |
if (isset($options['multipart'])) {
|
261 |
-
$options['body'] = new
|
262 |
unset($options['multipart']);
|
263 |
}
|
|
|
264 |
if (isset($options['json'])) {
|
265 |
-
$options['body'] = \
|
266 |
unset($options['json']);
|
267 |
// Ensure that we don't have the header in different case and set the new value.
|
268 |
-
$options['_conditional'] =
|
269 |
$options['_conditional']['Content-Type'] = 'application/json';
|
270 |
}
|
271 |
-
|
|
|
|
|
|
|
272 |
// Ensure that we don't have the header in different case and set the new value.
|
273 |
-
$options['_conditional'] =
|
274 |
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
|
275 |
}
|
|
|
276 |
if (isset($options['body'])) {
|
277 |
-
if (
|
278 |
$this->invalidBody();
|
279 |
}
|
280 |
-
$modify['body'] =
|
281 |
unset($options['body']);
|
282 |
}
|
283 |
-
|
|
|
284 |
$value = $options['auth'];
|
285 |
-
$type = isset($value[2]) ?
|
286 |
switch ($type) {
|
287 |
case 'basic':
|
288 |
// Ensure that we don't have the header in different case and set the new value.
|
289 |
-
$modify['set_headers'] =
|
290 |
-
$modify['set_headers']['Authorization'] = 'Basic '
|
|
|
291 |
break;
|
292 |
case 'digest':
|
293 |
// @todo: Do not rely on curl
|
294 |
-
$options['curl'][
|
295 |
-
$options['curl'][
|
296 |
break;
|
297 |
case 'ntlm':
|
298 |
-
$options['curl'][
|
299 |
-
$options['curl'][
|
300 |
break;
|
301 |
}
|
302 |
}
|
|
|
303 |
if (isset($options['query'])) {
|
304 |
$value = $options['query'];
|
305 |
-
if (
|
306 |
-
$value =
|
307 |
}
|
308 |
-
if (
|
309 |
throw new \InvalidArgumentException('query must be a string or array');
|
310 |
}
|
311 |
$modify['query'] = $value;
|
312 |
unset($options['query']);
|
313 |
}
|
|
|
314 |
// Ensure that sink is not an invalid value.
|
315 |
if (isset($options['sink'])) {
|
316 |
// TODO: Add more sink validation?
|
317 |
-
if (
|
318 |
throw new \InvalidArgumentException('sink must not be a boolean');
|
319 |
}
|
320 |
}
|
321 |
-
|
322 |
-
|
|
|
323 |
// Use a multipart/form-data POST if a Content-Type is not set.
|
324 |
// Ensure that we don't have the header in different case and set the new value.
|
325 |
-
$options['_conditional'] =
|
326 |
-
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
|
|
|
327 |
}
|
|
|
328 |
// Merge in conditional headers if they are not present.
|
329 |
if (isset($options['_conditional'])) {
|
330 |
// Build up the changes so it's in a single clone of the message.
|
@@ -334,14 +403,20 @@ class Client implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\ClientInterface
|
|
334 |
$modify['set_headers'][$k] = $v;
|
335 |
}
|
336 |
}
|
337 |
-
$request =
|
338 |
// Don't pass this internal value along to middleware/handlers.
|
339 |
unset($options['_conditional']);
|
340 |
}
|
|
|
341 |
return $request;
|
342 |
}
|
|
|
343 |
private function invalidBody()
|
344 |
{
|
345 |
-
throw new \InvalidArgumentException('Passing in the "body" request '
|
|
|
|
|
|
|
|
|
346 |
}
|
347 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Cookie\CookieJar;
|
5 |
+
use GuzzleHttp\Promise;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
use Psr\Http\Message\UriInterface;
|
8 |
+
use Psr\Http\Message\RequestInterface;
|
9 |
+
use Psr\Http\Message\ResponseInterface;
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* @method ResponseInterface get(string|UriInterface $uri, array $options = [])
|
13 |
* @method ResponseInterface head(string|UriInterface $uri, array $options = [])
|
22 |
* @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
|
23 |
* @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
|
24 |
*/
|
25 |
+
class Client implements ClientInterface
|
26 |
{
|
27 |
/** @var array Default request options */
|
28 |
private $config;
|
29 |
+
|
30 |
/**
|
31 |
* Clients accept an array of constructor parameters.
|
32 |
*
|
62 |
public function __construct(array $config = [])
|
63 |
{
|
64 |
if (!isset($config['handler'])) {
|
65 |
+
$config['handler'] = HandlerStack::create();
|
66 |
+
} elseif (!is_callable($config['handler'])) {
|
67 |
throw new \InvalidArgumentException('handler must be a callable');
|
68 |
}
|
69 |
+
|
70 |
// Convert the base_uri to a UriInterface
|
71 |
if (isset($config['base_uri'])) {
|
72 |
+
$config['base_uri'] = Psr7\uri_for($config['base_uri']);
|
73 |
}
|
74 |
+
|
75 |
$this->configureDefaults($config);
|
76 |
}
|
77 |
+
|
78 |
public function __call($method, $args)
|
79 |
{
|
80 |
+
if (count($args) < 1) {
|
81 |
throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
|
82 |
}
|
83 |
+
|
84 |
$uri = $args[0];
|
85 |
$opts = isset($args[1]) ? $args[1] : [];
|
86 |
+
|
87 |
+
return substr($method, -5) === 'Async'
|
88 |
+
? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
|
89 |
+
: $this->request($method, $uri, $opts);
|
90 |
}
|
91 |
+
|
92 |
+
public function sendAsync(RequestInterface $request, array $options = [])
|
93 |
{
|
94 |
// Merge the base URI into the request URI if needed.
|
95 |
$options = $this->prepareDefaults($options);
|
96 |
+
|
97 |
+
return $this->transfer(
|
98 |
+
$request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
|
99 |
+
$options
|
100 |
+
);
|
101 |
}
|
102 |
+
|
103 |
+
public function send(RequestInterface $request, array $options = [])
|
104 |
{
|
105 |
+
$options[RequestOptions::SYNCHRONOUS] = true;
|
106 |
return $this->sendAsync($request, $options)->wait();
|
107 |
}
|
108 |
+
|
109 |
public function requestAsync($method, $uri = '', array $options = [])
|
110 |
{
|
111 |
$options = $this->prepareDefaults($options);
|
115 |
$version = isset($options['version']) ? $options['version'] : '1.1';
|
116 |
// Merge the URI into the base URI.
|
117 |
$uri = $this->buildUri($uri, $options);
|
118 |
+
if (is_array($body)) {
|
119 |
$this->invalidBody();
|
120 |
}
|
121 |
+
$request = new Psr7\Request($method, $uri, $headers, $body, $version);
|
122 |
// Remove the option so that they are not doubly-applied.
|
123 |
unset($options['headers'], $options['body'], $options['version']);
|
124 |
+
|
125 |
return $this->transfer($request, $options);
|
126 |
}
|
127 |
+
|
128 |
public function request($method, $uri = '', array $options = [])
|
129 |
{
|
130 |
+
$options[RequestOptions::SYNCHRONOUS] = true;
|
131 |
return $this->requestAsync($method, $uri, $options)->wait();
|
132 |
}
|
133 |
+
|
134 |
public function getConfig($option = null)
|
135 |
{
|
136 |
+
return $option === null
|
137 |
+
? $this->config
|
138 |
+
: (isset($this->config[$option]) ? $this->config[$option] : null);
|
139 |
}
|
140 |
+
|
141 |
private function buildUri($uri, array $config)
|
142 |
{
|
143 |
// for BC we accept null which would otherwise fail in uri_for
|
144 |
+
$uri = Psr7\uri_for($uri === null ? '' : $uri);
|
145 |
+
|
146 |
if (isset($config['base_uri'])) {
|
147 |
+
$uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
|
148 |
}
|
149 |
+
|
150 |
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
|
151 |
}
|
152 |
+
|
153 |
/**
|
154 |
* Configures the default options for a client.
|
155 |
*
|
157 |
*/
|
158 |
private function configureDefaults(array $config)
|
159 |
{
|
160 |
+
$defaults = [
|
161 |
+
'allow_redirects' => RedirectMiddleware::$defaultSettings,
|
162 |
+
'http_errors' => true,
|
163 |
+
'decode_content' => true,
|
164 |
+
'verify' => true,
|
165 |
+
'cookies' => false
|
166 |
+
];
|
167 |
+
|
168 |
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
|
169 |
+
|
170 |
// We can only trust the HTTP_PROXY environment variable in a CLI
|
171 |
// process due to the fact that PHP has no reliable mechanism to
|
172 |
// get environment variables that start with "HTTP_".
|
173 |
+
if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) {
|
174 |
+
$defaults['proxy']['http'] = getenv('HTTP_PROXY');
|
175 |
}
|
176 |
+
|
177 |
+
if ($proxy = getenv('HTTPS_PROXY')) {
|
178 |
$defaults['proxy']['https'] = $proxy;
|
179 |
}
|
180 |
+
|
181 |
+
if ($noProxy = getenv('NO_PROXY')) {
|
182 |
+
$cleanedNoProxy = str_replace(' ', '', $noProxy);
|
183 |
+
$defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
|
184 |
}
|
185 |
+
|
186 |
$this->config = $config + $defaults;
|
187 |
+
|
188 |
+
if (!empty($config['cookies']) && $config['cookies'] === true) {
|
189 |
+
$this->config['cookies'] = new CookieJar();
|
190 |
}
|
191 |
+
|
192 |
// Add the default user-agent header.
|
193 |
if (!isset($this->config['headers'])) {
|
194 |
$this->config['headers'] = ['User-Agent' => default_user_agent()];
|
195 |
} else {
|
196 |
// Add the User-Agent header if one was not already set.
|
197 |
+
foreach (array_keys($this->config['headers']) as $name) {
|
198 |
+
if (strtolower($name) === 'user-agent') {
|
199 |
return;
|
200 |
}
|
201 |
}
|
202 |
$this->config['headers']['User-Agent'] = default_user_agent();
|
203 |
}
|
204 |
}
|
205 |
+
|
206 |
/**
|
207 |
* Merges default options into the array.
|
208 |
*
|
213 |
private function prepareDefaults($options)
|
214 |
{
|
215 |
$defaults = $this->config;
|
216 |
+
|
217 |
if (!empty($defaults['headers'])) {
|
218 |
// Default headers are only added if they are not present.
|
219 |
$defaults['_conditional'] = $defaults['headers'];
|
220 |
unset($defaults['headers']);
|
221 |
}
|
222 |
+
|
223 |
// Special handling for headers is required as they are added as
|
224 |
// conditional headers and as headers passed to a request ctor.
|
225 |
+
if (array_key_exists('headers', $options)) {
|
226 |
// Allows default headers to be unset.
|
227 |
if ($options['headers'] === null) {
|
228 |
$defaults['_conditional'] = null;
|
229 |
unset($options['headers']);
|
230 |
+
} elseif (!is_array($options['headers'])) {
|
231 |
throw new \InvalidArgumentException('headers must be an array');
|
232 |
}
|
233 |
}
|
234 |
+
|
235 |
// Shallow merge defaults underneath options.
|
236 |
$result = $options + $defaults;
|
237 |
+
|
238 |
// Remove null values.
|
239 |
foreach ($result as $k => $v) {
|
240 |
if ($v === null) {
|
241 |
unset($result[$k]);
|
242 |
}
|
243 |
}
|
244 |
+
|
245 |
return $result;
|
246 |
}
|
247 |
+
|
248 |
/**
|
249 |
* Transfers the given request and applies request options.
|
250 |
*
|
256 |
*
|
257 |
* @return Promise\PromiseInterface
|
258 |
*/
|
259 |
+
private function transfer(RequestInterface $request, array $options)
|
260 |
{
|
261 |
// save_to -> sink
|
262 |
if (isset($options['save_to'])) {
|
263 |
$options['sink'] = $options['save_to'];
|
264 |
unset($options['save_to']);
|
265 |
}
|
266 |
+
|
267 |
// exceptions -> http_errors
|
268 |
if (isset($options['exceptions'])) {
|
269 |
$options['http_errors'] = $options['exceptions'];
|
270 |
unset($options['exceptions']);
|
271 |
}
|
272 |
+
|
273 |
$request = $this->applyOptions($request, $options);
|
274 |
$handler = $options['handler'];
|
275 |
+
|
276 |
try {
|
277 |
+
return Promise\promise_for($handler($request, $options));
|
278 |
} catch (\Exception $e) {
|
279 |
+
return Promise\rejection_for($e);
|
280 |
}
|
281 |
}
|
282 |
+
|
283 |
/**
|
284 |
* Applies the array of request options to a request.
|
285 |
*
|
288 |
*
|
289 |
* @return RequestInterface
|
290 |
*/
|
291 |
+
private function applyOptions(RequestInterface $request, array &$options)
|
292 |
{
|
293 |
+
$modify = [
|
294 |
+
'set_headers' => [],
|
295 |
+
];
|
296 |
+
|
297 |
if (isset($options['headers'])) {
|
298 |
$modify['set_headers'] = $options['headers'];
|
299 |
unset($options['headers']);
|
300 |
}
|
301 |
+
|
302 |
if (isset($options['form_params'])) {
|
303 |
if (isset($options['multipart'])) {
|
304 |
+
throw new \InvalidArgumentException('You cannot use '
|
305 |
+
. 'form_params and multipart at the same time. Use the '
|
306 |
+
. 'form_params option if you want to send application/'
|
307 |
+
. 'x-www-form-urlencoded requests, and the multipart '
|
308 |
+
. 'option to send multipart/form-data requests.');
|
309 |
}
|
310 |
+
$options['body'] = http_build_query($options['form_params'], '', '&');
|
311 |
unset($options['form_params']);
|
312 |
// Ensure that we don't have the header in different case and set the new value.
|
313 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
314 |
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
315 |
}
|
316 |
+
|
317 |
if (isset($options['multipart'])) {
|
318 |
+
$options['body'] = new Psr7\MultipartStream($options['multipart']);
|
319 |
unset($options['multipart']);
|
320 |
}
|
321 |
+
|
322 |
if (isset($options['json'])) {
|
323 |
+
$options['body'] = \GuzzleHttp\json_encode($options['json']);
|
324 |
unset($options['json']);
|
325 |
// Ensure that we don't have the header in different case and set the new value.
|
326 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
327 |
$options['_conditional']['Content-Type'] = 'application/json';
|
328 |
}
|
329 |
+
|
330 |
+
if (!empty($options['decode_content'])
|
331 |
+
&& $options['decode_content'] !== true
|
332 |
+
) {
|
333 |
// Ensure that we don't have the header in different case and set the new value.
|
334 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
|
335 |
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
|
336 |
}
|
337 |
+
|
338 |
if (isset($options['body'])) {
|
339 |
+
if (is_array($options['body'])) {
|
340 |
$this->invalidBody();
|
341 |
}
|
342 |
+
$modify['body'] = Psr7\stream_for($options['body']);
|
343 |
unset($options['body']);
|
344 |
}
|
345 |
+
|
346 |
+
if (!empty($options['auth']) && is_array($options['auth'])) {
|
347 |
$value = $options['auth'];
|
348 |
+
$type = isset($value[2]) ? strtolower($value[2]) : 'basic';
|
349 |
switch ($type) {
|
350 |
case 'basic':
|
351 |
// Ensure that we don't have the header in different case and set the new value.
|
352 |
+
$modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
|
353 |
+
$modify['set_headers']['Authorization'] = 'Basic '
|
354 |
+
. base64_encode("$value[0]:$value[1]");
|
355 |
break;
|
356 |
case 'digest':
|
357 |
// @todo: Do not rely on curl
|
358 |
+
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
|
359 |
+
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
360 |
break;
|
361 |
case 'ntlm':
|
362 |
+
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
|
363 |
+
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
364 |
break;
|
365 |
}
|
366 |
}
|
367 |
+
|
368 |
if (isset($options['query'])) {
|
369 |
$value = $options['query'];
|
370 |
+
if (is_array($value)) {
|
371 |
+
$value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
|
372 |
}
|
373 |
+
if (!is_string($value)) {
|
374 |
throw new \InvalidArgumentException('query must be a string or array');
|
375 |
}
|
376 |
$modify['query'] = $value;
|
377 |
unset($options['query']);
|
378 |
}
|
379 |
+
|
380 |
// Ensure that sink is not an invalid value.
|
381 |
if (isset($options['sink'])) {
|
382 |
// TODO: Add more sink validation?
|
383 |
+
if (is_bool($options['sink'])) {
|
384 |
throw new \InvalidArgumentException('sink must not be a boolean');
|
385 |
}
|
386 |
}
|
387 |
+
|
388 |
+
$request = Psr7\modify_request($request, $modify);
|
389 |
+
if ($request->getBody() instanceof Psr7\MultipartStream) {
|
390 |
// Use a multipart/form-data POST if a Content-Type is not set.
|
391 |
// Ensure that we don't have the header in different case and set the new value.
|
392 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
393 |
+
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
|
394 |
+
. $request->getBody()->getBoundary();
|
395 |
}
|
396 |
+
|
397 |
// Merge in conditional headers if they are not present.
|
398 |
if (isset($options['_conditional'])) {
|
399 |
// Build up the changes so it's in a single clone of the message.
|
403 |
$modify['set_headers'][$k] = $v;
|
404 |
}
|
405 |
}
|
406 |
+
$request = Psr7\modify_request($request, $modify);
|
407 |
// Don't pass this internal value along to middleware/handlers.
|
408 |
unset($options['_conditional']);
|
409 |
}
|
410 |
+
|
411 |
return $request;
|
412 |
}
|
413 |
+
|
414 |
private function invalidBody()
|
415 |
{
|
416 |
+
throw new \InvalidArgumentException('Passing in the "body" request '
|
417 |
+
. 'option as an array to send a POST request has been deprecated. '
|
418 |
+
. 'Please use the "form_params" request option to send a '
|
419 |
+
. 'application/x-www-form-urlencoded request, or the "multipart" '
|
420 |
+
. 'request option to send a multipart/form-data request.');
|
421 |
}
|
422 |
}
|
@@ -1,18 +1,19 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\GuzzleException;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
10 |
/**
|
11 |
* Client interface for sending HTTP requests.
|
12 |
*/
|
13 |
interface ClientInterface
|
14 |
{
|
15 |
const VERSION = '6.3.3';
|
|
|
16 |
/**
|
17 |
* Send an HTTP request.
|
18 |
*
|
@@ -23,7 +24,8 @@ interface ClientInterface
|
|
23 |
* @return ResponseInterface
|
24 |
* @throws GuzzleException
|
25 |
*/
|
26 |
-
public function send(
|
|
|
27 |
/**
|
28 |
* Asynchronously send an HTTP request.
|
29 |
*
|
@@ -33,7 +35,8 @@ interface ClientInterface
|
|
33 |
*
|
34 |
* @return PromiseInterface
|
35 |
*/
|
36 |
-
public function sendAsync(
|
|
|
37 |
/**
|
38 |
* Create and send an HTTP request.
|
39 |
*
|
@@ -49,6 +52,7 @@ interface ClientInterface
|
|
49 |
* @throws GuzzleException
|
50 |
*/
|
51 |
public function request($method, $uri, array $options = []);
|
|
|
52 |
/**
|
53 |
* Create and send an asynchronous HTTP request.
|
54 |
*
|
@@ -64,6 +68,7 @@ interface ClientInterface
|
|
64 |
* @return PromiseInterface
|
65 |
*/
|
66 |
public function requestAsync($method, $uri, array $options = []);
|
|
|
67 |
/**
|
68 |
* Get a client configuration option.
|
69 |
*
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use GuzzleHttp\Exception\GuzzleException;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
use Psr\Http\Message\UriInterface;
|
9 |
|
|
|
|
|
|
|
|
|
|
|
10 |
/**
|
11 |
* Client interface for sending HTTP requests.
|
12 |
*/
|
13 |
interface ClientInterface
|
14 |
{
|
15 |
const VERSION = '6.3.3';
|
16 |
+
|
17 |
/**
|
18 |
* Send an HTTP request.
|
19 |
*
|
24 |
* @return ResponseInterface
|
25 |
* @throws GuzzleException
|
26 |
*/
|
27 |
+
public function send(RequestInterface $request, array $options = []);
|
28 |
+
|
29 |
/**
|
30 |
* Asynchronously send an HTTP request.
|
31 |
*
|
35 |
*
|
36 |
* @return PromiseInterface
|
37 |
*/
|
38 |
+
public function sendAsync(RequestInterface $request, array $options = []);
|
39 |
+
|
40 |
/**
|
41 |
* Create and send an HTTP request.
|
42 |
*
|
52 |
* @throws GuzzleException
|
53 |
*/
|
54 |
public function request($method, $uri, array $options = []);
|
55 |
+
|
56 |
/**
|
57 |
* Create and send an asynchronous HTTP request.
|
58 |
*
|
68 |
* @return PromiseInterface
|
69 |
*/
|
70 |
public function requestAsync($method, $uri, array $options = []);
|
71 |
+
|
72 |
/**
|
73 |
* Get a client configuration option.
|
74 |
*
|
@@ -1,18 +1,20 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
7 |
/**
|
8 |
* Cookie jar that stores cookies as an array
|
9 |
*/
|
10 |
-
class CookieJar implements
|
11 |
{
|
12 |
/** @var SetCookie[] Loaded cookie data */
|
13 |
private $cookies = [];
|
|
|
14 |
/** @var bool */
|
15 |
private $strictMode;
|
|
|
16 |
/**
|
17 |
* @param bool $strictMode Set to true to throw exceptions when invalid
|
18 |
* cookies are added to the cookie jar.
|
@@ -20,16 +22,18 @@ class CookieJar implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJarI
|
|
20 |
* arrays that can be used with the SetCookie
|
21 |
* constructor
|
22 |
*/
|
23 |
-
public function __construct($strictMode =
|
24 |
{
|
25 |
$this->strictMode = $strictMode;
|
|
|
26 |
foreach ($cookieArray as $cookie) {
|
27 |
-
if (
|
28 |
-
$cookie = new
|
29 |
}
|
30 |
$this->setCookie($cookie);
|
31 |
}
|
32 |
}
|
|
|
33 |
/**
|
34 |
* Create a new Cookie jar from an associative array and domain.
|
35 |
*
|
@@ -42,10 +46,17 @@ class CookieJar implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJarI
|
|
42 |
{
|
43 |
$cookieJar = new self();
|
44 |
foreach ($cookies as $name => $value) {
|
45 |
-
$cookieJar->setCookie(new
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
|
|
47 |
return $cookieJar;
|
48 |
}
|
|
|
49 |
/**
|
50 |
* @deprecated
|
51 |
*/
|
@@ -53,6 +64,7 @@ class CookieJar implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJarI
|
|
53 |
{
|
54 |
return $value;
|
55 |
}
|
|
|
56 |
/**
|
57 |
* Evaluate if this cookie should be persisted to storage
|
58 |
* that survives between requests.
|
@@ -61,15 +73,19 @@ class CookieJar implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJarI
|
|
61 |
* @param bool $allowSessionCookies If we should persist session cookies
|
62 |
* @return bool
|
63 |
*/
|
64 |
-
public static function shouldPersist(
|
65 |
-
|
|
|
|
|
66 |
if ($cookie->getExpires() || $allowSessionCookies) {
|
67 |
if (!$cookie->getDiscard()) {
|
68 |
-
return
|
69 |
}
|
70 |
}
|
71 |
-
|
|
|
72 |
}
|
|
|
73 |
/**
|
74 |
* Finds and returns the cookie based on the name
|
75 |
*
|
@@ -83,113 +99,150 @@ class CookieJar implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJarI
|
|
83 |
return null;
|
84 |
}
|
85 |
foreach ($this->cookies as $cookie) {
|
86 |
-
if ($cookie->getName() !== null &&
|
87 |
return $cookie;
|
88 |
}
|
89 |
}
|
90 |
}
|
|
|
91 |
public function toArray()
|
92 |
{
|
93 |
-
return
|
94 |
return $cookie->toArray();
|
95 |
}, $this->getIterator()->getArrayCopy());
|
96 |
}
|
|
|
97 |
public function clear($domain = null, $path = null, $name = null)
|
98 |
{
|
99 |
if (!$domain) {
|
100 |
$this->cookies = [];
|
101 |
return;
|
102 |
} elseif (!$path) {
|
103 |
-
$this->cookies =
|
104 |
-
|
105 |
-
|
|
|
|
|
|
|
106 |
} elseif (!$name) {
|
107 |
-
$this->cookies =
|
108 |
-
|
109 |
-
|
|
|
|
|
|
|
|
|
110 |
} else {
|
111 |
-
$this->cookies =
|
112 |
-
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
114 |
}
|
115 |
}
|
|
|
116 |
public function clearSessionCookies()
|
117 |
{
|
118 |
-
$this->cookies =
|
119 |
-
|
120 |
-
|
|
|
|
|
|
|
121 |
}
|
122 |
-
|
|
|
123 |
{
|
124 |
// If the name string is empty (but not 0), ignore the set-cookie
|
125 |
// string entirely.
|
126 |
$name = $cookie->getName();
|
127 |
if (!$name && $name !== '0') {
|
128 |
-
return
|
129 |
}
|
|
|
130 |
// Only allow cookies with set and valid domain, name, value
|
131 |
$result = $cookie->validate();
|
132 |
-
if ($result !==
|
133 |
if ($this->strictMode) {
|
134 |
throw new \RuntimeException('Invalid cookie: ' . $result);
|
135 |
} else {
|
136 |
$this->removeCookieIfEmpty($cookie);
|
137 |
-
return
|
138 |
}
|
139 |
}
|
|
|
140 |
// Resolve conflicts with previously set cookies
|
141 |
foreach ($this->cookies as $i => $c) {
|
|
|
142 |
// Two cookies are identical, when their path, and domain are
|
143 |
// identical.
|
144 |
-
if ($c->getPath() != $cookie->getPath() ||
|
|
|
|
|
|
|
145 |
continue;
|
146 |
}
|
|
|
147 |
// The previously set cookie is a discard cookie and this one is
|
148 |
// not so allow the new cookie to be set
|
149 |
if (!$cookie->getDiscard() && $c->getDiscard()) {
|
150 |
unset($this->cookies[$i]);
|
151 |
continue;
|
152 |
}
|
|
|
153 |
// If the new cookie's expiration is further into the future, then
|
154 |
// replace the old cookie
|
155 |
if ($cookie->getExpires() > $c->getExpires()) {
|
156 |
unset($this->cookies[$i]);
|
157 |
continue;
|
158 |
}
|
|
|
159 |
// If the value has changed, we better change it
|
160 |
if ($cookie->getValue() !== $c->getValue()) {
|
161 |
unset($this->cookies[$i]);
|
162 |
continue;
|
163 |
}
|
|
|
164 |
// The cookie exists, so no need to continue
|
165 |
-
return
|
166 |
}
|
|
|
167 |
$this->cookies[] = $cookie;
|
168 |
-
|
|
|
169 |
}
|
|
|
170 |
public function count()
|
171 |
{
|
172 |
-
return
|
173 |
}
|
|
|
174 |
public function getIterator()
|
175 |
{
|
176 |
-
return new \ArrayIterator(
|
177 |
}
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
180 |
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
|
181 |
foreach ($cookieHeader as $cookie) {
|
182 |
-
$sc =
|
183 |
if (!$sc->getDomain()) {
|
184 |
$sc->setDomain($request->getUri()->getHost());
|
185 |
}
|
186 |
-
if (0 !==
|
187 |
$sc->setPath($this->getCookiePathFromRequest($request));
|
188 |
}
|
189 |
$this->setCookie($sc);
|
190 |
}
|
191 |
}
|
192 |
}
|
|
|
193 |
/**
|
194 |
* Computes cookie path following RFC 6265 section 5.1.4
|
195 |
*
|
@@ -198,48 +251,64 @@ class CookieJar implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJarI
|
|
198 |
* @param RequestInterface $request
|
199 |
* @return string
|
200 |
*/
|
201 |
-
private function getCookiePathFromRequest(
|
202 |
{
|
203 |
$uriPath = $request->getUri()->getPath();
|
204 |
-
if (''
|
205 |
return '/';
|
206 |
}
|
207 |
-
if (0 !==
|
208 |
return '/';
|
209 |
}
|
210 |
if ('/' === $uriPath) {
|
211 |
return '/';
|
212 |
}
|
213 |
-
if (0 ===
|
214 |
return '/';
|
215 |
}
|
216 |
-
|
|
|
217 |
}
|
218 |
-
|
|
|
219 |
{
|
220 |
$values = [];
|
221 |
$uri = $request->getUri();
|
222 |
$scheme = $uri->getScheme();
|
223 |
$host = $uri->getHost();
|
224 |
$path = $uri->getPath() ?: '/';
|
|
|
225 |
foreach ($this->cookies as $cookie) {
|
226 |
-
if ($cookie->matchesPath($path) &&
|
227 |
-
$
|
|
|
|
|
|
|
|
|
|
|
228 |
}
|
229 |
}
|
230 |
-
|
|
|
|
|
|
|
231 |
}
|
|
|
232 |
/**
|
233 |
* If a cookie already exists and the server asks to set it again with a
|
234 |
* null value, the cookie must be deleted.
|
235 |
*
|
236 |
* @param SetCookie $cookie
|
237 |
*/
|
238 |
-
private function removeCookieIfEmpty(
|
239 |
{
|
240 |
$cookieValue = $cookie->getValue();
|
241 |
if ($cookieValue === null || $cookieValue === '') {
|
242 |
-
$this->clear(
|
|
|
|
|
|
|
|
|
243 |
}
|
244 |
}
|
245 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
|
|
|
|
|
7 |
/**
|
8 |
* Cookie jar that stores cookies as an array
|
9 |
*/
|
10 |
+
class CookieJar implements CookieJarInterface
|
11 |
{
|
12 |
/** @var SetCookie[] Loaded cookie data */
|
13 |
private $cookies = [];
|
14 |
+
|
15 |
/** @var bool */
|
16 |
private $strictMode;
|
17 |
+
|
18 |
/**
|
19 |
* @param bool $strictMode Set to true to throw exceptions when invalid
|
20 |
* cookies are added to the cookie jar.
|
22 |
* arrays that can be used with the SetCookie
|
23 |
* constructor
|
24 |
*/
|
25 |
+
public function __construct($strictMode = false, $cookieArray = [])
|
26 |
{
|
27 |
$this->strictMode = $strictMode;
|
28 |
+
|
29 |
foreach ($cookieArray as $cookie) {
|
30 |
+
if (!($cookie instanceof SetCookie)) {
|
31 |
+
$cookie = new SetCookie($cookie);
|
32 |
}
|
33 |
$this->setCookie($cookie);
|
34 |
}
|
35 |
}
|
36 |
+
|
37 |
/**
|
38 |
* Create a new Cookie jar from an associative array and domain.
|
39 |
*
|
46 |
{
|
47 |
$cookieJar = new self();
|
48 |
foreach ($cookies as $name => $value) {
|
49 |
+
$cookieJar->setCookie(new SetCookie([
|
50 |
+
'Domain' => $domain,
|
51 |
+
'Name' => $name,
|
52 |
+
'Value' => $value,
|
53 |
+
'Discard' => true
|
54 |
+
]));
|
55 |
}
|
56 |
+
|
57 |
return $cookieJar;
|
58 |
}
|
59 |
+
|
60 |
/**
|
61 |
* @deprecated
|
62 |
*/
|
64 |
{
|
65 |
return $value;
|
66 |
}
|
67 |
+
|
68 |
/**
|
69 |
* Evaluate if this cookie should be persisted to storage
|
70 |
* that survives between requests.
|
73 |
* @param bool $allowSessionCookies If we should persist session cookies
|
74 |
* @return bool
|
75 |
*/
|
76 |
+
public static function shouldPersist(
|
77 |
+
SetCookie $cookie,
|
78 |
+
$allowSessionCookies = false
|
79 |
+
) {
|
80 |
if ($cookie->getExpires() || $allowSessionCookies) {
|
81 |
if (!$cookie->getDiscard()) {
|
82 |
+
return true;
|
83 |
}
|
84 |
}
|
85 |
+
|
86 |
+
return false;
|
87 |
}
|
88 |
+
|
89 |
/**
|
90 |
* Finds and returns the cookie based on the name
|
91 |
*
|
99 |
return null;
|
100 |
}
|
101 |
foreach ($this->cookies as $cookie) {
|
102 |
+
if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
|
103 |
return $cookie;
|
104 |
}
|
105 |
}
|
106 |
}
|
107 |
+
|
108 |
public function toArray()
|
109 |
{
|
110 |
+
return array_map(function (SetCookie $cookie) {
|
111 |
return $cookie->toArray();
|
112 |
}, $this->getIterator()->getArrayCopy());
|
113 |
}
|
114 |
+
|
115 |
public function clear($domain = null, $path = null, $name = null)
|
116 |
{
|
117 |
if (!$domain) {
|
118 |
$this->cookies = [];
|
119 |
return;
|
120 |
} elseif (!$path) {
|
121 |
+
$this->cookies = array_filter(
|
122 |
+
$this->cookies,
|
123 |
+
function (SetCookie $cookie) use ($path, $domain) {
|
124 |
+
return !$cookie->matchesDomain($domain);
|
125 |
+
}
|
126 |
+
);
|
127 |
} elseif (!$name) {
|
128 |
+
$this->cookies = array_filter(
|
129 |
+
$this->cookies,
|
130 |
+
function (SetCookie $cookie) use ($path, $domain) {
|
131 |
+
return !($cookie->matchesPath($path) &&
|
132 |
+
$cookie->matchesDomain($domain));
|
133 |
+
}
|
134 |
+
);
|
135 |
} else {
|
136 |
+
$this->cookies = array_filter(
|
137 |
+
$this->cookies,
|
138 |
+
function (SetCookie $cookie) use ($path, $domain, $name) {
|
139 |
+
return !($cookie->getName() == $name &&
|
140 |
+
$cookie->matchesPath($path) &&
|
141 |
+
$cookie->matchesDomain($domain));
|
142 |
+
}
|
143 |
+
);
|
144 |
}
|
145 |
}
|
146 |
+
|
147 |
public function clearSessionCookies()
|
148 |
{
|
149 |
+
$this->cookies = array_filter(
|
150 |
+
$this->cookies,
|
151 |
+
function (SetCookie $cookie) {
|
152 |
+
return !$cookie->getDiscard() && $cookie->getExpires();
|
153 |
+
}
|
154 |
+
);
|
155 |
}
|
156 |
+
|
157 |
+
public function setCookie(SetCookie $cookie)
|
158 |
{
|
159 |
// If the name string is empty (but not 0), ignore the set-cookie
|
160 |
// string entirely.
|
161 |
$name = $cookie->getName();
|
162 |
if (!$name && $name !== '0') {
|
163 |
+
return false;
|
164 |
}
|
165 |
+
|
166 |
// Only allow cookies with set and valid domain, name, value
|
167 |
$result = $cookie->validate();
|
168 |
+
if ($result !== true) {
|
169 |
if ($this->strictMode) {
|
170 |
throw new \RuntimeException('Invalid cookie: ' . $result);
|
171 |
} else {
|
172 |
$this->removeCookieIfEmpty($cookie);
|
173 |
+
return false;
|
174 |
}
|
175 |
}
|
176 |
+
|
177 |
// Resolve conflicts with previously set cookies
|
178 |
foreach ($this->cookies as $i => $c) {
|
179 |
+
|
180 |
// Two cookies are identical, when their path, and domain are
|
181 |
// identical.
|
182 |
+
if ($c->getPath() != $cookie->getPath() ||
|
183 |
+
$c->getDomain() != $cookie->getDomain() ||
|
184 |
+
$c->getName() != $cookie->getName()
|
185 |
+
) {
|
186 |
continue;
|
187 |
}
|
188 |
+
|
189 |
// The previously set cookie is a discard cookie and this one is
|
190 |
// not so allow the new cookie to be set
|
191 |
if (!$cookie->getDiscard() && $c->getDiscard()) {
|
192 |
unset($this->cookies[$i]);
|
193 |
continue;
|
194 |
}
|
195 |
+
|
196 |
// If the new cookie's expiration is further into the future, then
|
197 |
// replace the old cookie
|
198 |
if ($cookie->getExpires() > $c->getExpires()) {
|
199 |
unset($this->cookies[$i]);
|
200 |
continue;
|
201 |
}
|
202 |
+
|
203 |
// If the value has changed, we better change it
|
204 |
if ($cookie->getValue() !== $c->getValue()) {
|
205 |
unset($this->cookies[$i]);
|
206 |
continue;
|
207 |
}
|
208 |
+
|
209 |
// The cookie exists, so no need to continue
|
210 |
+
return false;
|
211 |
}
|
212 |
+
|
213 |
$this->cookies[] = $cookie;
|
214 |
+
|
215 |
+
return true;
|
216 |
}
|
217 |
+
|
218 |
public function count()
|
219 |
{
|
220 |
+
return count($this->cookies);
|
221 |
}
|
222 |
+
|
223 |
public function getIterator()
|
224 |
{
|
225 |
+
return new \ArrayIterator(array_values($this->cookies));
|
226 |
}
|
227 |
+
|
228 |
+
public function extractCookies(
|
229 |
+
RequestInterface $request,
|
230 |
+
ResponseInterface $response
|
231 |
+
) {
|
232 |
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
|
233 |
foreach ($cookieHeader as $cookie) {
|
234 |
+
$sc = SetCookie::fromString($cookie);
|
235 |
if (!$sc->getDomain()) {
|
236 |
$sc->setDomain($request->getUri()->getHost());
|
237 |
}
|
238 |
+
if (0 !== strpos($sc->getPath(), '/')) {
|
239 |
$sc->setPath($this->getCookiePathFromRequest($request));
|
240 |
}
|
241 |
$this->setCookie($sc);
|
242 |
}
|
243 |
}
|
244 |
}
|
245 |
+
|
246 |
/**
|
247 |
* Computes cookie path following RFC 6265 section 5.1.4
|
248 |
*
|
251 |
* @param RequestInterface $request
|
252 |
* @return string
|
253 |
*/
|
254 |
+
private function getCookiePathFromRequest(RequestInterface $request)
|
255 |
{
|
256 |
$uriPath = $request->getUri()->getPath();
|
257 |
+
if ('' === $uriPath) {
|
258 |
return '/';
|
259 |
}
|
260 |
+
if (0 !== strpos($uriPath, '/')) {
|
261 |
return '/';
|
262 |
}
|
263 |
if ('/' === $uriPath) {
|
264 |
return '/';
|
265 |
}
|
266 |
+
if (0 === $lastSlashPos = strrpos($uriPath, '/')) {
|
267 |
return '/';
|
268 |
}
|
269 |
+
|
270 |
+
return substr($uriPath, 0, $lastSlashPos);
|
271 |
}
|
272 |
+
|
273 |
+
public function withCookieHeader(RequestInterface $request)
|
274 |
{
|
275 |
$values = [];
|
276 |
$uri = $request->getUri();
|
277 |
$scheme = $uri->getScheme();
|
278 |
$host = $uri->getHost();
|
279 |
$path = $uri->getPath() ?: '/';
|
280 |
+
|
281 |
foreach ($this->cookies as $cookie) {
|
282 |
+
if ($cookie->matchesPath($path) &&
|
283 |
+
$cookie->matchesDomain($host) &&
|
284 |
+
!$cookie->isExpired() &&
|
285 |
+
(!$cookie->getSecure() || $scheme === 'https')
|
286 |
+
) {
|
287 |
+
$values[] = $cookie->getName() . '='
|
288 |
+
. $cookie->getValue();
|
289 |
}
|
290 |
}
|
291 |
+
|
292 |
+
return $values
|
293 |
+
? $request->withHeader('Cookie', implode('; ', $values))
|
294 |
+
: $request;
|
295 |
}
|
296 |
+
|
297 |
/**
|
298 |
* If a cookie already exists and the server asks to set it again with a
|
299 |
* null value, the cookie must be deleted.
|
300 |
*
|
301 |
* @param SetCookie $cookie
|
302 |
*/
|
303 |
+
private function removeCookieIfEmpty(SetCookie $cookie)
|
304 |
{
|
305 |
$cookieValue = $cookie->getValue();
|
306 |
if ($cookieValue === null || $cookieValue === '') {
|
307 |
+
$this->clear(
|
308 |
+
$cookie->getDomain(),
|
309 |
+
$cookie->getPath(),
|
310 |
+
$cookie->getName()
|
311 |
+
);
|
312 |
}
|
313 |
}
|
314 |
}
|
@@ -1,9 +1,9 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
7 |
/**
|
8 |
* Stores HTTP cookies.
|
9 |
*
|
@@ -26,14 +26,19 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
|
26 |
*
|
27 |
* @return RequestInterface returns the modified request.
|
28 |
*/
|
29 |
-
public function withCookieHeader(
|
|
|
30 |
/**
|
31 |
* Extract cookies from an HTTP response and store them in the CookieJar.
|
32 |
*
|
33 |
* @param RequestInterface $request Request that was sent
|
34 |
* @param ResponseInterface $response Response that was received
|
35 |
*/
|
36 |
-
public function extractCookies(
|
|
|
|
|
|
|
|
|
37 |
/**
|
38 |
* Sets a cookie in the cookie jar.
|
39 |
*
|
@@ -41,7 +46,8 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
|
41 |
*
|
42 |
* @return bool Returns true on success or false on failure
|
43 |
*/
|
44 |
-
public function setCookie(
|
|
|
45 |
/**
|
46 |
* Remove cookies currently held in the cookie jar.
|
47 |
*
|
@@ -59,6 +65,7 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
|
59 |
* @return CookieJarInterface
|
60 |
*/
|
61 |
public function clear($domain = null, $path = null, $name = null);
|
|
|
62 |
/**
|
63 |
* Discard all sessions cookies.
|
64 |
*
|
@@ -67,6 +74,7 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
|
67 |
* to RFC 2965.
|
68 |
*/
|
69 |
public function clearSessionCookies();
|
|
|
70 |
/**
|
71 |
* Converts the cookie jar to an array.
|
72 |
*
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
|
|
|
|
|
7 |
/**
|
8 |
* Stores HTTP cookies.
|
9 |
*
|
26 |
*
|
27 |
* @return RequestInterface returns the modified request.
|
28 |
*/
|
29 |
+
public function withCookieHeader(RequestInterface $request);
|
30 |
+
|
31 |
/**
|
32 |
* Extract cookies from an HTTP response and store them in the CookieJar.
|
33 |
*
|
34 |
* @param RequestInterface $request Request that was sent
|
35 |
* @param ResponseInterface $response Response that was received
|
36 |
*/
|
37 |
+
public function extractCookies(
|
38 |
+
RequestInterface $request,
|
39 |
+
ResponseInterface $response
|
40 |
+
);
|
41 |
+
|
42 |
/**
|
43 |
* Sets a cookie in the cookie jar.
|
44 |
*
|
46 |
*
|
47 |
* @return bool Returns true on success or false on failure
|
48 |
*/
|
49 |
+
public function setCookie(SetCookie $cookie);
|
50 |
+
|
51 |
/**
|
52 |
* Remove cookies currently held in the cookie jar.
|
53 |
*
|
65 |
* @return CookieJarInterface
|
66 |
*/
|
67 |
public function clear($domain = null, $path = null, $name = null);
|
68 |
+
|
69 |
/**
|
70 |
* Discard all sessions cookies.
|
71 |
*
|
74 |
* to RFC 2965.
|
75 |
*/
|
76 |
public function clearSessionCookies();
|
77 |
+
|
78 |
/**
|
79 |
* Converts the cookie jar to an array.
|
80 |
*
|
@@ -1,16 +1,17 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie;
|
4 |
|
5 |
/**
|
6 |
* Persists non-session cookies using a JSON formatted file
|
7 |
*/
|
8 |
-
class FileCookieJar extends
|
9 |
{
|
10 |
/** @var string filename */
|
11 |
private $filename;
|
|
|
12 |
/** @var bool Control whether to persist session cookies or not. */
|
13 |
private $storeSessionCookies;
|
|
|
14 |
/**
|
15 |
* Create a new FileCookieJar object
|
16 |
*
|
@@ -20,14 +21,16 @@ class FileCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJar
|
|
20 |
*
|
21 |
* @throws \RuntimeException if the file cannot be found or created
|
22 |
*/
|
23 |
-
public function __construct($cookieFile, $storeSessionCookies =
|
24 |
{
|
25 |
$this->filename = $cookieFile;
|
26 |
$this->storeSessionCookies = $storeSessionCookies;
|
27 |
-
|
|
|
28 |
$this->load($cookieFile);
|
29 |
}
|
30 |
}
|
|
|
31 |
/**
|
32 |
* Saves the file when shutting down
|
33 |
*/
|
@@ -35,6 +38,7 @@ class FileCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJar
|
|
35 |
{
|
36 |
$this->save($this->filename);
|
37 |
}
|
|
|
38 |
/**
|
39 |
* Saves the cookies to a file.
|
40 |
*
|
@@ -46,15 +50,17 @@ class FileCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJar
|
|
46 |
$json = [];
|
47 |
foreach ($this as $cookie) {
|
48 |
/** @var SetCookie $cookie */
|
49 |
-
if (
|
50 |
$json[] = $cookie->toArray();
|
51 |
}
|
52 |
}
|
53 |
-
|
54 |
-
|
|
|
55 |
throw new \RuntimeException("Unable to save file {$filename}");
|
56 |
}
|
57 |
}
|
|
|
58 |
/**
|
59 |
* Load cookies from a JSON formatted file.
|
60 |
*
|
@@ -65,18 +71,19 @@ class FileCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJar
|
|
65 |
*/
|
66 |
public function load($filename)
|
67 |
{
|
68 |
-
$json =
|
69 |
-
if (
|
70 |
throw new \RuntimeException("Unable to load file {$filename}");
|
71 |
} elseif ($json === '') {
|
72 |
return;
|
73 |
}
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
78 |
}
|
79 |
-
} elseif (
|
80 |
throw new \RuntimeException("Invalid cookie file: {$filename}");
|
81 |
}
|
82 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
|
|
3 |
|
4 |
/**
|
5 |
* Persists non-session cookies using a JSON formatted file
|
6 |
*/
|
7 |
+
class FileCookieJar extends CookieJar
|
8 |
{
|
9 |
/** @var string filename */
|
10 |
private $filename;
|
11 |
+
|
12 |
/** @var bool Control whether to persist session cookies or not. */
|
13 |
private $storeSessionCookies;
|
14 |
+
|
15 |
/**
|
16 |
* Create a new FileCookieJar object
|
17 |
*
|
21 |
*
|
22 |
* @throws \RuntimeException if the file cannot be found or created
|
23 |
*/
|
24 |
+
public function __construct($cookieFile, $storeSessionCookies = false)
|
25 |
{
|
26 |
$this->filename = $cookieFile;
|
27 |
$this->storeSessionCookies = $storeSessionCookies;
|
28 |
+
|
29 |
+
if (file_exists($cookieFile)) {
|
30 |
$this->load($cookieFile);
|
31 |
}
|
32 |
}
|
33 |
+
|
34 |
/**
|
35 |
* Saves the file when shutting down
|
36 |
*/
|
38 |
{
|
39 |
$this->save($this->filename);
|
40 |
}
|
41 |
+
|
42 |
/**
|
43 |
* Saves the cookies to a file.
|
44 |
*
|
50 |
$json = [];
|
51 |
foreach ($this as $cookie) {
|
52 |
/** @var SetCookie $cookie */
|
53 |
+
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
54 |
$json[] = $cookie->toArray();
|
55 |
}
|
56 |
}
|
57 |
+
|
58 |
+
$jsonStr = \GuzzleHttp\json_encode($json);
|
59 |
+
if (false === file_put_contents($filename, $jsonStr)) {
|
60 |
throw new \RuntimeException("Unable to save file {$filename}");
|
61 |
}
|
62 |
}
|
63 |
+
|
64 |
/**
|
65 |
* Load cookies from a JSON formatted file.
|
66 |
*
|
71 |
*/
|
72 |
public function load($filename)
|
73 |
{
|
74 |
+
$json = file_get_contents($filename);
|
75 |
+
if (false === $json) {
|
76 |
throw new \RuntimeException("Unable to load file {$filename}");
|
77 |
} elseif ($json === '') {
|
78 |
return;
|
79 |
}
|
80 |
+
|
81 |
+
$data = \GuzzleHttp\json_decode($json, true);
|
82 |
+
if (is_array($data)) {
|
83 |
+
foreach (json_decode($json, true) as $cookie) {
|
84 |
+
$this->setCookie(new SetCookie($cookie));
|
85 |
}
|
86 |
+
} elseif (strlen($data)) {
|
87 |
throw new \RuntimeException("Invalid cookie file: {$filename}");
|
88 |
}
|
89 |
}
|
@@ -1,16 +1,17 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie;
|
4 |
|
5 |
/**
|
6 |
* Persists cookies in the client session
|
7 |
*/
|
8 |
-
class SessionCookieJar extends
|
9 |
{
|
10 |
/** @var string session key */
|
11 |
private $sessionKey;
|
|
|
12 |
/** @var bool Control whether to persist session cookies or not. */
|
13 |
private $storeSessionCookies;
|
|
|
14 |
/**
|
15 |
* Create a new SessionCookieJar object
|
16 |
*
|
@@ -19,12 +20,13 @@ class SessionCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\Cookie
|
|
19 |
* @param bool $storeSessionCookies Set to true to store session cookies
|
20 |
* in the cookie jar.
|
21 |
*/
|
22 |
-
public function __construct($sessionKey, $storeSessionCookies =
|
23 |
{
|
24 |
$this->sessionKey = $sessionKey;
|
25 |
$this->storeSessionCookies = $storeSessionCookies;
|
26 |
$this->load();
|
27 |
}
|
|
|
28 |
/**
|
29 |
* Saves cookies to session when shutting down
|
30 |
*/
|
@@ -32,6 +34,7 @@ class SessionCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\Cookie
|
|
32 |
{
|
33 |
$this->save();
|
34 |
}
|
|
|
35 |
/**
|
36 |
* Save cookies to the client session
|
37 |
*/
|
@@ -40,12 +43,14 @@ class SessionCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\Cookie
|
|
40 |
$json = [];
|
41 |
foreach ($this as $cookie) {
|
42 |
/** @var SetCookie $cookie */
|
43 |
-
if (
|
44 |
$json[] = $cookie->toArray();
|
45 |
}
|
46 |
}
|
47 |
-
|
|
|
48 |
}
|
|
|
49 |
/**
|
50 |
* Load the contents of the client session into the data array
|
51 |
*/
|
@@ -54,12 +59,12 @@ class SessionCookieJar extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\Cookie
|
|
54 |
if (!isset($_SESSION[$this->sessionKey])) {
|
55 |
return;
|
56 |
}
|
57 |
-
$data =
|
58 |
-
if (
|
59 |
foreach ($data as $cookie) {
|
60 |
-
$this->setCookie(new
|
61 |
}
|
62 |
-
} elseif (
|
63 |
throw new \RuntimeException("Invalid cookie data");
|
64 |
}
|
65 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
|
|
3 |
|
4 |
/**
|
5 |
* Persists cookies in the client session
|
6 |
*/
|
7 |
+
class SessionCookieJar extends CookieJar
|
8 |
{
|
9 |
/** @var string session key */
|
10 |
private $sessionKey;
|
11 |
+
|
12 |
/** @var bool Control whether to persist session cookies or not. */
|
13 |
private $storeSessionCookies;
|
14 |
+
|
15 |
/**
|
16 |
* Create a new SessionCookieJar object
|
17 |
*
|
20 |
* @param bool $storeSessionCookies Set to true to store session cookies
|
21 |
* in the cookie jar.
|
22 |
*/
|
23 |
+
public function __construct($sessionKey, $storeSessionCookies = false)
|
24 |
{
|
25 |
$this->sessionKey = $sessionKey;
|
26 |
$this->storeSessionCookies = $storeSessionCookies;
|
27 |
$this->load();
|
28 |
}
|
29 |
+
|
30 |
/**
|
31 |
* Saves cookies to session when shutting down
|
32 |
*/
|
34 |
{
|
35 |
$this->save();
|
36 |
}
|
37 |
+
|
38 |
/**
|
39 |
* Save cookies to the client session
|
40 |
*/
|
43 |
$json = [];
|
44 |
foreach ($this as $cookie) {
|
45 |
/** @var SetCookie $cookie */
|
46 |
+
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
47 |
$json[] = $cookie->toArray();
|
48 |
}
|
49 |
}
|
50 |
+
|
51 |
+
$_SESSION[$this->sessionKey] = json_encode($json);
|
52 |
}
|
53 |
+
|
54 |
/**
|
55 |
* Load the contents of the client session into the data array
|
56 |
*/
|
59 |
if (!isset($_SESSION[$this->sessionKey])) {
|
60 |
return;
|
61 |
}
|
62 |
+
$data = json_decode($_SESSION[$this->sessionKey], true);
|
63 |
+
if (is_array($data)) {
|
64 |
foreach ($data as $cookie) {
|
65 |
+
$this->setCookie(new SetCookie($cookie));
|
66 |
}
|
67 |
+
} elseif (strlen($data)) {
|
68 |
throw new \RuntimeException("Invalid cookie data");
|
69 |
}
|
70 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie;
|
4 |
|
5 |
/**
|
6 |
* Set-Cookie object
|
@@ -8,9 +7,21 @@ namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie;
|
|
8 |
class SetCookie
|
9 |
{
|
10 |
/** @var array */
|
11 |
-
private static $defaults = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/** @var array Cookie data */
|
13 |
private $data;
|
|
|
14 |
/**
|
15 |
* Create a new SetCookie object from a string
|
16 |
*
|
@@ -23,23 +34,27 @@ class SetCookie
|
|
23 |
// Create the default return array
|
24 |
$data = self::$defaults;
|
25 |
// Explode the cookie string using a series of semicolons
|
26 |
-
$pieces =
|
27 |
// The name of the cookie (first kvp) must exist and include an equal sign.
|
28 |
-
if (empty($pieces[0]) ||
|
29 |
return new self($data);
|
30 |
}
|
|
|
31 |
// Add the cookie pieces into the parsed data array
|
32 |
foreach ($pieces as $part) {
|
33 |
-
$cookieParts =
|
34 |
-
$key =
|
35 |
-
$value = isset($cookieParts[1])
|
|
|
|
|
|
|
36 |
// Only check for non-cookies when cookies have been found
|
37 |
if (empty($data['Name'])) {
|
38 |
$data['Name'] = $key;
|
39 |
$data['Value'] = $value;
|
40 |
} else {
|
41 |
-
foreach (
|
42 |
-
if (
|
43 |
$data[$search] = $value;
|
44 |
continue 2;
|
45 |
}
|
@@ -47,40 +62,46 @@ class SetCookie
|
|
47 |
$data[$key] = $value;
|
48 |
}
|
49 |
}
|
|
|
50 |
return new self($data);
|
51 |
}
|
|
|
52 |
/**
|
53 |
* @param array $data Array of cookie data provided by a Cookie parser
|
54 |
*/
|
55 |
public function __construct(array $data = [])
|
56 |
{
|
57 |
-
$this->data =
|
58 |
// Extract the Expires value and turn it into a UNIX timestamp if needed
|
59 |
if (!$this->getExpires() && $this->getMaxAge()) {
|
60 |
// Calculate the Expires date
|
61 |
-
$this->setExpires(
|
62 |
-
} elseif ($this->getExpires() &&
|
63 |
$this->setExpires($this->getExpires());
|
64 |
}
|
65 |
}
|
|
|
66 |
public function __toString()
|
67 |
{
|
68 |
$str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
|
69 |
foreach ($this->data as $k => $v) {
|
70 |
-
if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !==
|
71 |
if ($k === 'Expires') {
|
72 |
-
$str .= 'Expires=' .
|
73 |
} else {
|
74 |
-
$str .= ($v ===
|
75 |
}
|
76 |
}
|
77 |
}
|
78 |
-
|
|
|
79 |
}
|
|
|
80 |
public function toArray()
|
81 |
{
|
82 |
return $this->data;
|
83 |
}
|
|
|
84 |
/**
|
85 |
* Get the cookie name
|
86 |
*
|
@@ -90,6 +111,7 @@ class SetCookie
|
|
90 |
{
|
91 |
return $this->data['Name'];
|
92 |
}
|
|
|
93 |
/**
|
94 |
* Set the cookie name
|
95 |
*
|
@@ -99,6 +121,7 @@ class SetCookie
|
|
99 |
{
|
100 |
$this->data['Name'] = $name;
|
101 |
}
|
|
|
102 |
/**
|
103 |
* Get the cookie value
|
104 |
*
|
@@ -108,6 +131,7 @@ class SetCookie
|
|
108 |
{
|
109 |
return $this->data['Value'];
|
110 |
}
|
|
|
111 |
/**
|
112 |
* Set the cookie value
|
113 |
*
|
@@ -117,6 +141,7 @@ class SetCookie
|
|
117 |
{
|
118 |
$this->data['Value'] = $value;
|
119 |
}
|
|
|
120 |
/**
|
121 |
* Get the domain
|
122 |
*
|
@@ -126,6 +151,7 @@ class SetCookie
|
|
126 |
{
|
127 |
return $this->data['Domain'];
|
128 |
}
|
|
|
129 |
/**
|
130 |
* Set the domain of the cookie
|
131 |
*
|
@@ -135,6 +161,7 @@ class SetCookie
|
|
135 |
{
|
136 |
$this->data['Domain'] = $domain;
|
137 |
}
|
|
|
138 |
/**
|
139 |
* Get the path
|
140 |
*
|
@@ -144,6 +171,7 @@ class SetCookie
|
|
144 |
{
|
145 |
return $this->data['Path'];
|
146 |
}
|
|
|
147 |
/**
|
148 |
* Set the path of the cookie
|
149 |
*
|
@@ -153,6 +181,7 @@ class SetCookie
|
|
153 |
{
|
154 |
$this->data['Path'] = $path;
|
155 |
}
|
|
|
156 |
/**
|
157 |
* Maximum lifetime of the cookie in seconds
|
158 |
*
|
@@ -162,6 +191,7 @@ class SetCookie
|
|
162 |
{
|
163 |
return $this->data['Max-Age'];
|
164 |
}
|
|
|
165 |
/**
|
166 |
* Set the max-age of the cookie
|
167 |
*
|
@@ -171,6 +201,7 @@ class SetCookie
|
|
171 |
{
|
172 |
$this->data['Max-Age'] = $maxAge;
|
173 |
}
|
|
|
174 |
/**
|
175 |
* The UNIX timestamp when the cookie Expires
|
176 |
*
|
@@ -180,6 +211,7 @@ class SetCookie
|
|
180 |
{
|
181 |
return $this->data['Expires'];
|
182 |
}
|
|
|
183 |
/**
|
184 |
* Set the unix timestamp for which the cookie will expire
|
185 |
*
|
@@ -187,8 +219,11 @@ class SetCookie
|
|
187 |
*/
|
188 |
public function setExpires($timestamp)
|
189 |
{
|
190 |
-
$this->data['Expires'] =
|
|
|
|
|
191 |
}
|
|
|
192 |
/**
|
193 |
* Get whether or not this is a secure cookie
|
194 |
*
|
@@ -198,6 +233,7 @@ class SetCookie
|
|
198 |
{
|
199 |
return $this->data['Secure'];
|
200 |
}
|
|
|
201 |
/**
|
202 |
* Set whether or not the cookie is secure
|
203 |
*
|
@@ -207,6 +243,7 @@ class SetCookie
|
|
207 |
{
|
208 |
$this->data['Secure'] = $secure;
|
209 |
}
|
|
|
210 |
/**
|
211 |
* Get whether or not this is a session cookie
|
212 |
*
|
@@ -216,6 +253,7 @@ class SetCookie
|
|
216 |
{
|
217 |
return $this->data['Discard'];
|
218 |
}
|
|
|
219 |
/**
|
220 |
* Set whether or not this is a session cookie
|
221 |
*
|
@@ -225,6 +263,7 @@ class SetCookie
|
|
225 |
{
|
226 |
$this->data['Discard'] = $discard;
|
227 |
}
|
|
|
228 |
/**
|
229 |
* Get whether or not this is an HTTP only cookie
|
230 |
*
|
@@ -234,6 +273,7 @@ class SetCookie
|
|
234 |
{
|
235 |
return $this->data['HttpOnly'];
|
236 |
}
|
|
|
237 |
/**
|
238 |
* Set whether or not this is an HTTP only cookie
|
239 |
*
|
@@ -243,6 +283,7 @@ class SetCookie
|
|
243 |
{
|
244 |
$this->data['HttpOnly'] = $httpOnly;
|
245 |
}
|
|
|
246 |
/**
|
247 |
* Check if the cookie matches a path value.
|
248 |
*
|
@@ -263,21 +304,26 @@ class SetCookie
|
|
263 |
public function matchesPath($requestPath)
|
264 |
{
|
265 |
$cookiePath = $this->getPath();
|
|
|
266 |
// Match on exact matches or when path is the default empty "/"
|
267 |
if ($cookiePath === '/' || $cookiePath == $requestPath) {
|
268 |
-
return
|
269 |
}
|
|
|
270 |
// Ensure that the cookie-path is a prefix of the request path.
|
271 |
-
if (0 !==
|
272 |
-
return
|
273 |
}
|
|
|
274 |
// Match if the last character of the cookie-path is "/"
|
275 |
-
if (
|
276 |
-
return
|
277 |
}
|
|
|
278 |
// Match if the first character not included in cookie path is "/"
|
279 |
-
return
|
280 |
}
|
|
|
281 |
/**
|
282 |
* Check if the cookie matches a domain value
|
283 |
*
|
@@ -289,18 +335,22 @@ class SetCookie
|
|
289 |
{
|
290 |
// Remove the leading '.' as per spec in RFC 6265.
|
291 |
// http://tools.ietf.org/html/rfc6265#section-5.2.3
|
292 |
-
$cookieDomain =
|
|
|
293 |
// Domain not set or exact match.
|
294 |
-
if (!$cookieDomain ||
|
295 |
-
return
|
296 |
}
|
|
|
297 |
// Matching the subdomain according to RFC 6265.
|
298 |
// http://tools.ietf.org/html/rfc6265#section-5.1.3
|
299 |
-
if (
|
300 |
-
return
|
301 |
}
|
302 |
-
|
|
|
303 |
}
|
|
|
304 |
/**
|
305 |
* Check if the cookie is expired
|
306 |
*
|
@@ -308,8 +358,9 @@ class SetCookie
|
|
308 |
*/
|
309 |
public function isExpired()
|
310 |
{
|
311 |
-
return $this->getExpires() !== null &&
|
312 |
}
|
|
|
313 |
/**
|
314 |
* Check if the cookie is valid according to RFC 6265
|
315 |
*
|
@@ -319,25 +370,34 @@ class SetCookie
|
|
319 |
{
|
320 |
// Names must not be empty, but can be 0
|
321 |
$name = $this->getName();
|
322 |
-
if (empty($name) &&
|
323 |
return 'The cookie name must not be empty';
|
324 |
}
|
|
|
325 |
// Check if any of the invalid characters are present in the cookie name
|
326 |
-
if (
|
327 |
-
|
|
|
|
|
|
|
|
|
|
|
328 |
}
|
|
|
329 |
// Value must not be empty, but can be 0
|
330 |
$value = $this->getValue();
|
331 |
-
if (empty($value) &&
|
332 |
return 'The cookie value must not be empty';
|
333 |
}
|
|
|
334 |
// Domains must not be empty, but can be 0
|
335 |
// A "0" is not a valid internet domain, but may be used as server name
|
336 |
// in a private network.
|
337 |
$domain = $this->getDomain();
|
338 |
-
if (empty($domain) &&
|
339 |
return 'The cookie domain must not be empty';
|
340 |
}
|
341 |
-
|
|
|
342 |
}
|
343 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
|
|
3 |
|
4 |
/**
|
5 |
* Set-Cookie object
|
7 |
class SetCookie
|
8 |
{
|
9 |
/** @var array */
|
10 |
+
private static $defaults = [
|
11 |
+
'Name' => null,
|
12 |
+
'Value' => null,
|
13 |
+
'Domain' => null,
|
14 |
+
'Path' => '/',
|
15 |
+
'Max-Age' => null,
|
16 |
+
'Expires' => null,
|
17 |
+
'Secure' => false,
|
18 |
+
'Discard' => false,
|
19 |
+
'HttpOnly' => false
|
20 |
+
];
|
21 |
+
|
22 |
/** @var array Cookie data */
|
23 |
private $data;
|
24 |
+
|
25 |
/**
|
26 |
* Create a new SetCookie object from a string
|
27 |
*
|
34 |
// Create the default return array
|
35 |
$data = self::$defaults;
|
36 |
// Explode the cookie string using a series of semicolons
|
37 |
+
$pieces = array_filter(array_map('trim', explode(';', $cookie)));
|
38 |
// The name of the cookie (first kvp) must exist and include an equal sign.
|
39 |
+
if (empty($pieces[0]) || !strpos($pieces[0], '=')) {
|
40 |
return new self($data);
|
41 |
}
|
42 |
+
|
43 |
// Add the cookie pieces into the parsed data array
|
44 |
foreach ($pieces as $part) {
|
45 |
+
$cookieParts = explode('=', $part, 2);
|
46 |
+
$key = trim($cookieParts[0]);
|
47 |
+
$value = isset($cookieParts[1])
|
48 |
+
? trim($cookieParts[1], " \n\r\t\0\x0B")
|
49 |
+
: true;
|
50 |
+
|
51 |
// Only check for non-cookies when cookies have been found
|
52 |
if (empty($data['Name'])) {
|
53 |
$data['Name'] = $key;
|
54 |
$data['Value'] = $value;
|
55 |
} else {
|
56 |
+
foreach (array_keys(self::$defaults) as $search) {
|
57 |
+
if (!strcasecmp($search, $key)) {
|
58 |
$data[$search] = $value;
|
59 |
continue 2;
|
60 |
}
|
62 |
$data[$key] = $value;
|
63 |
}
|
64 |
}
|
65 |
+
|
66 |
return new self($data);
|
67 |
}
|
68 |
+
|
69 |
/**
|
70 |
* @param array $data Array of cookie data provided by a Cookie parser
|
71 |
*/
|
72 |
public function __construct(array $data = [])
|
73 |
{
|
74 |
+
$this->data = array_replace(self::$defaults, $data);
|
75 |
// Extract the Expires value and turn it into a UNIX timestamp if needed
|
76 |
if (!$this->getExpires() && $this->getMaxAge()) {
|
77 |
// Calculate the Expires date
|
78 |
+
$this->setExpires(time() + $this->getMaxAge());
|
79 |
+
} elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
|
80 |
$this->setExpires($this->getExpires());
|
81 |
}
|
82 |
}
|
83 |
+
|
84 |
public function __toString()
|
85 |
{
|
86 |
$str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
|
87 |
foreach ($this->data as $k => $v) {
|
88 |
+
if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
|
89 |
if ($k === 'Expires') {
|
90 |
+
$str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
|
91 |
} else {
|
92 |
+
$str .= ($v === true ? $k : "{$k}={$v}") . '; ';
|
93 |
}
|
94 |
}
|
95 |
}
|
96 |
+
|
97 |
+
return rtrim($str, '; ');
|
98 |
}
|
99 |
+
|
100 |
public function toArray()
|
101 |
{
|
102 |
return $this->data;
|
103 |
}
|
104 |
+
|
105 |
/**
|
106 |
* Get the cookie name
|
107 |
*
|
111 |
{
|
112 |
return $this->data['Name'];
|
113 |
}
|
114 |
+
|
115 |
/**
|
116 |
* Set the cookie name
|
117 |
*
|
121 |
{
|
122 |
$this->data['Name'] = $name;
|
123 |
}
|
124 |
+
|
125 |
/**
|
126 |
* Get the cookie value
|
127 |
*
|
131 |
{
|
132 |
return $this->data['Value'];
|
133 |
}
|
134 |
+
|
135 |
/**
|
136 |
* Set the cookie value
|
137 |
*
|
141 |
{
|
142 |
$this->data['Value'] = $value;
|
143 |
}
|
144 |
+
|
145 |
/**
|
146 |
* Get the domain
|
147 |
*
|
151 |
{
|
152 |
return $this->data['Domain'];
|
153 |
}
|
154 |
+
|
155 |
/**
|
156 |
* Set the domain of the cookie
|
157 |
*
|
161 |
{
|
162 |
$this->data['Domain'] = $domain;
|
163 |
}
|
164 |
+
|
165 |
/**
|
166 |
* Get the path
|
167 |
*
|
171 |
{
|
172 |
return $this->data['Path'];
|
173 |
}
|
174 |
+
|
175 |
/**
|
176 |
* Set the path of the cookie
|
177 |
*
|
181 |
{
|
182 |
$this->data['Path'] = $path;
|
183 |
}
|
184 |
+
|
185 |
/**
|
186 |
* Maximum lifetime of the cookie in seconds
|
187 |
*
|
191 |
{
|
192 |
return $this->data['Max-Age'];
|
193 |
}
|
194 |
+
|
195 |
/**
|
196 |
* Set the max-age of the cookie
|
197 |
*
|
201 |
{
|
202 |
$this->data['Max-Age'] = $maxAge;
|
203 |
}
|
204 |
+
|
205 |
/**
|
206 |
* The UNIX timestamp when the cookie Expires
|
207 |
*
|
211 |
{
|
212 |
return $this->data['Expires'];
|
213 |
}
|
214 |
+
|
215 |
/**
|
216 |
* Set the unix timestamp for which the cookie will expire
|
217 |
*
|
219 |
*/
|
220 |
public function setExpires($timestamp)
|
221 |
{
|
222 |
+
$this->data['Expires'] = is_numeric($timestamp)
|
223 |
+
? (int) $timestamp
|
224 |
+
: strtotime($timestamp);
|
225 |
}
|
226 |
+
|
227 |
/**
|
228 |
* Get whether or not this is a secure cookie
|
229 |
*
|
233 |
{
|
234 |
return $this->data['Secure'];
|
235 |
}
|
236 |
+
|
237 |
/**
|
238 |
* Set whether or not the cookie is secure
|
239 |
*
|
243 |
{
|
244 |
$this->data['Secure'] = $secure;
|
245 |
}
|
246 |
+
|
247 |
/**
|
248 |
* Get whether or not this is a session cookie
|
249 |
*
|
253 |
{
|
254 |
return $this->data['Discard'];
|
255 |
}
|
256 |
+
|
257 |
/**
|
258 |
* Set whether or not this is a session cookie
|
259 |
*
|
263 |
{
|
264 |
$this->data['Discard'] = $discard;
|
265 |
}
|
266 |
+
|
267 |
/**
|
268 |
* Get whether or not this is an HTTP only cookie
|
269 |
*
|
273 |
{
|
274 |
return $this->data['HttpOnly'];
|
275 |
}
|
276 |
+
|
277 |
/**
|
278 |
* Set whether or not this is an HTTP only cookie
|
279 |
*
|
283 |
{
|
284 |
$this->data['HttpOnly'] = $httpOnly;
|
285 |
}
|
286 |
+
|
287 |
/**
|
288 |
* Check if the cookie matches a path value.
|
289 |
*
|
304 |
public function matchesPath($requestPath)
|
305 |
{
|
306 |
$cookiePath = $this->getPath();
|
307 |
+
|
308 |
// Match on exact matches or when path is the default empty "/"
|
309 |
if ($cookiePath === '/' || $cookiePath == $requestPath) {
|
310 |
+
return true;
|
311 |
}
|
312 |
+
|
313 |
// Ensure that the cookie-path is a prefix of the request path.
|
314 |
+
if (0 !== strpos($requestPath, $cookiePath)) {
|
315 |
+
return false;
|
316 |
}
|
317 |
+
|
318 |
// Match if the last character of the cookie-path is "/"
|
319 |
+
if (substr($cookiePath, -1, 1) === '/') {
|
320 |
+
return true;
|
321 |
}
|
322 |
+
|
323 |
// Match if the first character not included in cookie path is "/"
|
324 |
+
return substr($requestPath, strlen($cookiePath), 1) === '/';
|
325 |
}
|
326 |
+
|
327 |
/**
|
328 |
* Check if the cookie matches a domain value
|
329 |
*
|
335 |
{
|
336 |
// Remove the leading '.' as per spec in RFC 6265.
|
337 |
// http://tools.ietf.org/html/rfc6265#section-5.2.3
|
338 |
+
$cookieDomain = ltrim($this->getDomain(), '.');
|
339 |
+
|
340 |
// Domain not set or exact match.
|
341 |
+
if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
|
342 |
+
return true;
|
343 |
}
|
344 |
+
|
345 |
// Matching the subdomain according to RFC 6265.
|
346 |
// http://tools.ietf.org/html/rfc6265#section-5.1.3
|
347 |
+
if (filter_var($domain, FILTER_VALIDATE_IP)) {
|
348 |
+
return false;
|
349 |
}
|
350 |
+
|
351 |
+
return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain);
|
352 |
}
|
353 |
+
|
354 |
/**
|
355 |
* Check if the cookie is expired
|
356 |
*
|
358 |
*/
|
359 |
public function isExpired()
|
360 |
{
|
361 |
+
return $this->getExpires() !== null && time() > $this->getExpires();
|
362 |
}
|
363 |
+
|
364 |
/**
|
365 |
* Check if the cookie is valid according to RFC 6265
|
366 |
*
|
370 |
{
|
371 |
// Names must not be empty, but can be 0
|
372 |
$name = $this->getName();
|
373 |
+
if (empty($name) && !is_numeric($name)) {
|
374 |
return 'The cookie name must not be empty';
|
375 |
}
|
376 |
+
|
377 |
// Check if any of the invalid characters are present in the cookie name
|
378 |
+
if (preg_match(
|
379 |
+
'/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
|
380 |
+
$name
|
381 |
+
)) {
|
382 |
+
return 'Cookie name must not contain invalid characters: ASCII '
|
383 |
+
. 'Control characters (0-31;127), space, tab and the '
|
384 |
+
. 'following characters: ()<>@,;:\"/?={}';
|
385 |
}
|
386 |
+
|
387 |
// Value must not be empty, but can be 0
|
388 |
$value = $this->getValue();
|
389 |
+
if (empty($value) && !is_numeric($value)) {
|
390 |
return 'The cookie value must not be empty';
|
391 |
}
|
392 |
+
|
393 |
// Domains must not be empty, but can be 0
|
394 |
// A "0" is not a valid internet domain, but may be used as server name
|
395 |
// in a private network.
|
396 |
$domain = $this->getDomain();
|
397 |
+
if (empty($domain) && !is_numeric($domain)) {
|
398 |
return 'The cookie domain must not be empty';
|
399 |
}
|
400 |
+
|
401 |
+
return true;
|
402 |
}
|
403 |
}
|
@@ -1,18 +1,26 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
7 |
/**
|
8 |
* Exception when an HTTP error occurs (4xx or 5xx error)
|
9 |
*/
|
10 |
-
class BadResponseException extends
|
11 |
{
|
12 |
-
public function __construct(
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
14 |
if (null === $response) {
|
15 |
-
|
|
|
|
|
|
|
16 |
}
|
17 |
parent::__construct($message, $request, $response, $previous, $handlerContext);
|
18 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
|
|
|
|
|
7 |
/**
|
8 |
* Exception when an HTTP error occurs (4xx or 5xx error)
|
9 |
*/
|
10 |
+
class BadResponseException extends RequestException
|
11 |
{
|
12 |
+
public function __construct(
|
13 |
+
$message,
|
14 |
+
RequestInterface $request,
|
15 |
+
ResponseInterface $response = null,
|
16 |
+
\Exception $previous = null,
|
17 |
+
array $handlerContext = []
|
18 |
+
) {
|
19 |
if (null === $response) {
|
20 |
+
@trigger_error(
|
21 |
+
'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.',
|
22 |
+
E_USER_DEPRECATED
|
23 |
+
);
|
24 |
}
|
25 |
parent::__construct($message, $request, $response, $previous, $handlerContext);
|
26 |
}
|
@@ -1,10 +1,7 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception;
|
4 |
|
5 |
/**
|
6 |
* Exception when a client error is encountered (4xx codes)
|
7 |
*/
|
8 |
-
class ClientException extends
|
9 |
-
{
|
10 |
-
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
|
|
3 |
|
4 |
/**
|
5 |
* Exception when a client error is encountered (4xx codes)
|
6 |
*/
|
7 |
+
class ClientException extends BadResponseException {}
|
|
|
|
@@ -1,19 +1,24 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
/**
|
7 |
* Exception thrown when a connection cannot be established.
|
8 |
*
|
9 |
* Note that no response is present for a ConnectException
|
10 |
*/
|
11 |
-
class ConnectException extends
|
12 |
{
|
13 |
-
public function __construct(
|
14 |
-
|
|
|
|
|
|
|
|
|
15 |
parent::__construct($message, $request, null, $previous, $handlerContext);
|
16 |
}
|
|
|
17 |
/**
|
18 |
* @return null
|
19 |
*/
|
@@ -21,11 +26,12 @@ class ConnectException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Req
|
|
21 |
{
|
22 |
return null;
|
23 |
}
|
|
|
24 |
/**
|
25 |
* @return bool
|
26 |
*/
|
27 |
public function hasResponse()
|
28 |
{
|
29 |
-
return
|
30 |
}
|
31 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Exception thrown when a connection cannot be established.
|
8 |
*
|
9 |
* Note that no response is present for a ConnectException
|
10 |
*/
|
11 |
+
class ConnectException extends RequestException
|
12 |
{
|
13 |
+
public function __construct(
|
14 |
+
$message,
|
15 |
+
RequestInterface $request,
|
16 |
+
\Exception $previous = null,
|
17 |
+
array $handlerContext = []
|
18 |
+
) {
|
19 |
parent::__construct($message, $request, null, $previous, $handlerContext);
|
20 |
}
|
21 |
+
|
22 |
/**
|
23 |
* @return null
|
24 |
*/
|
26 |
{
|
27 |
return null;
|
28 |
}
|
29 |
+
|
30 |
/**
|
31 |
* @return bool
|
32 |
*/
|
33 |
public function hasResponse()
|
34 |
{
|
35 |
+
return false;
|
36 |
}
|
37 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception;
|
4 |
|
5 |
/**
|
6 |
* @method string getMessage()
|
@@ -11,6 +10,4 @@ namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception;
|
|
11 |
* @method array getTrace()
|
12 |
* @method string getTraceAsString()
|
13 |
*/
|
14 |
-
interface GuzzleException
|
15 |
-
{
|
16 |
-
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
|
|
3 |
|
4 |
/**
|
5 |
* @method string getMessage()
|
10 |
* @method array getTrace()
|
11 |
* @method string getTraceAsString()
|
12 |
*/
|
13 |
+
interface GuzzleException {}
|
|
|
|
@@ -1,31 +1,42 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
9 |
/**
|
10 |
* HTTP Request exception
|
11 |
*/
|
12 |
-
class RequestException extends
|
13 |
{
|
14 |
/** @var RequestInterface */
|
15 |
private $request;
|
|
|
16 |
/** @var ResponseInterface */
|
17 |
private $response;
|
|
|
18 |
/** @var array */
|
19 |
private $handlerContext;
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
// Set the code of the exception if the response is set and not future.
|
23 |
-
$code = $response &&
|
|
|
|
|
24 |
parent::__construct($message, $code, $previous);
|
25 |
$this->request = $request;
|
26 |
$this->response = $response;
|
27 |
$this->handlerContext = $handlerContext;
|
28 |
}
|
|
|
29 |
/**
|
30 |
* Wrap non-RequestExceptions with a RequestException
|
31 |
*
|
@@ -34,10 +45,13 @@ class RequestException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Tra
|
|
34 |
*
|
35 |
* @return RequestException
|
36 |
*/
|
37 |
-
public static function wrapException(
|
38 |
{
|
39 |
-
return $e instanceof
|
|
|
|
|
40 |
}
|
|
|
41 |
/**
|
42 |
* Factory method to create a new exception with a normalized error message
|
43 |
*
|
@@ -48,33 +62,57 @@ class RequestException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Tra
|
|
48 |
*
|
49 |
* @return self
|
50 |
*/
|
51 |
-
public static function create(
|
52 |
-
|
|
|
|
|
|
|
|
|
53 |
if (!$response) {
|
54 |
-
return new self(
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
}
|
56 |
-
|
|
|
57 |
if ($level === 4) {
|
58 |
$label = 'Client error';
|
59 |
-
$className =
|
60 |
} elseif ($level === 5) {
|
61 |
$label = 'Server error';
|
62 |
-
$className =
|
63 |
} else {
|
64 |
$label = 'Unsuccessful request';
|
65 |
$className = __CLASS__;
|
66 |
}
|
|
|
67 |
$uri = $request->getUri();
|
68 |
$uri = static::obfuscateUri($uri);
|
|
|
69 |
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
70 |
// <html> ... (truncated)
|
71 |
-
$message =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
$summary = static::getResponseBodySummary($response);
|
|
|
73 |
if ($summary !== null) {
|
74 |
$message .= ":\n{$summary}\n";
|
75 |
}
|
|
|
76 |
return new $className($message, $request, $response, $previous, $ctx);
|
77 |
}
|
|
|
78 |
/**
|
79 |
* Get a short summary of the response
|
80 |
*
|
@@ -84,28 +122,36 @@ class RequestException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Tra
|
|
84 |
*
|
85 |
* @return string|null
|
86 |
*/
|
87 |
-
public static function getResponseBodySummary(
|
88 |
{
|
89 |
$body = $response->getBody();
|
|
|
90 |
if (!$body->isSeekable()) {
|
91 |
return null;
|
92 |
}
|
|
|
93 |
$size = $body->getSize();
|
|
|
94 |
if ($size === 0) {
|
95 |
return null;
|
96 |
}
|
|
|
97 |
$summary = $body->read(120);
|
98 |
$body->rewind();
|
|
|
99 |
if ($size > 120) {
|
100 |
$summary .= ' (truncated...)';
|
101 |
}
|
|
|
102 |
// Matches any printable character, including unicode characters:
|
103 |
// letters, marks, numbers, punctuation, spacing, and separators.
|
104 |
-
if (
|
105 |
return null;
|
106 |
}
|
|
|
107 |
return $summary;
|
108 |
}
|
|
|
109 |
/**
|
110 |
* Obfuscates URI if there is an username and a password present
|
111 |
*
|
@@ -116,11 +162,14 @@ class RequestException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Tra
|
|
116 |
private static function obfuscateUri($uri)
|
117 |
{
|
118 |
$userInfo = $uri->getUserInfo();
|
119 |
-
|
120 |
-
|
|
|
121 |
}
|
|
|
122 |
return $uri;
|
123 |
}
|
|
|
124 |
/**
|
125 |
* Get the request that caused the exception
|
126 |
*
|
@@ -130,6 +179,7 @@ class RequestException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Tra
|
|
130 |
{
|
131 |
return $this->request;
|
132 |
}
|
|
|
133 |
/**
|
134 |
* Get the associated response
|
135 |
*
|
@@ -139,6 +189,7 @@ class RequestException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Tra
|
|
139 |
{
|
140 |
return $this->response;
|
141 |
}
|
|
|
142 |
/**
|
143 |
* Check if a response was received
|
144 |
*
|
@@ -148,6 +199,7 @@ class RequestException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\Tra
|
|
148 |
{
|
149 |
return $this->response !== null;
|
150 |
}
|
|
|
151 |
/**
|
152 |
* Get contextual information about the error from the underlying handler.
|
153 |
*
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
+
use Psr\Http\Message\UriInterface;
|
8 |
|
|
|
|
|
|
|
|
|
9 |
/**
|
10 |
* HTTP Request exception
|
11 |
*/
|
12 |
+
class RequestException extends TransferException
|
13 |
{
|
14 |
/** @var RequestInterface */
|
15 |
private $request;
|
16 |
+
|
17 |
/** @var ResponseInterface */
|
18 |
private $response;
|
19 |
+
|
20 |
/** @var array */
|
21 |
private $handlerContext;
|
22 |
+
|
23 |
+
public function __construct(
|
24 |
+
$message,
|
25 |
+
RequestInterface $request,
|
26 |
+
ResponseInterface $response = null,
|
27 |
+
\Exception $previous = null,
|
28 |
+
array $handlerContext = []
|
29 |
+
) {
|
30 |
// Set the code of the exception if the response is set and not future.
|
31 |
+
$code = $response && !($response instanceof PromiseInterface)
|
32 |
+
? $response->getStatusCode()
|
33 |
+
: 0;
|
34 |
parent::__construct($message, $code, $previous);
|
35 |
$this->request = $request;
|
36 |
$this->response = $response;
|
37 |
$this->handlerContext = $handlerContext;
|
38 |
}
|
39 |
+
|
40 |
/**
|
41 |
* Wrap non-RequestExceptions with a RequestException
|
42 |
*
|
45 |
*
|
46 |
* @return RequestException
|
47 |
*/
|
48 |
+
public static function wrapException(RequestInterface $request, \Exception $e)
|
49 |
{
|
50 |
+
return $e instanceof RequestException
|
51 |
+
? $e
|
52 |
+
: new RequestException($e->getMessage(), $request, null, $e);
|
53 |
}
|
54 |
+
|
55 |
/**
|
56 |
* Factory method to create a new exception with a normalized error message
|
57 |
*
|
62 |
*
|
63 |
* @return self
|
64 |
*/
|
65 |
+
public static function create(
|
66 |
+
RequestInterface $request,
|
67 |
+
ResponseInterface $response = null,
|
68 |
+
\Exception $previous = null,
|
69 |
+
array $ctx = []
|
70 |
+
) {
|
71 |
if (!$response) {
|
72 |
+
return new self(
|
73 |
+
'Error completing request',
|
74 |
+
$request,
|
75 |
+
null,
|
76 |
+
$previous,
|
77 |
+
$ctx
|
78 |
+
);
|
79 |
}
|
80 |
+
|
81 |
+
$level = (int) floor($response->getStatusCode() / 100);
|
82 |
if ($level === 4) {
|
83 |
$label = 'Client error';
|
84 |
+
$className = ClientException::class;
|
85 |
} elseif ($level === 5) {
|
86 |
$label = 'Server error';
|
87 |
+
$className = ServerException::class;
|
88 |
} else {
|
89 |
$label = 'Unsuccessful request';
|
90 |
$className = __CLASS__;
|
91 |
}
|
92 |
+
|
93 |
$uri = $request->getUri();
|
94 |
$uri = static::obfuscateUri($uri);
|
95 |
+
|
96 |
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
97 |
// <html> ... (truncated)
|
98 |
+
$message = sprintf(
|
99 |
+
'%s: `%s %s` resulted in a `%s %s` response',
|
100 |
+
$label,
|
101 |
+
$request->getMethod(),
|
102 |
+
$uri,
|
103 |
+
$response->getStatusCode(),
|
104 |
+
$response->getReasonPhrase()
|
105 |
+
);
|
106 |
+
|
107 |
$summary = static::getResponseBodySummary($response);
|
108 |
+
|
109 |
if ($summary !== null) {
|
110 |
$message .= ":\n{$summary}\n";
|
111 |
}
|
112 |
+
|
113 |
return new $className($message, $request, $response, $previous, $ctx);
|
114 |
}
|
115 |
+
|
116 |
/**
|
117 |
* Get a short summary of the response
|
118 |
*
|
122 |
*
|
123 |
* @return string|null
|
124 |
*/
|
125 |
+
public static function getResponseBodySummary(ResponseInterface $response)
|
126 |
{
|
127 |
$body = $response->getBody();
|
128 |
+
|
129 |
if (!$body->isSeekable()) {
|
130 |
return null;
|
131 |
}
|
132 |
+
|
133 |
$size = $body->getSize();
|
134 |
+
|
135 |
if ($size === 0) {
|
136 |
return null;
|
137 |
}
|
138 |
+
|
139 |
$summary = $body->read(120);
|
140 |
$body->rewind();
|
141 |
+
|
142 |
if ($size > 120) {
|
143 |
$summary .= ' (truncated...)';
|
144 |
}
|
145 |
+
|
146 |
// Matches any printable character, including unicode characters:
|
147 |
// letters, marks, numbers, punctuation, spacing, and separators.
|
148 |
+
if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
|
149 |
return null;
|
150 |
}
|
151 |
+
|
152 |
return $summary;
|
153 |
}
|
154 |
+
|
155 |
/**
|
156 |
* Obfuscates URI if there is an username and a password present
|
157 |
*
|
162 |
private static function obfuscateUri($uri)
|
163 |
{
|
164 |
$userInfo = $uri->getUserInfo();
|
165 |
+
|
166 |
+
if (false !== ($pos = strpos($userInfo, ':'))) {
|
167 |
+
return $uri->withUserInfo(substr($userInfo, 0, $pos), '***');
|
168 |
}
|
169 |
+
|
170 |
return $uri;
|
171 |
}
|
172 |
+
|
173 |
/**
|
174 |
* Get the request that caused the exception
|
175 |
*
|
179 |
{
|
180 |
return $this->request;
|
181 |
}
|
182 |
+
|
183 |
/**
|
184 |
* Get the associated response
|
185 |
*
|
189 |
{
|
190 |
return $this->response;
|
191 |
}
|
192 |
+
|
193 |
/**
|
194 |
* Check if a response was received
|
195 |
*
|
199 |
{
|
200 |
return $this->response !== null;
|
201 |
}
|
202 |
+
|
203 |
/**
|
204 |
* Get contextual information about the error from the underlying handler.
|
205 |
*
|
@@ -1,20 +1,22 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Exception thrown when a seek fails on a stream.
|
8 |
*/
|
9 |
-
class SeekException extends \RuntimeException implements
|
10 |
{
|
11 |
private $stream;
|
12 |
-
|
|
|
13 |
{
|
14 |
$this->stream = $stream;
|
15 |
$msg = $msg ?: 'Could not seek the stream to position ' . $pos;
|
16 |
parent::__construct($msg);
|
17 |
}
|
|
|
18 |
/**
|
19 |
* @return StreamInterface
|
20 |
*/
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Exception thrown when a seek fails on a stream.
|
8 |
*/
|
9 |
+
class SeekException extends \RuntimeException implements GuzzleException
|
10 |
{
|
11 |
private $stream;
|
12 |
+
|
13 |
+
public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
|
14 |
{
|
15 |
$this->stream = $stream;
|
16 |
$msg = $msg ?: 'Could not seek the stream to position ' . $pos;
|
17 |
parent::__construct($msg);
|
18 |
}
|
19 |
+
|
20 |
/**
|
21 |
* @return StreamInterface
|
22 |
*/
|
@@ -1,10 +1,7 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception;
|
4 |
|
5 |
/**
|
6 |
* Exception when a server error is encountered (5xx codes)
|
7 |
*/
|
8 |
-
class ServerException extends
|
9 |
-
{
|
10 |
-
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
|
|
3 |
|
4 |
/**
|
5 |
* Exception when a server error is encountered (5xx codes)
|
6 |
*/
|
7 |
+
class ServerException extends BadResponseException {}
|
|
|
|
@@ -1,7 +1,4 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
class TooManyRedirectsException extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\RequestException
|
6 |
-
{
|
7 |
-
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
|
4 |
+
class TooManyRedirectsException extends RequestException {}
|
|
|
|
|
|
|
|
@@ -1,7 +1,4 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
class TransferException extends \RuntimeException implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\GuzzleException
|
6 |
-
{
|
7 |
-
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
|
4 |
+
class TransferException extends \RuntimeException implements GuzzleException {}
|
|
|
|
|
|
|
|
@@ -1,23 +1,25 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\RequestException;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\ConnectException;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\FulfilledPromise;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\LazyOpenStream;
|
10 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\TransferStats;
|
11 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
12 |
/**
|
13 |
* Creates curl resources from a request
|
14 |
*/
|
15 |
-
class CurlFactory implements
|
16 |
{
|
17 |
/** @var array */
|
18 |
private $handles = [];
|
|
|
19 |
/** @var int Total number of idle handles to keep in cache */
|
20 |
private $maxHandles;
|
|
|
21 |
/**
|
22 |
* @param int $maxHandles Maximum number of idle handles.
|
23 |
*/
|
@@ -25,13 +27,15 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
25 |
{
|
26 |
$this->maxHandles = $maxHandles;
|
27 |
}
|
28 |
-
|
|
|
29 |
{
|
30 |
if (isset($options['curl']['body_as_string'])) {
|
31 |
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
32 |
unset($options['curl']['body_as_string']);
|
33 |
}
|
34 |
-
|
|
|
35 |
$easy->request = $request;
|
36 |
$easy->options = $options;
|
37 |
$conf = $this->getDefaultConf($easy);
|
@@ -39,34 +43,42 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
39 |
$this->applyHandlerOptions($easy, $conf);
|
40 |
$this->applyHeaders($easy, $conf);
|
41 |
unset($conf['_headers']);
|
|
|
42 |
// Add handler options from the request configuration options
|
43 |
if (isset($options['curl'])) {
|
44 |
-
$conf =
|
45 |
}
|
46 |
-
|
47 |
-
$
|
48 |
-
|
|
|
|
|
|
|
|
|
49 |
return $easy;
|
50 |
}
|
51 |
-
|
|
|
52 |
{
|
53 |
$resource = $easy->handle;
|
54 |
unset($easy->handle);
|
55 |
-
|
56 |
-
|
|
|
57 |
} else {
|
58 |
// Remove all callback functions as they can hold onto references
|
59 |
// and are not cleaned up by curl_reset. Using curl_setopt_array
|
60 |
// does not work for some reason, so removing each one
|
61 |
// individually.
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
$this->handles[] = $resource;
|
68 |
}
|
69 |
}
|
|
|
70 |
/**
|
71 |
* Completes a cURL transaction, either returning a response promise or a
|
72 |
* rejected promise.
|
@@ -77,122 +89,201 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
77 |
*
|
78 |
* @return \GuzzleHttp\Promise\PromiseInterface
|
79 |
*/
|
80 |
-
public static function finish(
|
81 |
-
|
|
|
|
|
|
|
82 |
if (isset($easy->options['on_stats'])) {
|
83 |
self::invokeStats($easy);
|
84 |
}
|
|
|
85 |
if (!$easy->response || $easy->errno) {
|
86 |
return self::finishError($handler, $easy, $factory);
|
87 |
}
|
|
|
88 |
// Return the response if it is present and there is no error.
|
89 |
$factory->release($easy);
|
|
|
90 |
// Rewind the body of the response if possible.
|
91 |
$body = $easy->response->getBody();
|
92 |
if ($body->isSeekable()) {
|
93 |
$body->rewind();
|
94 |
}
|
95 |
-
|
|
|
96 |
}
|
97 |
-
|
|
|
98 |
{
|
99 |
-
$curlStats =
|
100 |
-
$stats = new
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
105 |
// Get error information and release the handle to the factory.
|
106 |
-
$ctx = [
|
|
|
|
|
|
|
107 |
$factory->release($easy);
|
|
|
108 |
// Retry when nothing is present or when curl failed to rewind.
|
109 |
-
if (empty($easy->options['_err_message'])
|
|
|
|
|
110 |
return self::retryFailedRewind($handler, $easy, $ctx);
|
111 |
}
|
|
|
112 |
return self::createRejection($easy, $ctx);
|
113 |
}
|
114 |
-
|
|
|
115 |
{
|
116 |
-
static $connectionErrors = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
// If an exception was encountered during the onHeaders event, then
|
118 |
// return a rejected promise that wraps that exception.
|
119 |
if ($easy->onHeadersException) {
|
120 |
-
return \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
// Create a connection exception if it was a specific error code.
|
124 |
-
$error = isset($connectionErrors[$easy->errno])
|
125 |
-
|
|
|
|
|
|
|
126 |
}
|
127 |
-
|
|
|
128 |
{
|
129 |
-
$conf = [
|
130 |
-
|
131 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
}
|
|
|
133 |
$version = $easy->request->getProtocolVersion();
|
134 |
if ($version == 1.1) {
|
135 |
-
$conf[
|
136 |
} elseif ($version == 2.0) {
|
137 |
-
$conf[
|
138 |
} else {
|
139 |
-
$conf[
|
140 |
}
|
|
|
141 |
return $conf;
|
142 |
}
|
143 |
-
|
|
|
144 |
{
|
145 |
$body = $easy->request->getBody();
|
146 |
$size = $body->getSize();
|
|
|
147 |
if ($size === null || $size > 0) {
|
148 |
$this->applyBody($easy->request, $easy->options, $conf);
|
149 |
return;
|
150 |
}
|
|
|
151 |
$method = $easy->request->getMethod();
|
152 |
if ($method === 'PUT' || $method === 'POST') {
|
153 |
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
154 |
if (!$easy->request->hasHeader('Content-Length')) {
|
155 |
-
$conf[
|
156 |
}
|
157 |
} elseif ($method === 'HEAD') {
|
158 |
-
$conf[
|
159 |
-
unset(
|
|
|
|
|
|
|
|
|
|
|
160 |
}
|
161 |
}
|
162 |
-
|
|
|
163 |
{
|
164 |
-
$size = $request->hasHeader('Content-Length')
|
|
|
|
|
|
|
165 |
// Send the body as a string if the size is less than 1MB OR if the
|
166 |
// [curl][body_as_string] request value is set.
|
167 |
-
if ($size !== null && $size < 1000000 ||
|
168 |
-
$
|
|
|
|
|
169 |
// Don't duplicate the Content-Length header
|
170 |
$this->removeHeader('Content-Length', $conf);
|
171 |
$this->removeHeader('Transfer-Encoding', $conf);
|
172 |
} else {
|
173 |
-
$conf[
|
174 |
if ($size !== null) {
|
175 |
-
$conf[
|
176 |
$this->removeHeader('Content-Length', $conf);
|
177 |
}
|
178 |
$body = $request->getBody();
|
179 |
if ($body->isSeekable()) {
|
180 |
$body->rewind();
|
181 |
}
|
182 |
-
$conf[
|
183 |
return $body->read($length);
|
184 |
};
|
185 |
}
|
|
|
186 |
// If the Expect header is not present, prevent curl from adding it
|
187 |
if (!$request->hasHeader('Expect')) {
|
188 |
-
$conf[
|
189 |
}
|
|
|
190 |
// cURL sometimes adds a content-type by default. Prevent this.
|
191 |
if (!$request->hasHeader('Content-Type')) {
|
192 |
-
$conf[
|
193 |
}
|
194 |
}
|
195 |
-
|
|
|
196 |
{
|
197 |
foreach ($conf['_headers'] as $name => $values) {
|
198 |
foreach ($values as $value) {
|
@@ -200,17 +291,19 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
200 |
if ($value === '') {
|
201 |
// cURL requires a special format for empty headers.
|
202 |
// See https://github.com/guzzle/guzzle/issues/1882 for more details.
|
203 |
-
$conf[
|
204 |
} else {
|
205 |
-
$conf[
|
206 |
}
|
207 |
}
|
208 |
}
|
|
|
209 |
// Remove the Accept header if one was not set
|
210 |
if (!$easy->request->hasHeader('Accept')) {
|
211 |
-
$conf[
|
212 |
}
|
213 |
}
|
|
|
214 |
/**
|
215 |
* Remove a header from the options array.
|
216 |
*
|
@@ -219,143 +312,170 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
219 |
*/
|
220 |
private function removeHeader($name, array &$options)
|
221 |
{
|
222 |
-
foreach (
|
223 |
-
if (
|
224 |
unset($options['_headers'][$key]);
|
225 |
return;
|
226 |
}
|
227 |
}
|
228 |
}
|
229 |
-
|
|
|
230 |
{
|
231 |
$options = $easy->options;
|
232 |
if (isset($options['verify'])) {
|
233 |
-
if ($options['verify'] ===
|
234 |
-
unset($conf[
|
235 |
-
$conf[
|
236 |
-
$conf[
|
237 |
} else {
|
238 |
-
$conf[
|
239 |
-
$conf[
|
240 |
-
if (
|
241 |
// Throw an error if the file/folder/link path is not valid or doesn't exist.
|
242 |
-
if (
|
243 |
-
throw new \InvalidArgumentException(
|
|
|
|
|
244 |
}
|
245 |
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
|
246 |
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
|
247 |
-
if (
|
248 |
-
$
|
|
|
249 |
} else {
|
250 |
-
$conf[
|
251 |
}
|
252 |
}
|
253 |
}
|
254 |
}
|
|
|
255 |
if (!empty($options['decode_content'])) {
|
256 |
$accept = $easy->request->getHeaderLine('Accept-Encoding');
|
257 |
if ($accept) {
|
258 |
-
$conf[
|
259 |
} else {
|
260 |
-
$conf[
|
261 |
// Don't let curl send the header over the wire
|
262 |
-
$conf[
|
263 |
}
|
264 |
}
|
|
|
265 |
if (isset($options['sink'])) {
|
266 |
$sink = $options['sink'];
|
267 |
-
if (
|
268 |
-
$sink = \
|
269 |
-
} elseif (
|
270 |
// Ensure that the directory exists before failing in curl.
|
271 |
-
throw new \RuntimeException(
|
|
|
|
|
|
|
|
|
272 |
} else {
|
273 |
-
$sink = new
|
274 |
}
|
275 |
$easy->sink = $sink;
|
276 |
-
$conf[
|
277 |
return $sink->write($write);
|
278 |
};
|
279 |
} else {
|
280 |
// Use a default temp stream if no sink was set.
|
281 |
-
$conf[
|
282 |
-
$easy->sink =
|
283 |
}
|
284 |
-
$timeoutRequiresNoSignal =
|
285 |
if (isset($options['timeout'])) {
|
286 |
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
|
287 |
-
$conf[
|
288 |
}
|
|
|
289 |
// CURL default value is CURL_IPRESOLVE_WHATEVER
|
290 |
if (isset($options['force_ip_resolve'])) {
|
291 |
if ('v4' === $options['force_ip_resolve']) {
|
292 |
-
$conf[
|
293 |
} elseif ('v6' === $options['force_ip_resolve']) {
|
294 |
-
$conf[
|
295 |
}
|
296 |
}
|
|
|
297 |
if (isset($options['connect_timeout'])) {
|
298 |
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
|
299 |
-
$conf[
|
300 |
}
|
301 |
-
|
302 |
-
|
|
|
303 |
}
|
|
|
304 |
if (isset($options['proxy'])) {
|
305 |
-
if (
|
306 |
-
$conf[
|
307 |
} else {
|
308 |
$scheme = $easy->request->getUri()->getScheme();
|
309 |
if (isset($options['proxy'][$scheme])) {
|
310 |
$host = $easy->request->getUri()->getHost();
|
311 |
-
if (!isset($options['proxy']['no']) ||
|
312 |
-
$
|
|
|
|
|
313 |
}
|
314 |
}
|
315 |
}
|
316 |
}
|
|
|
317 |
if (isset($options['cert'])) {
|
318 |
$cert = $options['cert'];
|
319 |
-
if (
|
320 |
-
$conf[
|
321 |
$cert = $cert[0];
|
322 |
}
|
323 |
-
if (
|
324 |
-
throw new \InvalidArgumentException(
|
|
|
|
|
325 |
}
|
326 |
-
$conf[
|
327 |
}
|
|
|
328 |
if (isset($options['ssl_key'])) {
|
329 |
$sslKey = $options['ssl_key'];
|
330 |
-
if (
|
331 |
-
$conf[
|
332 |
$sslKey = $sslKey[0];
|
333 |
}
|
334 |
-
if (
|
335 |
-
throw new \InvalidArgumentException(
|
|
|
|
|
336 |
}
|
337 |
-
$conf[
|
338 |
}
|
|
|
339 |
if (isset($options['progress'])) {
|
340 |
$progress = $options['progress'];
|
341 |
-
if (
|
342 |
-
throw new \InvalidArgumentException(
|
|
|
|
|
343 |
}
|
344 |
-
$conf[
|
345 |
-
$conf[
|
346 |
-
$args =
|
347 |
// PHP 5.5 pushed the handle onto the start of the args
|
348 |
-
if (
|
349 |
-
|
350 |
}
|
351 |
-
|
352 |
};
|
353 |
}
|
|
|
354 |
if (!empty($options['debug'])) {
|
355 |
-
$conf[
|
356 |
-
$conf[
|
357 |
}
|
358 |
}
|
|
|
359 |
/**
|
360 |
* This function ensures that a response was set on a transaction. If one
|
361 |
* was not set, then the request is retried if possible. This error
|
@@ -365,8 +485,11 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
365 |
* error, causing the request to be sent through curl_multi_info_read()
|
366 |
* without an error status.
|
367 |
*/
|
368 |
-
private static function retryFailedRewind(
|
369 |
-
|
|
|
|
|
|
|
370 |
try {
|
371 |
// Only rewind if the body has been read from.
|
372 |
$body = $easy->request->getBody();
|
@@ -374,34 +497,51 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
374 |
$body->rewind();
|
375 |
}
|
376 |
} catch (\RuntimeException $e) {
|
377 |
-
$ctx['error'] = 'The connection unexpectedly failed without '
|
|
|
|
|
|
|
378 |
return self::createRejection($easy, $ctx);
|
379 |
}
|
|
|
380 |
// Retry no more than 3 times before giving up.
|
381 |
if (!isset($easy->options['_curl_retries'])) {
|
382 |
$easy->options['_curl_retries'] = 1;
|
383 |
} elseif ($easy->options['_curl_retries'] == 2) {
|
384 |
-
$ctx['error'] = 'The cURL request was retried 3 times '
|
|
|
|
|
|
|
|
|
|
|
385 |
return self::createRejection($easy, $ctx);
|
386 |
} else {
|
387 |
$easy->options['_curl_retries']++;
|
388 |
}
|
|
|
389 |
return $handler($easy->request, $easy->options);
|
390 |
}
|
391 |
-
|
|
|
392 |
{
|
393 |
if (isset($easy->options['on_headers'])) {
|
394 |
$onHeaders = $easy->options['on_headers'];
|
395 |
-
|
|
|
396 |
throw new \InvalidArgumentException('on_headers must be callable');
|
397 |
}
|
398 |
} else {
|
399 |
$onHeaders = null;
|
400 |
}
|
401 |
-
|
402 |
-
|
|
|
|
|
|
|
|
|
|
|
403 |
if ($value === '') {
|
404 |
-
$startingResponse =
|
405 |
$easy->createResponse();
|
406 |
if ($onHeaders !== null) {
|
407 |
try {
|
@@ -414,12 +554,12 @@ class CurlFactory implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlFac
|
|
414 |
}
|
415 |
}
|
416 |
} elseif ($startingResponse) {
|
417 |
-
$startingResponse =
|
418 |
$easy->headers = [$value];
|
419 |
} else {
|
420 |
$easy->headers[] = $value;
|
421 |
}
|
422 |
-
return
|
423 |
};
|
424 |
}
|
425 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
|
4 |
+
use GuzzleHttp\Exception\RequestException;
|
5 |
+
use GuzzleHttp\Exception\ConnectException;
|
6 |
+
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
use GuzzleHttp\Psr7\LazyOpenStream;
|
9 |
+
use GuzzleHttp\TransferStats;
|
10 |
+
use Psr\Http\Message\RequestInterface;
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Creates curl resources from a request
|
14 |
*/
|
15 |
+
class CurlFactory implements CurlFactoryInterface
|
16 |
{
|
17 |
/** @var array */
|
18 |
private $handles = [];
|
19 |
+
|
20 |
/** @var int Total number of idle handles to keep in cache */
|
21 |
private $maxHandles;
|
22 |
+
|
23 |
/**
|
24 |
* @param int $maxHandles Maximum number of idle handles.
|
25 |
*/
|
27 |
{
|
28 |
$this->maxHandles = $maxHandles;
|
29 |
}
|
30 |
+
|
31 |
+
public function create(RequestInterface $request, array $options)
|
32 |
{
|
33 |
if (isset($options['curl']['body_as_string'])) {
|
34 |
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
35 |
unset($options['curl']['body_as_string']);
|
36 |
}
|
37 |
+
|
38 |
+
$easy = new EasyHandle;
|
39 |
$easy->request = $request;
|
40 |
$easy->options = $options;
|
41 |
$conf = $this->getDefaultConf($easy);
|
43 |
$this->applyHandlerOptions($easy, $conf);
|
44 |
$this->applyHeaders($easy, $conf);
|
45 |
unset($conf['_headers']);
|
46 |
+
|
47 |
// Add handler options from the request configuration options
|
48 |
if (isset($options['curl'])) {
|
49 |
+
$conf = array_replace($conf, $options['curl']);
|
50 |
}
|
51 |
+
|
52 |
+
$conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
|
53 |
+
$easy->handle = $this->handles
|
54 |
+
? array_pop($this->handles)
|
55 |
+
: curl_init();
|
56 |
+
curl_setopt_array($easy->handle, $conf);
|
57 |
+
|
58 |
return $easy;
|
59 |
}
|
60 |
+
|
61 |
+
public function release(EasyHandle $easy)
|
62 |
{
|
63 |
$resource = $easy->handle;
|
64 |
unset($easy->handle);
|
65 |
+
|
66 |
+
if (count($this->handles) >= $this->maxHandles) {
|
67 |
+
curl_close($resource);
|
68 |
} else {
|
69 |
// Remove all callback functions as they can hold onto references
|
70 |
// and are not cleaned up by curl_reset. Using curl_setopt_array
|
71 |
// does not work for some reason, so removing each one
|
72 |
// individually.
|
73 |
+
curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
|
74 |
+
curl_setopt($resource, CURLOPT_READFUNCTION, null);
|
75 |
+
curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
|
76 |
+
curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
|
77 |
+
curl_reset($resource);
|
78 |
$this->handles[] = $resource;
|
79 |
}
|
80 |
}
|
81 |
+
|
82 |
/**
|
83 |
* Completes a cURL transaction, either returning a response promise or a
|
84 |
* rejected promise.
|
89 |
*
|
90 |
* @return \GuzzleHttp\Promise\PromiseInterface
|
91 |
*/
|
92 |
+
public static function finish(
|
93 |
+
callable $handler,
|
94 |
+
EasyHandle $easy,
|
95 |
+
CurlFactoryInterface $factory
|
96 |
+
) {
|
97 |
if (isset($easy->options['on_stats'])) {
|
98 |
self::invokeStats($easy);
|
99 |
}
|
100 |
+
|
101 |
if (!$easy->response || $easy->errno) {
|
102 |
return self::finishError($handler, $easy, $factory);
|
103 |
}
|
104 |
+
|
105 |
// Return the response if it is present and there is no error.
|
106 |
$factory->release($easy);
|
107 |
+
|
108 |
// Rewind the body of the response if possible.
|
109 |
$body = $easy->response->getBody();
|
110 |
if ($body->isSeekable()) {
|
111 |
$body->rewind();
|
112 |
}
|
113 |
+
|
114 |
+
return new FulfilledPromise($easy->response);
|
115 |
}
|
116 |
+
|
117 |
+
private static function invokeStats(EasyHandle $easy)
|
118 |
{
|
119 |
+
$curlStats = curl_getinfo($easy->handle);
|
120 |
+
$stats = new TransferStats(
|
121 |
+
$easy->request,
|
122 |
+
$easy->response,
|
123 |
+
$curlStats['total_time'],
|
124 |
+
$easy->errno,
|
125 |
+
$curlStats
|
126 |
+
);
|
127 |
+
call_user_func($easy->options['on_stats'], $stats);
|
128 |
}
|
129 |
+
|
130 |
+
private static function finishError(
|
131 |
+
callable $handler,
|
132 |
+
EasyHandle $easy,
|
133 |
+
CurlFactoryInterface $factory
|
134 |
+
) {
|
135 |
// Get error information and release the handle to the factory.
|
136 |
+
$ctx = [
|
137 |
+
'errno' => $easy->errno,
|
138 |
+
'error' => curl_error($easy->handle),
|
139 |
+
] + curl_getinfo($easy->handle);
|
140 |
$factory->release($easy);
|
141 |
+
|
142 |
// Retry when nothing is present or when curl failed to rewind.
|
143 |
+
if (empty($easy->options['_err_message'])
|
144 |
+
&& (!$easy->errno || $easy->errno == 65)
|
145 |
+
) {
|
146 |
return self::retryFailedRewind($handler, $easy, $ctx);
|
147 |
}
|
148 |
+
|
149 |
return self::createRejection($easy, $ctx);
|
150 |
}
|
151 |
+
|
152 |
+
private static function createRejection(EasyHandle $easy, array $ctx)
|
153 |
{
|
154 |
+
static $connectionErrors = [
|
155 |
+
CURLE_OPERATION_TIMEOUTED => true,
|
156 |
+
CURLE_COULDNT_RESOLVE_HOST => true,
|
157 |
+
CURLE_COULDNT_CONNECT => true,
|
158 |
+
CURLE_SSL_CONNECT_ERROR => true,
|
159 |
+
CURLE_GOT_NOTHING => true,
|
160 |
+
];
|
161 |
+
|
162 |
// If an exception was encountered during the onHeaders event, then
|
163 |
// return a rejected promise that wraps that exception.
|
164 |
if ($easy->onHeadersException) {
|
165 |
+
return \GuzzleHttp\Promise\rejection_for(
|
166 |
+
new RequestException(
|
167 |
+
'An error was encountered during the on_headers event',
|
168 |
+
$easy->request,
|
169 |
+
$easy->response,
|
170 |
+
$easy->onHeadersException,
|
171 |
+
$ctx
|
172 |
+
)
|
173 |
+
);
|
174 |
}
|
175 |
+
|
176 |
+
$message = sprintf(
|
177 |
+
'cURL error %s: %s (%s)',
|
178 |
+
$ctx['errno'],
|
179 |
+
$ctx['error'],
|
180 |
+
'see http://curl.haxx.se/libcurl/c/libcurl-errors.html'
|
181 |
+
);
|
182 |
+
|
183 |
// Create a connection exception if it was a specific error code.
|
184 |
+
$error = isset($connectionErrors[$easy->errno])
|
185 |
+
? new ConnectException($message, $easy->request, null, $ctx)
|
186 |
+
: new RequestException($message, $easy->request, $easy->response, null, $ctx);
|
187 |
+
|
188 |
+
return \GuzzleHttp\Promise\rejection_for($error);
|
189 |
}
|
190 |
+
|
191 |
+
private function getDefaultConf(EasyHandle $easy)
|
192 |
{
|
193 |
+
$conf = [
|
194 |
+
'_headers' => $easy->request->getHeaders(),
|
195 |
+
CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
|
196 |
+
CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
|
197 |
+
CURLOPT_RETURNTRANSFER => false,
|
198 |
+
CURLOPT_HEADER => false,
|
199 |
+
CURLOPT_CONNECTTIMEOUT => 150,
|
200 |
+
];
|
201 |
+
|
202 |
+
if (defined('CURLOPT_PROTOCOLS')) {
|
203 |
+
$conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
204 |
}
|
205 |
+
|
206 |
$version = $easy->request->getProtocolVersion();
|
207 |
if ($version == 1.1) {
|
208 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
|
209 |
} elseif ($version == 2.0) {
|
210 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
|
211 |
} else {
|
212 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
|
213 |
}
|
214 |
+
|
215 |
return $conf;
|
216 |
}
|
217 |
+
|
218 |
+
private function applyMethod(EasyHandle $easy, array &$conf)
|
219 |
{
|
220 |
$body = $easy->request->getBody();
|
221 |
$size = $body->getSize();
|
222 |
+
|
223 |
if ($size === null || $size > 0) {
|
224 |
$this->applyBody($easy->request, $easy->options, $conf);
|
225 |
return;
|
226 |
}
|
227 |
+
|
228 |
$method = $easy->request->getMethod();
|
229 |
if ($method === 'PUT' || $method === 'POST') {
|
230 |
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
231 |
if (!$easy->request->hasHeader('Content-Length')) {
|
232 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
|
233 |
}
|
234 |
} elseif ($method === 'HEAD') {
|
235 |
+
$conf[CURLOPT_NOBODY] = true;
|
236 |
+
unset(
|
237 |
+
$conf[CURLOPT_WRITEFUNCTION],
|
238 |
+
$conf[CURLOPT_READFUNCTION],
|
239 |
+
$conf[CURLOPT_FILE],
|
240 |
+
$conf[CURLOPT_INFILE]
|
241 |
+
);
|
242 |
}
|
243 |
}
|
244 |
+
|
245 |
+
private function applyBody(RequestInterface $request, array $options, array &$conf)
|
246 |
{
|
247 |
+
$size = $request->hasHeader('Content-Length')
|
248 |
+
? (int) $request->getHeaderLine('Content-Length')
|
249 |
+
: null;
|
250 |
+
|
251 |
// Send the body as a string if the size is less than 1MB OR if the
|
252 |
// [curl][body_as_string] request value is set.
|
253 |
+
if (($size !== null && $size < 1000000) ||
|
254 |
+
!empty($options['_body_as_string'])
|
255 |
+
) {
|
256 |
+
$conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
|
257 |
// Don't duplicate the Content-Length header
|
258 |
$this->removeHeader('Content-Length', $conf);
|
259 |
$this->removeHeader('Transfer-Encoding', $conf);
|
260 |
} else {
|
261 |
+
$conf[CURLOPT_UPLOAD] = true;
|
262 |
if ($size !== null) {
|
263 |
+
$conf[CURLOPT_INFILESIZE] = $size;
|
264 |
$this->removeHeader('Content-Length', $conf);
|
265 |
}
|
266 |
$body = $request->getBody();
|
267 |
if ($body->isSeekable()) {
|
268 |
$body->rewind();
|
269 |
}
|
270 |
+
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
|
271 |
return $body->read($length);
|
272 |
};
|
273 |
}
|
274 |
+
|
275 |
// If the Expect header is not present, prevent curl from adding it
|
276 |
if (!$request->hasHeader('Expect')) {
|
277 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Expect:';
|
278 |
}
|
279 |
+
|
280 |
// cURL sometimes adds a content-type by default. Prevent this.
|
281 |
if (!$request->hasHeader('Content-Type')) {
|
282 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
283 |
}
|
284 |
}
|
285 |
+
|
286 |
+
private function applyHeaders(EasyHandle $easy, array &$conf)
|
287 |
{
|
288 |
foreach ($conf['_headers'] as $name => $values) {
|
289 |
foreach ($values as $value) {
|
291 |
if ($value === '') {
|
292 |
// cURL requires a special format for empty headers.
|
293 |
// See https://github.com/guzzle/guzzle/issues/1882 for more details.
|
294 |
+
$conf[CURLOPT_HTTPHEADER][] = "$name;";
|
295 |
} else {
|
296 |
+
$conf[CURLOPT_HTTPHEADER][] = "$name: $value";
|
297 |
}
|
298 |
}
|
299 |
}
|
300 |
+
|
301 |
// Remove the Accept header if one was not set
|
302 |
if (!$easy->request->hasHeader('Accept')) {
|
303 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Accept:';
|
304 |
}
|
305 |
}
|
306 |
+
|
307 |
/**
|
308 |
* Remove a header from the options array.
|
309 |
*
|
312 |
*/
|
313 |
private function removeHeader($name, array &$options)
|
314 |
{
|
315 |
+
foreach (array_keys($options['_headers']) as $key) {
|
316 |
+
if (!strcasecmp($key, $name)) {
|
317 |
unset($options['_headers'][$key]);
|
318 |
return;
|
319 |
}
|
320 |
}
|
321 |
}
|
322 |
+
|
323 |
+
private function applyHandlerOptions(EasyHandle $easy, array &$conf)
|
324 |
{
|
325 |
$options = $easy->options;
|
326 |
if (isset($options['verify'])) {
|
327 |
+
if ($options['verify'] === false) {
|
328 |
+
unset($conf[CURLOPT_CAINFO]);
|
329 |
+
$conf[CURLOPT_SSL_VERIFYHOST] = 0;
|
330 |
+
$conf[CURLOPT_SSL_VERIFYPEER] = false;
|
331 |
} else {
|
332 |
+
$conf[CURLOPT_SSL_VERIFYHOST] = 2;
|
333 |
+
$conf[CURLOPT_SSL_VERIFYPEER] = true;
|
334 |
+
if (is_string($options['verify'])) {
|
335 |
// Throw an error if the file/folder/link path is not valid or doesn't exist.
|
336 |
+
if (!file_exists($options['verify'])) {
|
337 |
+
throw new \InvalidArgumentException(
|
338 |
+
"SSL CA bundle not found: {$options['verify']}"
|
339 |
+
);
|
340 |
}
|
341 |
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
|
342 |
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
|
343 |
+
if (is_dir($options['verify']) ||
|
344 |
+
(is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
|
345 |
+
$conf[CURLOPT_CAPATH] = $options['verify'];
|
346 |
} else {
|
347 |
+
$conf[CURLOPT_CAINFO] = $options['verify'];
|
348 |
}
|
349 |
}
|
350 |
}
|
351 |
}
|
352 |
+
|
353 |
if (!empty($options['decode_content'])) {
|
354 |
$accept = $easy->request->getHeaderLine('Accept-Encoding');
|
355 |
if ($accept) {
|
356 |
+
$conf[CURLOPT_ENCODING] = $accept;
|
357 |
} else {
|
358 |
+
$conf[CURLOPT_ENCODING] = '';
|
359 |
// Don't let curl send the header over the wire
|
360 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
361 |
}
|
362 |
}
|
363 |
+
|
364 |
if (isset($options['sink'])) {
|
365 |
$sink = $options['sink'];
|
366 |
+
if (!is_string($sink)) {
|
367 |
+
$sink = \GuzzleHttp\Psr7\stream_for($sink);
|
368 |
+
} elseif (!is_dir(dirname($sink))) {
|
369 |
// Ensure that the directory exists before failing in curl.
|
370 |
+
throw new \RuntimeException(sprintf(
|
371 |
+
'Directory %s does not exist for sink value of %s',
|
372 |
+
dirname($sink),
|
373 |
+
$sink
|
374 |
+
));
|
375 |
} else {
|
376 |
+
$sink = new LazyOpenStream($sink, 'w+');
|
377 |
}
|
378 |
$easy->sink = $sink;
|
379 |
+
$conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
|
380 |
return $sink->write($write);
|
381 |
};
|
382 |
} else {
|
383 |
// Use a default temp stream if no sink was set.
|
384 |
+
$conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
|
385 |
+
$easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
|
386 |
}
|
387 |
+
$timeoutRequiresNoSignal = false;
|
388 |
if (isset($options['timeout'])) {
|
389 |
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
|
390 |
+
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
|
391 |
}
|
392 |
+
|
393 |
// CURL default value is CURL_IPRESOLVE_WHATEVER
|
394 |
if (isset($options['force_ip_resolve'])) {
|
395 |
if ('v4' === $options['force_ip_resolve']) {
|
396 |
+
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
|
397 |
} elseif ('v6' === $options['force_ip_resolve']) {
|
398 |
+
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
|
399 |
}
|
400 |
}
|
401 |
+
|
402 |
if (isset($options['connect_timeout'])) {
|
403 |
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
|
404 |
+
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
|
405 |
}
|
406 |
+
|
407 |
+
if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
408 |
+
$conf[CURLOPT_NOSIGNAL] = true;
|
409 |
}
|
410 |
+
|
411 |
if (isset($options['proxy'])) {
|
412 |
+
if (!is_array($options['proxy'])) {
|
413 |
+
$conf[CURLOPT_PROXY] = $options['proxy'];
|
414 |
} else {
|
415 |
$scheme = $easy->request->getUri()->getScheme();
|
416 |
if (isset($options['proxy'][$scheme])) {
|
417 |
$host = $easy->request->getUri()->getHost();
|
418 |
+
if (!isset($options['proxy']['no']) ||
|
419 |
+
!\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
|
420 |
+
) {
|
421 |
+
$conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
|
422 |
}
|
423 |
}
|
424 |
}
|
425 |
}
|
426 |
+
|
427 |
if (isset($options['cert'])) {
|
428 |
$cert = $options['cert'];
|
429 |
+
if (is_array($cert)) {
|
430 |
+
$conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
|
431 |
$cert = $cert[0];
|
432 |
}
|
433 |
+
if (!file_exists($cert)) {
|
434 |
+
throw new \InvalidArgumentException(
|
435 |
+
"SSL certificate not found: {$cert}"
|
436 |
+
);
|
437 |
}
|
438 |
+
$conf[CURLOPT_SSLCERT] = $cert;
|
439 |
}
|
440 |
+
|
441 |
if (isset($options['ssl_key'])) {
|
442 |
$sslKey = $options['ssl_key'];
|
443 |
+
if (is_array($sslKey)) {
|
444 |
+
$conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1];
|
445 |
$sslKey = $sslKey[0];
|
446 |
}
|
447 |
+
if (!file_exists($sslKey)) {
|
448 |
+
throw new \InvalidArgumentException(
|
449 |
+
"SSL private key not found: {$sslKey}"
|
450 |
+
);
|
451 |
}
|
452 |
+
$conf[CURLOPT_SSLKEY] = $sslKey;
|
453 |
}
|
454 |
+
|
455 |
if (isset($options['progress'])) {
|
456 |
$progress = $options['progress'];
|
457 |
+
if (!is_callable($progress)) {
|
458 |
+
throw new \InvalidArgumentException(
|
459 |
+
'progress client option must be callable'
|
460 |
+
);
|
461 |
}
|
462 |
+
$conf[CURLOPT_NOPROGRESS] = false;
|
463 |
+
$conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
|
464 |
+
$args = func_get_args();
|
465 |
// PHP 5.5 pushed the handle onto the start of the args
|
466 |
+
if (is_resource($args[0])) {
|
467 |
+
array_shift($args);
|
468 |
}
|
469 |
+
call_user_func_array($progress, $args);
|
470 |
};
|
471 |
}
|
472 |
+
|
473 |
if (!empty($options['debug'])) {
|
474 |
+
$conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
|
475 |
+
$conf[CURLOPT_VERBOSE] = true;
|
476 |
}
|
477 |
}
|
478 |
+
|
479 |
/**
|
480 |
* This function ensures that a response was set on a transaction. If one
|
481 |
* was not set, then the request is retried if possible. This error
|
485 |
* error, causing the request to be sent through curl_multi_info_read()
|
486 |
* without an error status.
|
487 |
*/
|
488 |
+
private static function retryFailedRewind(
|
489 |
+
callable $handler,
|
490 |
+
EasyHandle $easy,
|
491 |
+
array $ctx
|
492 |
+
) {
|
493 |
try {
|
494 |
// Only rewind if the body has been read from.
|
495 |
$body = $easy->request->getBody();
|
497 |
$body->rewind();
|
498 |
}
|
499 |
} catch (\RuntimeException $e) {
|
500 |
+
$ctx['error'] = 'The connection unexpectedly failed without '
|
501 |
+
. 'providing an error. The request would have been retried, '
|
502 |
+
. 'but attempting to rewind the request body failed. '
|
503 |
+
. 'Exception: ' . $e;
|
504 |
return self::createRejection($easy, $ctx);
|
505 |
}
|
506 |
+
|
507 |
// Retry no more than 3 times before giving up.
|
508 |
if (!isset($easy->options['_curl_retries'])) {
|
509 |
$easy->options['_curl_retries'] = 1;
|
510 |
} elseif ($easy->options['_curl_retries'] == 2) {
|
511 |
+
$ctx['error'] = 'The cURL request was retried 3 times '
|
512 |
+
. 'and did not succeed. The most likely reason for the failure '
|
513 |
+
. 'is that cURL was unable to rewind the body of the request '
|
514 |
+
. 'and subsequent retries resulted in the same error. Turn on '
|
515 |
+
. 'the debug option to see what went wrong. See '
|
516 |
+
. 'https://bugs.php.net/bug.php?id=47204 for more information.';
|
517 |
return self::createRejection($easy, $ctx);
|
518 |
} else {
|
519 |
$easy->options['_curl_retries']++;
|
520 |
}
|
521 |
+
|
522 |
return $handler($easy->request, $easy->options);
|
523 |
}
|
524 |
+
|
525 |
+
private function createHeaderFn(EasyHandle $easy)
|
526 |
{
|
527 |
if (isset($easy->options['on_headers'])) {
|
528 |
$onHeaders = $easy->options['on_headers'];
|
529 |
+
|
530 |
+
if (!is_callable($onHeaders)) {
|
531 |
throw new \InvalidArgumentException('on_headers must be callable');
|
532 |
}
|
533 |
} else {
|
534 |
$onHeaders = null;
|
535 |
}
|
536 |
+
|
537 |
+
return function ($ch, $h) use (
|
538 |
+
$onHeaders,
|
539 |
+
$easy,
|
540 |
+
&$startingResponse
|
541 |
+
) {
|
542 |
+
$value = trim($h);
|
543 |
if ($value === '') {
|
544 |
+
$startingResponse = true;
|
545 |
$easy->createResponse();
|
546 |
if ($onHeaders !== null) {
|
547 |
try {
|
554 |
}
|
555 |
}
|
556 |
} elseif ($startingResponse) {
|
557 |
+
$startingResponse = false;
|
558 |
$easy->headers = [$value];
|
559 |
} else {
|
560 |
$easy->headers[] = $value;
|
561 |
}
|
562 |
+
return strlen($h);
|
563 |
};
|
564 |
}
|
565 |
}
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
interface CurlFactoryInterface
|
7 |
{
|
8 |
/**
|
@@ -14,7 +14,8 @@ interface CurlFactoryInterface
|
|
14 |
* @return EasyHandle
|
15 |
* @throws \RuntimeException when an option cannot be applied
|
16 |
*/
|
17 |
-
public function create(
|
|
|
18 |
/**
|
19 |
* Release an easy handle, allowing it to be reused or closed.
|
20 |
*
|
@@ -22,5 +23,5 @@ interface CurlFactoryInterface
|
|
22 |
*
|
23 |
* @param EasyHandle $easy
|
24 |
*/
|
25 |
-
public function release(
|
26 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
|
|
|
6 |
interface CurlFactoryInterface
|
7 |
{
|
8 |
/**
|
14 |
* @return EasyHandle
|
15 |
* @throws \RuntimeException when an option cannot be applied
|
16 |
*/
|
17 |
+
public function create(RequestInterface $request, array $options);
|
18 |
+
|
19 |
/**
|
20 |
* Release an easy handle, allowing it to be reused or closed.
|
21 |
*
|
23 |
*
|
24 |
* @param EasyHandle $easy
|
25 |
*/
|
26 |
+
public function release(EasyHandle $easy);
|
27 |
}
|
@@ -1,9 +1,9 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
7 |
/**
|
8 |
* HTTP handler that uses cURL easy handles as a transport layer.
|
9 |
*
|
@@ -15,6 +15,7 @@ class CurlHandler
|
|
15 |
{
|
16 |
/** @var CurlFactoryInterface */
|
17 |
private $factory;
|
|
|
18 |
/**
|
19 |
* Accepts an associative array of options:
|
20 |
*
|
@@ -24,16 +25,21 @@ class CurlHandler
|
|
24 |
*/
|
25 |
public function __construct(array $options = [])
|
26 |
{
|
27 |
-
$this->factory = isset($options['handle_factory'])
|
|
|
|
|
28 |
}
|
29 |
-
|
|
|
30 |
{
|
31 |
if (isset($options['delay'])) {
|
32 |
-
|
33 |
}
|
|
|
34 |
$easy = $this->factory->create($request, $options);
|
35 |
-
|
36 |
-
$easy->errno =
|
37 |
-
|
|
|
38 |
}
|
39 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
|
4 |
+
use GuzzleHttp\Psr7;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
|
|
|
|
|
7 |
/**
|
8 |
* HTTP handler that uses cURL easy handles as a transport layer.
|
9 |
*
|
15 |
{
|
16 |
/** @var CurlFactoryInterface */
|
17 |
private $factory;
|
18 |
+
|
19 |
/**
|
20 |
* Accepts an associative array of options:
|
21 |
*
|
25 |
*/
|
26 |
public function __construct(array $options = [])
|
27 |
{
|
28 |
+
$this->factory = isset($options['handle_factory'])
|
29 |
+
? $options['handle_factory']
|
30 |
+
: new CurlFactory(3);
|
31 |
}
|
32 |
+
|
33 |
+
public function __invoke(RequestInterface $request, array $options)
|
34 |
{
|
35 |
if (isset($options['delay'])) {
|
36 |
+
usleep($options['delay'] * 1000);
|
37 |
}
|
38 |
+
|
39 |
$easy = $this->factory->create($request, $options);
|
40 |
+
curl_exec($easy->handle);
|
41 |
+
$easy->errno = curl_errno($easy->handle);
|
42 |
+
|
43 |
+
return CurlFactory::finish($this, $easy, $this->factory);
|
44 |
}
|
45 |
}
|
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise as P;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Promise;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
9 |
/**
|
10 |
* Returns an asynchronous response using curl_multi_* functions.
|
11 |
*
|
@@ -23,6 +23,7 @@ class CurlMultiHandler
|
|
23 |
private $active;
|
24 |
private $handles = [];
|
25 |
private $delays = [];
|
|
|
26 |
/**
|
27 |
* This handler accepts the following options:
|
28 |
*
|
@@ -34,33 +35,46 @@ class CurlMultiHandler
|
|
34 |
*/
|
35 |
public function __construct(array $options = [])
|
36 |
{
|
37 |
-
$this->factory = isset($options['handle_factory'])
|
38 |
-
|
|
|
|
|
39 |
}
|
|
|
40 |
public function __get($name)
|
41 |
{
|
42 |
if ($name === '_mh') {
|
43 |
-
return $this->_mh =
|
44 |
}
|
|
|
45 |
throw new \BadMethodCallException();
|
46 |
}
|
|
|
47 |
public function __destruct()
|
48 |
{
|
49 |
if (isset($this->_mh)) {
|
50 |
-
|
51 |
unset($this->_mh);
|
52 |
}
|
53 |
}
|
54 |
-
|
|
|
55 |
{
|
56 |
$easy = $this->factory->create($request, $options);
|
57 |
$id = (int) $easy->handle;
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
61 |
$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
|
|
|
62 |
return $promise;
|
63 |
}
|
|
|
64 |
/**
|
65 |
* Ticks the curl event loop.
|
66 |
*/
|
@@ -68,50 +82,62 @@ class CurlMultiHandler
|
|
68 |
{
|
69 |
// Add any delayed handles if needed.
|
70 |
if ($this->delays) {
|
71 |
-
$currentTime =
|
72 |
foreach ($this->delays as $id => $delay) {
|
73 |
if ($currentTime >= $delay) {
|
74 |
unset($this->delays[$id]);
|
75 |
-
|
|
|
|
|
|
|
76 |
}
|
77 |
}
|
78 |
}
|
|
|
79 |
// Step through the task queue which may add additional requests.
|
80 |
-
\
|
81 |
-
|
|
|
|
|
|
|
82 |
// Perform a usleep if a select returns -1.
|
83 |
// See: https://bugs.php.net/bug.php?id=61141
|
84 |
-
|
85 |
-
}
|
86 |
-
while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
|
87 |
}
|
|
|
|
|
|
|
88 |
$this->processMessages();
|
89 |
}
|
|
|
90 |
/**
|
91 |
* Runs until all outstanding connections have completed.
|
92 |
*/
|
93 |
public function execute()
|
94 |
{
|
95 |
-
$queue = \
|
|
|
96 |
while ($this->handles || !$queue->isEmpty()) {
|
97 |
// If there are no transfers, then sleep for the next delay
|
98 |
if (!$this->active && $this->delays) {
|
99 |
-
|
100 |
}
|
101 |
$this->tick();
|
102 |
}
|
103 |
}
|
|
|
104 |
private function addRequest(array $entry)
|
105 |
{
|
106 |
$easy = $entry['easy'];
|
107 |
$id = (int) $easy->handle;
|
108 |
$this->handles[$id] = $entry;
|
109 |
if (empty($easy->options['delay'])) {
|
110 |
-
|
111 |
} else {
|
112 |
-
$this->delays[$id] =
|
113 |
}
|
114 |
}
|
|
|
115 |
/**
|
116 |
* Cancels a handle from sending and removes references to it.
|
117 |
*
|
@@ -123,38 +149,51 @@ class CurlMultiHandler
|
|
123 |
{
|
124 |
// Cannot cancel if it has been processed.
|
125 |
if (!isset($this->handles[$id])) {
|
126 |
-
return
|
127 |
}
|
|
|
128 |
$handle = $this->handles[$id]['easy']->handle;
|
129 |
unset($this->delays[$id], $this->handles[$id]);
|
130 |
-
|
131 |
-
|
132 |
-
|
|
|
133 |
}
|
|
|
134 |
private function processMessages()
|
135 |
{
|
136 |
-
while ($done =
|
137 |
$id = (int) $done['handle'];
|
138 |
-
|
|
|
139 |
if (!isset($this->handles[$id])) {
|
140 |
// Probably was cancelled.
|
141 |
continue;
|
142 |
}
|
|
|
143 |
$entry = $this->handles[$id];
|
144 |
unset($this->handles[$id], $this->delays[$id]);
|
145 |
$entry['easy']->errno = $done['result'];
|
146 |
-
$entry['deferred']->resolve(
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
}
|
148 |
}
|
|
|
149 |
private function timeToNext()
|
150 |
{
|
151 |
-
$currentTime =
|
152 |
-
$nextTime =
|
153 |
foreach ($this->delays as $time) {
|
154 |
if ($time < $nextTime) {
|
155 |
$nextTime = $time;
|
156 |
}
|
157 |
}
|
158 |
-
|
|
|
159 |
}
|
160 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
|
4 |
+
use GuzzleHttp\Promise as P;
|
5 |
+
use GuzzleHttp\Promise\Promise;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
|
|
|
|
|
|
|
|
|
9 |
/**
|
10 |
* Returns an asynchronous response using curl_multi_* functions.
|
11 |
*
|
23 |
private $active;
|
24 |
private $handles = [];
|
25 |
private $delays = [];
|
26 |
+
|
27 |
/**
|
28 |
* This handler accepts the following options:
|
29 |
*
|
35 |
*/
|
36 |
public function __construct(array $options = [])
|
37 |
{
|
38 |
+
$this->factory = isset($options['handle_factory'])
|
39 |
+
? $options['handle_factory'] : new CurlFactory(50);
|
40 |
+
$this->selectTimeout = isset($options['select_timeout'])
|
41 |
+
? $options['select_timeout'] : 1;
|
42 |
}
|
43 |
+
|
44 |
public function __get($name)
|
45 |
{
|
46 |
if ($name === '_mh') {
|
47 |
+
return $this->_mh = curl_multi_init();
|
48 |
}
|
49 |
+
|
50 |
throw new \BadMethodCallException();
|
51 |
}
|
52 |
+
|
53 |
public function __destruct()
|
54 |
{
|
55 |
if (isset($this->_mh)) {
|
56 |
+
curl_multi_close($this->_mh);
|
57 |
unset($this->_mh);
|
58 |
}
|
59 |
}
|
60 |
+
|
61 |
+
public function __invoke(RequestInterface $request, array $options)
|
62 |
{
|
63 |
$easy = $this->factory->create($request, $options);
|
64 |
$id = (int) $easy->handle;
|
65 |
+
|
66 |
+
$promise = new Promise(
|
67 |
+
[$this, 'execute'],
|
68 |
+
function () use ($id) {
|
69 |
+
return $this->cancel($id);
|
70 |
+
}
|
71 |
+
);
|
72 |
+
|
73 |
$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
|
74 |
+
|
75 |
return $promise;
|
76 |
}
|
77 |
+
|
78 |
/**
|
79 |
* Ticks the curl event loop.
|
80 |
*/
|
82 |
{
|
83 |
// Add any delayed handles if needed.
|
84 |
if ($this->delays) {
|
85 |
+
$currentTime = microtime(true);
|
86 |
foreach ($this->delays as $id => $delay) {
|
87 |
if ($currentTime >= $delay) {
|
88 |
unset($this->delays[$id]);
|
89 |
+
curl_multi_add_handle(
|
90 |
+
$this->_mh,
|
91 |
+
$this->handles[$id]['easy']->handle
|
92 |
+
);
|
93 |
}
|
94 |
}
|
95 |
}
|
96 |
+
|
97 |
// Step through the task queue which may add additional requests.
|
98 |
+
P\queue()->run();
|
99 |
+
|
100 |
+
if ($this->active &&
|
101 |
+
curl_multi_select($this->_mh, $this->selectTimeout) === -1
|
102 |
+
) {
|
103 |
// Perform a usleep if a select returns -1.
|
104 |
// See: https://bugs.php.net/bug.php?id=61141
|
105 |
+
usleep(250);
|
|
|
|
|
106 |
}
|
107 |
+
|
108 |
+
while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
|
109 |
+
|
110 |
$this->processMessages();
|
111 |
}
|
112 |
+
|
113 |
/**
|
114 |
* Runs until all outstanding connections have completed.
|
115 |
*/
|
116 |
public function execute()
|
117 |
{
|
118 |
+
$queue = P\queue();
|
119 |
+
|
120 |
while ($this->handles || !$queue->isEmpty()) {
|
121 |
// If there are no transfers, then sleep for the next delay
|
122 |
if (!$this->active && $this->delays) {
|
123 |
+
usleep($this->timeToNext());
|
124 |
}
|
125 |
$this->tick();
|
126 |
}
|
127 |
}
|
128 |
+
|
129 |
private function addRequest(array $entry)
|
130 |
{
|
131 |
$easy = $entry['easy'];
|
132 |
$id = (int) $easy->handle;
|
133 |
$this->handles[$id] = $entry;
|
134 |
if (empty($easy->options['delay'])) {
|
135 |
+
curl_multi_add_handle($this->_mh, $easy->handle);
|
136 |
} else {
|
137 |
+
$this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000);
|
138 |
}
|
139 |
}
|
140 |
+
|
141 |
/**
|
142 |
* Cancels a handle from sending and removes references to it.
|
143 |
*
|
149 |
{
|
150 |
// Cannot cancel if it has been processed.
|
151 |
if (!isset($this->handles[$id])) {
|
152 |
+
return false;
|
153 |
}
|
154 |
+
|
155 |
$handle = $this->handles[$id]['easy']->handle;
|
156 |
unset($this->delays[$id], $this->handles[$id]);
|
157 |
+
curl_multi_remove_handle($this->_mh, $handle);
|
158 |
+
curl_close($handle);
|
159 |
+
|
160 |
+
return true;
|
161 |
}
|
162 |
+
|
163 |
private function processMessages()
|
164 |
{
|
165 |
+
while ($done = curl_multi_info_read($this->_mh)) {
|
166 |
$id = (int) $done['handle'];
|
167 |
+
curl_multi_remove_handle($this->_mh, $done['handle']);
|
168 |
+
|
169 |
if (!isset($this->handles[$id])) {
|
170 |
// Probably was cancelled.
|
171 |
continue;
|
172 |
}
|
173 |
+
|
174 |
$entry = $this->handles[$id];
|
175 |
unset($this->handles[$id], $this->delays[$id]);
|
176 |
$entry['easy']->errno = $done['result'];
|
177 |
+
$entry['deferred']->resolve(
|
178 |
+
CurlFactory::finish(
|
179 |
+
$this,
|
180 |
+
$entry['easy'],
|
181 |
+
$this->factory
|
182 |
+
)
|
183 |
+
);
|
184 |
}
|
185 |
}
|
186 |
+
|
187 |
private function timeToNext()
|
188 |
{
|
189 |
+
$currentTime = microtime(true);
|
190 |
+
$nextTime = PHP_INT_MAX;
|
191 |
foreach ($this->delays as $time) {
|
192 |
if ($time < $nextTime) {
|
193 |
$nextTime = $time;
|
194 |
}
|
195 |
}
|
196 |
+
|
197 |
+
return max(0, $nextTime - $currentTime) * 1000000;
|
198 |
}
|
199 |
}
|
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Response;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
9 |
/**
|
10 |
* Represents a cURL easy handle and the data it populates.
|
11 |
*
|
@@ -15,20 +15,28 @@ final class EasyHandle
|
|
15 |
{
|
16 |
/** @var resource cURL resource */
|
17 |
public $handle;
|
|
|
18 |
/** @var StreamInterface Where data is being written */
|
19 |
public $sink;
|
|
|
20 |
/** @var array Received HTTP headers so far */
|
21 |
public $headers = [];
|
|
|
22 |
/** @var ResponseInterface Received response (if any) */
|
23 |
public $response;
|
|
|
24 |
/** @var RequestInterface Request being sent */
|
25 |
public $request;
|
|
|
26 |
/** @var array Request options */
|
27 |
public $options = [];
|
|
|
28 |
/** @var int cURL error number (if any) */
|
29 |
public $errno = 0;
|
|
|
30 |
/** @var \Exception Exception during on_headers (if any) */
|
31 |
public $onHeadersException;
|
|
|
32 |
/**
|
33 |
* Attach a response to the easy handle based on the received headers.
|
34 |
*
|
@@ -39,15 +47,22 @@ final class EasyHandle
|
|
39 |
if (empty($this->headers)) {
|
40 |
throw new \RuntimeException('No headers have been received');
|
41 |
}
|
|
|
42 |
// HTTP-version SP status-code SP reason-phrase
|
43 |
-
$startLine =
|
44 |
-
$headers = \
|
45 |
-
$normalizedKeys = \
|
46 |
-
|
47 |
-
|
|
|
|
|
|
|
|
|
48 |
unset($headers[$normalizedKeys['content-encoding']]);
|
49 |
if (isset($normalizedKeys['content-length'])) {
|
50 |
-
$headers['x-encoded-content-length']
|
|
|
|
|
51 |
$bodyLength = (int) $this->sink->getSize();
|
52 |
if ($bodyLength) {
|
53 |
$headers[$normalizedKeys['content-length']] = $bodyLength;
|
@@ -56,12 +71,22 @@ final class EasyHandle
|
|
56 |
}
|
57 |
}
|
58 |
}
|
|
|
59 |
// Attach a response to the easy handle with the parsed headers.
|
60 |
-
$this->response = new
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
|
|
62 |
public function __get($name)
|
63 |
{
|
64 |
-
$msg = $name === 'handle'
|
|
|
|
|
65 |
throw new \BadMethodCallException($msg);
|
66 |
}
|
67 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
|
4 |
+
use GuzzleHttp\Psr7\Response;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
use Psr\Http\Message\StreamInterface;
|
8 |
|
|
|
|
|
|
|
|
|
9 |
/**
|
10 |
* Represents a cURL easy handle and the data it populates.
|
11 |
*
|
15 |
{
|
16 |
/** @var resource cURL resource */
|
17 |
public $handle;
|
18 |
+
|
19 |
/** @var StreamInterface Where data is being written */
|
20 |
public $sink;
|
21 |
+
|
22 |
/** @var array Received HTTP headers so far */
|
23 |
public $headers = [];
|
24 |
+
|
25 |
/** @var ResponseInterface Received response (if any) */
|
26 |
public $response;
|
27 |
+
|
28 |
/** @var RequestInterface Request being sent */
|
29 |
public $request;
|
30 |
+
|
31 |
/** @var array Request options */
|
32 |
public $options = [];
|
33 |
+
|
34 |
/** @var int cURL error number (if any) */
|
35 |
public $errno = 0;
|
36 |
+
|
37 |
/** @var \Exception Exception during on_headers (if any) */
|
38 |
public $onHeadersException;
|
39 |
+
|
40 |
/**
|
41 |
* Attach a response to the easy handle based on the received headers.
|
42 |
*
|
47 |
if (empty($this->headers)) {
|
48 |
throw new \RuntimeException('No headers have been received');
|
49 |
}
|
50 |
+
|
51 |
// HTTP-version SP status-code SP reason-phrase
|
52 |
+
$startLine = explode(' ', array_shift($this->headers), 3);
|
53 |
+
$headers = \GuzzleHttp\headers_from_lines($this->headers);
|
54 |
+
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
55 |
+
|
56 |
+
if (!empty($this->options['decode_content'])
|
57 |
+
&& isset($normalizedKeys['content-encoding'])
|
58 |
+
) {
|
59 |
+
$headers['x-encoded-content-encoding']
|
60 |
+
= $headers[$normalizedKeys['content-encoding']];
|
61 |
unset($headers[$normalizedKeys['content-encoding']]);
|
62 |
if (isset($normalizedKeys['content-length'])) {
|
63 |
+
$headers['x-encoded-content-length']
|
64 |
+
= $headers[$normalizedKeys['content-length']];
|
65 |
+
|
66 |
$bodyLength = (int) $this->sink->getSize();
|
67 |
if ($bodyLength) {
|
68 |
$headers[$normalizedKeys['content-length']] = $bodyLength;
|
71 |
}
|
72 |
}
|
73 |
}
|
74 |
+
|
75 |
// Attach a response to the easy handle with the parsed headers.
|
76 |
+
$this->response = new Response(
|
77 |
+
$startLine[1],
|
78 |
+
$headers,
|
79 |
+
$this->sink,
|
80 |
+
substr($startLine[0], 5),
|
81 |
+
isset($startLine[2]) ? (string) $startLine[2] : null
|
82 |
+
);
|
83 |
}
|
84 |
+
|
85 |
public function __get($name)
|
86 |
{
|
87 |
+
$msg = $name === 'handle'
|
88 |
+
? 'The EasyHandle has been released'
|
89 |
+
: 'Invalid property: ' . $name;
|
90 |
throw new \BadMethodCallException($msg);
|
91 |
}
|
92 |
}
|
@@ -1,14 +1,14 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\RequestException;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\HandlerStack;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\RejectedPromise;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\TransferStats;
|
10 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
11 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
12 |
/**
|
13 |
* Handler that returns responses or throw exceptions from a queue.
|
14 |
*/
|
@@ -19,6 +19,7 @@ class MockHandler implements \Countable
|
|
19 |
private $lastOptions;
|
20 |
private $onFulfilled;
|
21 |
private $onRejected;
|
|
|
22 |
/**
|
23 |
* Creates a new MockHandler that uses the default handler stack list of
|
24 |
* middlewares.
|
@@ -29,10 +30,14 @@ class MockHandler implements \Countable
|
|
29 |
*
|
30 |
* @return HandlerStack
|
31 |
*/
|
32 |
-
public static function createWithMiddleware(
|
33 |
-
|
34 |
-
|
|
|
|
|
|
|
35 |
}
|
|
|
36 |
/**
|
37 |
* The passed in value must be an array of
|
38 |
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
@@ -42,79 +47,104 @@ class MockHandler implements \Countable
|
|
42 |
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
43 |
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
44 |
*/
|
45 |
-
public function __construct(
|
46 |
-
|
|
|
|
|
|
|
47 |
$this->onFulfilled = $onFulfilled;
|
48 |
$this->onRejected = $onRejected;
|
|
|
49 |
if ($queue) {
|
50 |
-
|
51 |
}
|
52 |
}
|
53 |
-
|
|
|
54 |
{
|
55 |
if (!$this->queue) {
|
56 |
throw new \OutOfBoundsException('Mock queue is empty');
|
57 |
}
|
|
|
58 |
if (isset($options['delay'])) {
|
59 |
-
|
60 |
}
|
|
|
61 |
$this->lastRequest = $request;
|
62 |
$this->lastOptions = $options;
|
63 |
-
$response =
|
|
|
64 |
if (isset($options['on_headers'])) {
|
65 |
-
if (
|
66 |
throw new \InvalidArgumentException('on_headers must be callable');
|
67 |
}
|
68 |
try {
|
69 |
$options['on_headers']($response);
|
70 |
} catch (\Exception $e) {
|
71 |
$msg = 'An error was encountered during the on_headers event';
|
72 |
-
$response = new
|
73 |
}
|
74 |
}
|
75 |
-
|
76 |
-
|
|
|
77 |
}
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
$
|
86 |
-
$
|
87 |
-
|
88 |
-
\fwrite($sink, $contents);
|
89 |
-
} elseif (\is_string($sink)) {
|
90 |
-
\file_put_contents($sink, $contents);
|
91 |
-
} elseif ($sink instanceof \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface) {
|
92 |
-
$sink->write($contents);
|
93 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
-
|
96 |
-
}, function ($reason) use($request, $options) {
|
97 |
-
$this->invokeStats($request, $options, null, $reason);
|
98 |
-
if ($this->onRejected) {
|
99 |
-
\call_user_func($this->onRejected, $reason);
|
100 |
-
}
|
101 |
-
return \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\rejection_for($reason);
|
102 |
-
});
|
103 |
}
|
|
|
104 |
/**
|
105 |
* Adds one or more variadic requests, exceptions, callables, or promises
|
106 |
* to the queue.
|
107 |
*/
|
108 |
public function append()
|
109 |
{
|
110 |
-
foreach (
|
111 |
-
if ($value instanceof
|
|
|
|
|
|
|
|
|
112 |
$this->queue[] = $value;
|
113 |
} else {
|
114 |
-
throw new \InvalidArgumentException('Expected a response or '
|
|
|
115 |
}
|
116 |
}
|
117 |
}
|
|
|
118 |
/**
|
119 |
* Get the last received request.
|
120 |
*
|
@@ -124,6 +154,7 @@ class MockHandler implements \Countable
|
|
124 |
{
|
125 |
return $this->lastRequest;
|
126 |
}
|
|
|
127 |
/**
|
128 |
* Get the last received request options.
|
129 |
*
|
@@ -133,6 +164,7 @@ class MockHandler implements \Countable
|
|
133 |
{
|
134 |
return $this->lastOptions;
|
135 |
}
|
|
|
136 |
/**
|
137 |
* Returns the number of remaining items in the queue.
|
138 |
*
|
@@ -140,13 +172,18 @@ class MockHandler implements \Countable
|
|
140 |
*/
|
141 |
public function count()
|
142 |
{
|
143 |
-
return
|
144 |
}
|
145 |
-
|
146 |
-
|
|
|
|
|
|
|
|
|
|
|
147 |
if (isset($options['on_stats'])) {
|
148 |
-
$stats = new
|
149 |
-
|
150 |
}
|
151 |
}
|
152 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
|
4 |
+
use GuzzleHttp\Exception\RequestException;
|
5 |
+
use GuzzleHttp\HandlerStack;
|
6 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
8 |
+
use GuzzleHttp\TransferStats;
|
9 |
+
use Psr\Http\Message\RequestInterface;
|
10 |
+
use Psr\Http\Message\ResponseInterface;
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Handler that returns responses or throw exceptions from a queue.
|
14 |
*/
|
19 |
private $lastOptions;
|
20 |
private $onFulfilled;
|
21 |
private $onRejected;
|
22 |
+
|
23 |
/**
|
24 |
* Creates a new MockHandler that uses the default handler stack list of
|
25 |
* middlewares.
|
30 |
*
|
31 |
* @return HandlerStack
|
32 |
*/
|
33 |
+
public static function createWithMiddleware(
|
34 |
+
array $queue = null,
|
35 |
+
callable $onFulfilled = null,
|
36 |
+
callable $onRejected = null
|
37 |
+
) {
|
38 |
+
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
39 |
}
|
40 |
+
|
41 |
/**
|
42 |
* The passed in value must be an array of
|
43 |
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
47 |
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
48 |
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
49 |
*/
|
50 |
+
public function __construct(
|
51 |
+
array $queue = null,
|
52 |
+
callable $onFulfilled = null,
|
53 |
+
callable $onRejected = null
|
54 |
+
) {
|
55 |
$this->onFulfilled = $onFulfilled;
|
56 |
$this->onRejected = $onRejected;
|
57 |
+
|
58 |
if ($queue) {
|
59 |
+
call_user_func_array([$this, 'append'], $queue);
|
60 |
}
|
61 |
}
|
62 |
+
|
63 |
+
public function __invoke(RequestInterface $request, array $options)
|
64 |
{
|
65 |
if (!$this->queue) {
|
66 |
throw new \OutOfBoundsException('Mock queue is empty');
|
67 |
}
|
68 |
+
|
69 |
if (isset($options['delay'])) {
|
70 |
+
usleep($options['delay'] * 1000);
|
71 |
}
|
72 |
+
|
73 |
$this->lastRequest = $request;
|
74 |
$this->lastOptions = $options;
|
75 |
+
$response = array_shift($this->queue);
|
76 |
+
|
77 |
if (isset($options['on_headers'])) {
|
78 |
+
if (!is_callable($options['on_headers'])) {
|
79 |
throw new \InvalidArgumentException('on_headers must be callable');
|
80 |
}
|
81 |
try {
|
82 |
$options['on_headers']($response);
|
83 |
} catch (\Exception $e) {
|
84 |
$msg = 'An error was encountered during the on_headers event';
|
85 |
+
$response = new RequestException($msg, $request, $response, $e);
|
86 |
}
|
87 |
}
|
88 |
+
|
89 |
+
if (is_callable($response)) {
|
90 |
+
$response = call_user_func($response, $request, $options);
|
91 |
}
|
92 |
+
|
93 |
+
$response = $response instanceof \Exception
|
94 |
+
? \GuzzleHttp\Promise\rejection_for($response)
|
95 |
+
: \GuzzleHttp\Promise\promise_for($response);
|
96 |
+
|
97 |
+
return $response->then(
|
98 |
+
function ($value) use ($request, $options) {
|
99 |
+
$this->invokeStats($request, $options, $value);
|
100 |
+
if ($this->onFulfilled) {
|
101 |
+
call_user_func($this->onFulfilled, $value);
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
103 |
+
if (isset($options['sink'])) {
|
104 |
+
$contents = (string) $value->getBody();
|
105 |
+
$sink = $options['sink'];
|
106 |
+
|
107 |
+
if (is_resource($sink)) {
|
108 |
+
fwrite($sink, $contents);
|
109 |
+
} elseif (is_string($sink)) {
|
110 |
+
file_put_contents($sink, $contents);
|
111 |
+
} elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
|
112 |
+
$sink->write($contents);
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
return $value;
|
117 |
+
},
|
118 |
+
function ($reason) use ($request, $options) {
|
119 |
+
$this->invokeStats($request, $options, null, $reason);
|
120 |
+
if ($this->onRejected) {
|
121 |
+
call_user_func($this->onRejected, $reason);
|
122 |
+
}
|
123 |
+
return \GuzzleHttp\Promise\rejection_for($reason);
|
124 |
}
|
125 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
}
|
127 |
+
|
128 |
/**
|
129 |
* Adds one or more variadic requests, exceptions, callables, or promises
|
130 |
* to the queue.
|
131 |
*/
|
132 |
public function append()
|
133 |
{
|
134 |
+
foreach (func_get_args() as $value) {
|
135 |
+
if ($value instanceof ResponseInterface
|
136 |
+
|| $value instanceof \Exception
|
137 |
+
|| $value instanceof PromiseInterface
|
138 |
+
|| is_callable($value)
|
139 |
+
) {
|
140 |
$this->queue[] = $value;
|
141 |
} else {
|
142 |
+
throw new \InvalidArgumentException('Expected a response or '
|
143 |
+
. 'exception. Found ' . \GuzzleHttp\describe_type($value));
|
144 |
}
|
145 |
}
|
146 |
}
|
147 |
+
|
148 |
/**
|
149 |
* Get the last received request.
|
150 |
*
|
154 |
{
|
155 |
return $this->lastRequest;
|
156 |
}
|
157 |
+
|
158 |
/**
|
159 |
* Get the last received request options.
|
160 |
*
|
164 |
{
|
165 |
return $this->lastOptions;
|
166 |
}
|
167 |
+
|
168 |
/**
|
169 |
* Returns the number of remaining items in the queue.
|
170 |
*
|
172 |
*/
|
173 |
public function count()
|
174 |
{
|
175 |
+
return count($this->queue);
|
176 |
}
|
177 |
+
|
178 |
+
private function invokeStats(
|
179 |
+
RequestInterface $request,
|
180 |
+
array $options,
|
181 |
+
ResponseInterface $response = null,
|
182 |
+
$reason = null
|
183 |
+
) {
|
184 |
if (isset($options['on_stats'])) {
|
185 |
+
$stats = new TransferStats($request, $response, 0, $reason);
|
186 |
+
call_user_func($options['on_stats'], $stats);
|
187 |
}
|
188 |
}
|
189 |
}
|
@@ -1,9 +1,9 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\RequestOptions;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
7 |
/**
|
8 |
* Provides basic proxies for handlers.
|
9 |
*/
|
@@ -18,12 +18,17 @@ class Proxy
|
|
18 |
*
|
19 |
* @return callable Returns the composed handler.
|
20 |
*/
|
21 |
-
public static function wrapSync(
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
25 |
};
|
26 |
}
|
|
|
27 |
/**
|
28 |
* Sends streaming requests to a streaming compatible handler while sending
|
29 |
* all other requests to a default handler.
|
@@ -37,10 +42,14 @@ class Proxy
|
|
37 |
*
|
38 |
* @return callable Returns the composed handler.
|
39 |
*/
|
40 |
-
public static function wrapStreaming(
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
44 |
};
|
45 |
}
|
46 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
|
4 |
+
use GuzzleHttp\RequestOptions;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
|
|
|
|
|
7 |
/**
|
8 |
* Provides basic proxies for handlers.
|
9 |
*/
|
18 |
*
|
19 |
* @return callable Returns the composed handler.
|
20 |
*/
|
21 |
+
public static function wrapSync(
|
22 |
+
callable $default,
|
23 |
+
callable $sync
|
24 |
+
) {
|
25 |
+
return function (RequestInterface $request, array $options) use ($default, $sync) {
|
26 |
+
return empty($options[RequestOptions::SYNCHRONOUS])
|
27 |
+
? $default($request, $options)
|
28 |
+
: $sync($request, $options);
|
29 |
};
|
30 |
}
|
31 |
+
|
32 |
/**
|
33 |
* Sends streaming requests to a streaming compatible handler while sending
|
34 |
* all other requests to a default handler.
|
42 |
*
|
43 |
* @return callable Returns the composed handler.
|
44 |
*/
|
45 |
+
public static function wrapStreaming(
|
46 |
+
callable $default,
|
47 |
+
callable $streaming
|
48 |
+
) {
|
49 |
+
return function (RequestInterface $request, array $options) use ($default, $streaming) {
|
50 |
+
return empty($options['stream'])
|
51 |
+
? $default($request, $options)
|
52 |
+
: $streaming($request, $options);
|
53 |
};
|
54 |
}
|
55 |
}
|
@@ -1,22 +1,23 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler;
|
4 |
-
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\RequestException;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\ConnectException;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\FulfilledPromise;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
10 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\TransferStats;
|
11 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
12 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
13 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
14 |
/**
|
15 |
* HTTP handler that uses PHP's HTTP stream wrapper.
|
16 |
*/
|
17 |
class StreamHandler
|
18 |
{
|
19 |
private $lastHeaders = [];
|
|
|
20 |
/**
|
21 |
* Sends an HTTP request.
|
22 |
*
|
@@ -25,99 +26,153 @@ class StreamHandler
|
|
25 |
*
|
26 |
* @return PromiseInterface
|
27 |
*/
|
28 |
-
public function __invoke(
|
29 |
{
|
30 |
// Sleep if there is a delay specified.
|
31 |
if (isset($options['delay'])) {
|
32 |
-
|
33 |
}
|
34 |
-
|
|
|
|
|
35 |
try {
|
36 |
// Does not support the expect header.
|
37 |
$request = $request->withoutHeader('Expect');
|
|
|
38 |
// Append a content-length header if body size is zero to match
|
39 |
// cURL's behavior.
|
40 |
if (0 === $request->getBody()->getSize()) {
|
41 |
$request = $request->withHeader('Content-Length', 0);
|
42 |
}
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
} catch (\InvalidArgumentException $e) {
|
45 |
throw $e;
|
46 |
} catch (\Exception $e) {
|
47 |
// Determine if the error was a networking error.
|
48 |
$message = $e->getMessage();
|
49 |
// This list can probably get more comprehensive.
|
50 |
-
if (
|
51 |
-
|
|
|
|
|
|
|
|
|
52 |
}
|
53 |
-
$e =
|
54 |
$this->invokeStats($options, $request, $startTime, null, $e);
|
55 |
-
|
|
|
56 |
}
|
57 |
}
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
if (isset($options['on_stats'])) {
|
61 |
-
$stats = new
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
}
|
64 |
}
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
67 |
$hdrs = $this->lastHeaders;
|
68 |
$this->lastHeaders = [];
|
69 |
-
$parts =
|
70 |
-
$ver =
|
71 |
$status = $parts[1];
|
72 |
$reason = isset($parts[2]) ? $parts[2] : null;
|
73 |
-
$headers = \
|
74 |
list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
|
75 |
-
$stream =
|
76 |
$sink = $stream;
|
77 |
-
|
|
|
78 |
$sink = $this->createSink($stream, $options);
|
79 |
}
|
80 |
-
|
|
|
|
|
81 |
if (isset($options['on_headers'])) {
|
82 |
try {
|
83 |
$options['on_headers']($response);
|
84 |
} catch (\Exception $e) {
|
85 |
$msg = 'An error was encountered during the on_headers event';
|
86 |
-
$ex = new
|
87 |
-
return \
|
88 |
}
|
89 |
}
|
|
|
90 |
// Do not drain when the request is a HEAD request because they have
|
91 |
// no body.
|
92 |
if ($sink !== $stream) {
|
93 |
-
$this->drain(
|
|
|
|
|
|
|
|
|
94 |
}
|
|
|
95 |
$this->invokeStats($options, $request, $startTime, $response, null);
|
96 |
-
|
|
|
97 |
}
|
98 |
-
|
|
|
99 |
{
|
100 |
if (!empty($options['stream'])) {
|
101 |
return $stream;
|
102 |
}
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
}
|
|
|
106 |
private function checkDecode(array $options, array $headers, $stream)
|
107 |
{
|
108 |
// Automatically decode responses when instructed.
|
109 |
if (!empty($options['decode_content'])) {
|
110 |
-
$normalizedKeys = \
|
111 |
if (isset($normalizedKeys['content-encoding'])) {
|
112 |
$encoding = $headers[$normalizedKeys['content-encoding']];
|
113 |
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
|
114 |
-
$stream = new
|
115 |
-
|
|
|
|
|
|
|
116 |
// Remove content-encoding header
|
117 |
unset($headers[$normalizedKeys['content-encoding']]);
|
118 |
// Fix content-length header
|
119 |
if (isset($normalizedKeys['content-length'])) {
|
120 |
-
$headers['x-encoded-content-length']
|
|
|
|
|
121 |
$length = (int) $stream->getSize();
|
122 |
if ($length === 0) {
|
123 |
unset($headers[$normalizedKeys['content-length']]);
|
@@ -128,8 +183,10 @@ class StreamHandler
|
|
128 |
}
|
129 |
}
|
130 |
}
|
|
|
131 |
return [$stream, $headers];
|
132 |
}
|
|
|
133 |
/**
|
134 |
* Drains the source stream into the "sink" client option.
|
135 |
*
|
@@ -141,17 +198,27 @@ class StreamHandler
|
|
141 |
* @return StreamInterface
|
142 |
* @throws \RuntimeException when the sink option is invalid.
|
143 |
*/
|
144 |
-
private function drain(
|
145 |
-
|
|
|
|
|
|
|
146 |
// If a content-length header is provided, then stop reading once
|
147 |
// that number of bytes has been read. This can prevent infinitely
|
148 |
// reading from a stream when dealing with servers that do not honor
|
149 |
// Connection: Close headers.
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
151 |
$sink->seek(0);
|
152 |
$source->close();
|
|
|
153 |
return $sink;
|
154 |
}
|
|
|
155 |
/**
|
156 |
* Create a resource and check to ensure it was created successfully
|
157 |
*
|
@@ -163,43 +230,58 @@ class StreamHandler
|
|
163 |
private function createResource(callable $callback)
|
164 |
{
|
165 |
$errors = null;
|
166 |
-
|
167 |
-
$errors[] = [
|
168 |
-
|
|
|
|
|
|
|
|
|
169 |
});
|
|
|
170 |
$resource = $callback();
|
171 |
-
|
|
|
172 |
if (!$resource) {
|
173 |
$message = 'Error creating resource: ';
|
174 |
foreach ($errors as $err) {
|
175 |
foreach ($err as $key => $value) {
|
176 |
-
$message .= "[
|
177 |
}
|
178 |
}
|
179 |
-
throw new \RuntimeException(
|
180 |
}
|
|
|
181 |
return $resource;
|
182 |
}
|
183 |
-
|
|
|
184 |
{
|
185 |
static $methods;
|
186 |
if (!$methods) {
|
187 |
-
$methods =
|
188 |
}
|
|
|
189 |
// HTTP/1.1 streams using the PHP stream wrapper require a
|
190 |
// Connection: close header
|
191 |
-
if ($request->getProtocolVersion() == '1.1'
|
|
|
|
|
192 |
$request = $request->withHeader('Connection', 'close');
|
193 |
}
|
|
|
194 |
// Ensure SSL is verified by default
|
195 |
if (!isset($options['verify'])) {
|
196 |
-
$options['verify'] =
|
197 |
}
|
|
|
198 |
$params = [];
|
199 |
$context = $this->getDefaultContext($request);
|
200 |
-
|
|
|
201 |
throw new \InvalidArgumentException('on_headers must be callable');
|
202 |
}
|
|
|
203 |
if (!empty($options)) {
|
204 |
foreach ($options as $key => $value) {
|
205 |
$method = "add_{$key}";
|
@@ -208,62 +290,95 @@ class StreamHandler
|
|
208 |
}
|
209 |
}
|
210 |
}
|
|
|
211 |
if (isset($options['stream_context'])) {
|
212 |
-
if (
|
213 |
throw new \InvalidArgumentException('stream_context must be an array');
|
214 |
}
|
215 |
-
$context =
|
|
|
|
|
|
|
216 |
}
|
|
|
217 |
// Microsoft NTLM authentication only supported with curl handler
|
218 |
-
if (isset($options['auth'])
|
|
|
|
|
|
|
|
|
219 |
throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
|
220 |
}
|
|
|
221 |
$uri = $this->resolveHost($request, $options);
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
$resource = \fopen((string) $uri, 'r', null, $context);
|
227 |
-
$this->lastHeaders = $http_response_header;
|
228 |
-
if (isset($options['read_timeout'])) {
|
229 |
-
$readTimeout = $options['read_timeout'];
|
230 |
-
$sec = (int) $readTimeout;
|
231 |
-
$usec = ($readTimeout - $sec) * 100000;
|
232 |
-
\stream_set_timeout($resource, $sec, $usec);
|
233 |
}
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
}
|
237 |
-
|
|
|
238 |
{
|
239 |
$uri = $request->getUri();
|
240 |
-
|
|
|
241 |
if ('v4' === $options['force_ip_resolve']) {
|
242 |
-
$records =
|
243 |
if (!isset($records[0]['ip'])) {
|
244 |
-
throw new
|
245 |
}
|
246 |
$uri = $uri->withHost($records[0]['ip']);
|
247 |
} elseif ('v6' === $options['force_ip_resolve']) {
|
248 |
-
$records =
|
249 |
if (!isset($records[0]['ipv6'])) {
|
250 |
-
throw new
|
251 |
}
|
252 |
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
253 |
}
|
254 |
}
|
|
|
255 |
return $uri;
|
256 |
}
|
257 |
-
|
|
|
258 |
{
|
259 |
$headers = '';
|
260 |
foreach ($request->getHeaders() as $name => $value) {
|
261 |
foreach ($value as $val) {
|
262 |
-
$headers .= "
|
263 |
}
|
264 |
}
|
265 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
$body = (string) $request->getBody();
|
|
|
267 |
if (!empty($body)) {
|
268 |
$context['http']['content'] = $body;
|
269 |
// Prevent the HTTP handler from adding a Content-Type header.
|
@@ -271,105 +386,146 @@ class StreamHandler
|
|
271 |
$context['http']['header'] .= "Content-Type:\r\n";
|
272 |
}
|
273 |
}
|
274 |
-
|
|
|
|
|
275 |
return $context;
|
276 |
}
|
277 |
-
|
|
|
278 |
{
|
279 |
-
if (
|
280 |
$options['http']['proxy'] = $value;
|
281 |
} else {
|
282 |
$scheme = $request->getUri()->getScheme();
|
283 |
if (isset($value[$scheme])) {
|
284 |
-
if (!isset($value['no'])
|
|
|
|
|
|
|
|
|
|
|
285 |
$options['http']['proxy'] = $value[$scheme];
|
286 |
}
|
287 |
}
|
288 |
}
|
289 |
}
|
290 |
-
|
|
|
291 |
{
|
292 |
if ($value > 0) {
|
293 |
$options['http']['timeout'] = $value;
|
294 |
}
|
295 |
}
|
296 |
-
|
|
|
297 |
{
|
298 |
-
if ($value ===
|
299 |
// PHP 5.6 or greater will find the system cert by default. When
|
300 |
// < 5.6, use the Guzzle bundled cacert.
|
301 |
-
if (
|
302 |
-
$options['ssl']['cafile'] = \
|
303 |
}
|
304 |
-
} elseif (
|
305 |
$options['ssl']['cafile'] = $value;
|
306 |
-
if (
|
307 |
-
throw new \RuntimeException("SSL CA bundle not found:
|
308 |
}
|
309 |
-
} elseif ($value ===
|
310 |
-
$options['ssl']['verify_peer'] =
|
311 |
-
$options['ssl']['verify_peer_name'] =
|
312 |
return;
|
313 |
} else {
|
314 |
throw new \InvalidArgumentException('Invalid verify request option');
|
315 |
}
|
316 |
-
|
317 |
-
$options['ssl']['
|
318 |
-
$options['ssl']['
|
|
|
319 |
}
|
320 |
-
|
|
|
321 |
{
|
322 |
-
if (
|
323 |
$options['ssl']['passphrase'] = $value[1];
|
324 |
$value = $value[0];
|
325 |
}
|
326 |
-
|
|
|
327 |
throw new \RuntimeException("SSL certificate not found: {$value}");
|
328 |
}
|
|
|
329 |
$options['ssl']['local_cert'] = $value;
|
330 |
}
|
331 |
-
|
|
|
332 |
{
|
333 |
-
$this->addNotification(
|
334 |
-
|
335 |
-
|
|
|
|
|
|
|
336 |
}
|
337 |
-
|
338 |
}
|
339 |
-
|
|
|
340 |
{
|
341 |
-
if ($value ===
|
342 |
return;
|
343 |
}
|
344 |
-
|
345 |
-
static $
|
346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
|
348 |
-
$this->addNotification(
|
349 |
-
$
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
|
|
|
|
|
|
|
|
354 |
}
|
355 |
-
|
356 |
-
});
|
357 |
}
|
|
|
358 |
private function addNotification(array &$params, callable $notify)
|
359 |
{
|
360 |
// Wrap the existing function if needed.
|
361 |
if (!isset($params['notification'])) {
|
362 |
$params['notification'] = $notify;
|
363 |
} else {
|
364 |
-
$params['notification'] = $this->callArray([
|
|
|
|
|
|
|
365 |
}
|
366 |
}
|
|
|
367 |
private function callArray(array $functions)
|
368 |
{
|
369 |
-
return function () use($functions) {
|
370 |
-
$args =
|
371 |
foreach ($functions as $fn) {
|
372 |
-
|
373 |
}
|
374 |
};
|
375 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\RequestException;
|
5 |
+
use GuzzleHttp\Exception\ConnectException;
|
6 |
+
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
8 |
+
use GuzzleHttp\Psr7;
|
9 |
+
use GuzzleHttp\TransferStats;
|
10 |
+
use Psr\Http\Message\RequestInterface;
|
11 |
+
use Psr\Http\Message\ResponseInterface;
|
12 |
+
use Psr\Http\Message\StreamInterface;
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
/**
|
15 |
* HTTP handler that uses PHP's HTTP stream wrapper.
|
16 |
*/
|
17 |
class StreamHandler
|
18 |
{
|
19 |
private $lastHeaders = [];
|
20 |
+
|
21 |
/**
|
22 |
* Sends an HTTP request.
|
23 |
*
|
26 |
*
|
27 |
* @return PromiseInterface
|
28 |
*/
|
29 |
+
public function __invoke(RequestInterface $request, array $options)
|
30 |
{
|
31 |
// Sleep if there is a delay specified.
|
32 |
if (isset($options['delay'])) {
|
33 |
+
usleep($options['delay'] * 1000);
|
34 |
}
|
35 |
+
|
36 |
+
$startTime = isset($options['on_stats']) ? microtime(true) : null;
|
37 |
+
|
38 |
try {
|
39 |
// Does not support the expect header.
|
40 |
$request = $request->withoutHeader('Expect');
|
41 |
+
|
42 |
// Append a content-length header if body size is zero to match
|
43 |
// cURL's behavior.
|
44 |
if (0 === $request->getBody()->getSize()) {
|
45 |
$request = $request->withHeader('Content-Length', 0);
|
46 |
}
|
47 |
+
|
48 |
+
return $this->createResponse(
|
49 |
+
$request,
|
50 |
+
$options,
|
51 |
+
$this->createStream($request, $options),
|
52 |
+
$startTime
|
53 |
+
);
|
54 |
} catch (\InvalidArgumentException $e) {
|
55 |
throw $e;
|
56 |
} catch (\Exception $e) {
|
57 |
// Determine if the error was a networking error.
|
58 |
$message = $e->getMessage();
|
59 |
// This list can probably get more comprehensive.
|
60 |
+
if (strpos($message, 'getaddrinfo') // DNS lookup failed
|
61 |
+
|| strpos($message, 'Connection refused')
|
62 |
+
|| strpos($message, "couldn't connect to host") // error on HHVM
|
63 |
+
|| strpos($message, "connection attempt failed")
|
64 |
+
) {
|
65 |
+
$e = new ConnectException($e->getMessage(), $request, $e);
|
66 |
}
|
67 |
+
$e = RequestException::wrapException($request, $e);
|
68 |
$this->invokeStats($options, $request, $startTime, null, $e);
|
69 |
+
|
70 |
+
return \GuzzleHttp\Promise\rejection_for($e);
|
71 |
}
|
72 |
}
|
73 |
+
|
74 |
+
private function invokeStats(
|
75 |
+
array $options,
|
76 |
+
RequestInterface $request,
|
77 |
+
$startTime,
|
78 |
+
ResponseInterface $response = null,
|
79 |
+
$error = null
|
80 |
+
) {
|
81 |
if (isset($options['on_stats'])) {
|
82 |
+
$stats = new TransferStats(
|
83 |
+
$request,
|
84 |
+
$response,
|
85 |
+
microtime(true) - $startTime,
|
86 |
+
$error,
|
87 |
+
[]
|
88 |
+
);
|
89 |
+
call_user_func($options['on_stats'], $stats);
|
90 |
}
|
91 |
}
|
92 |
+
|
93 |
+
private function createResponse(
|
94 |
+
RequestInterface $request,
|
95 |
+
array $options,
|
96 |
+
$stream,
|
97 |
+
$startTime
|
98 |
+
) {
|
99 |
$hdrs = $this->lastHeaders;
|
100 |
$this->lastHeaders = [];
|
101 |
+
$parts = explode(' ', array_shift($hdrs), 3);
|
102 |
+
$ver = explode('/', $parts[0])[1];
|
103 |
$status = $parts[1];
|
104 |
$reason = isset($parts[2]) ? $parts[2] : null;
|
105 |
+
$headers = \GuzzleHttp\headers_from_lines($hdrs);
|
106 |
list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
|
107 |
+
$stream = Psr7\stream_for($stream);
|
108 |
$sink = $stream;
|
109 |
+
|
110 |
+
if (strcasecmp('HEAD', $request->getMethod())) {
|
111 |
$sink = $this->createSink($stream, $options);
|
112 |
}
|
113 |
+
|
114 |
+
$response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
|
115 |
+
|
116 |
if (isset($options['on_headers'])) {
|
117 |
try {
|
118 |
$options['on_headers']($response);
|
119 |
} catch (\Exception $e) {
|
120 |
$msg = 'An error was encountered during the on_headers event';
|
121 |
+
$ex = new RequestException($msg, $request, $response, $e);
|
122 |
+
return \GuzzleHttp\Promise\rejection_for($ex);
|
123 |
}
|
124 |
}
|
125 |
+
|
126 |
// Do not drain when the request is a HEAD request because they have
|
127 |
// no body.
|
128 |
if ($sink !== $stream) {
|
129 |
+
$this->drain(
|
130 |
+
$stream,
|
131 |
+
$sink,
|
132 |
+
$response->getHeaderLine('Content-Length')
|
133 |
+
);
|
134 |
}
|
135 |
+
|
136 |
$this->invokeStats($options, $request, $startTime, $response, null);
|
137 |
+
|
138 |
+
return new FulfilledPromise($response);
|
139 |
}
|
140 |
+
|
141 |
+
private function createSink(StreamInterface $stream, array $options)
|
142 |
{
|
143 |
if (!empty($options['stream'])) {
|
144 |
return $stream;
|
145 |
}
|
146 |
+
|
147 |
+
$sink = isset($options['sink'])
|
148 |
+
? $options['sink']
|
149 |
+
: fopen('php://temp', 'r+');
|
150 |
+
|
151 |
+
return is_string($sink)
|
152 |
+
? new Psr7\LazyOpenStream($sink, 'w+')
|
153 |
+
: Psr7\stream_for($sink);
|
154 |
}
|
155 |
+
|
156 |
private function checkDecode(array $options, array $headers, $stream)
|
157 |
{
|
158 |
// Automatically decode responses when instructed.
|
159 |
if (!empty($options['decode_content'])) {
|
160 |
+
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
161 |
if (isset($normalizedKeys['content-encoding'])) {
|
162 |
$encoding = $headers[$normalizedKeys['content-encoding']];
|
163 |
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
|
164 |
+
$stream = new Psr7\InflateStream(
|
165 |
+
Psr7\stream_for($stream)
|
166 |
+
);
|
167 |
+
$headers['x-encoded-content-encoding']
|
168 |
+
= $headers[$normalizedKeys['content-encoding']];
|
169 |
// Remove content-encoding header
|
170 |
unset($headers[$normalizedKeys['content-encoding']]);
|
171 |
// Fix content-length header
|
172 |
if (isset($normalizedKeys['content-length'])) {
|
173 |
+
$headers['x-encoded-content-length']
|
174 |
+
= $headers[$normalizedKeys['content-length']];
|
175 |
+
|
176 |
$length = (int) $stream->getSize();
|
177 |
if ($length === 0) {
|
178 |
unset($headers[$normalizedKeys['content-length']]);
|
183 |
}
|
184 |
}
|
185 |
}
|
186 |
+
|
187 |
return [$stream, $headers];
|
188 |
}
|
189 |
+
|
190 |
/**
|
191 |
* Drains the source stream into the "sink" client option.
|
192 |
*
|
198 |
* @return StreamInterface
|
199 |
* @throws \RuntimeException when the sink option is invalid.
|
200 |
*/
|
201 |
+
private function drain(
|
202 |
+
StreamInterface $source,
|
203 |
+
StreamInterface $sink,
|
204 |
+
$contentLength
|
205 |
+
) {
|
206 |
// If a content-length header is provided, then stop reading once
|
207 |
// that number of bytes has been read. This can prevent infinitely
|
208 |
// reading from a stream when dealing with servers that do not honor
|
209 |
// Connection: Close headers.
|
210 |
+
Psr7\copy_to_stream(
|
211 |
+
$source,
|
212 |
+
$sink,
|
213 |
+
(strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
|
214 |
+
);
|
215 |
+
|
216 |
$sink->seek(0);
|
217 |
$source->close();
|
218 |
+
|
219 |
return $sink;
|
220 |
}
|
221 |
+
|
222 |
/**
|
223 |
* Create a resource and check to ensure it was created successfully
|
224 |
*
|
230 |
private function createResource(callable $callback)
|
231 |
{
|
232 |
$errors = null;
|
233 |
+
set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
|
234 |
+
$errors[] = [
|
235 |
+
'message' => $msg,
|
236 |
+
'file' => $file,
|
237 |
+
'line' => $line
|
238 |
+
];
|
239 |
+
return true;
|
240 |
});
|
241 |
+
|
242 |
$resource = $callback();
|
243 |
+
restore_error_handler();
|
244 |
+
|
245 |
if (!$resource) {
|
246 |
$message = 'Error creating resource: ';
|
247 |
foreach ($errors as $err) {
|
248 |
foreach ($err as $key => $value) {
|
249 |
+
$message .= "[$key] $value" . PHP_EOL;
|
250 |
}
|
251 |
}
|
252 |
+
throw new \RuntimeException(trim($message));
|
253 |
}
|
254 |
+
|
255 |
return $resource;
|
256 |
}
|
257 |
+
|
258 |
+
private function createStream(RequestInterface $request, array $options)
|
259 |
{
|
260 |
static $methods;
|
261 |
if (!$methods) {
|
262 |
+
$methods = array_flip(get_class_methods(__CLASS__));
|
263 |
}
|
264 |
+
|
265 |
// HTTP/1.1 streams using the PHP stream wrapper require a
|
266 |
// Connection: close header
|
267 |
+
if ($request->getProtocolVersion() == '1.1'
|
268 |
+
&& !$request->hasHeader('Connection')
|
269 |
+
) {
|
270 |
$request = $request->withHeader('Connection', 'close');
|
271 |
}
|
272 |
+
|
273 |
// Ensure SSL is verified by default
|
274 |
if (!isset($options['verify'])) {
|
275 |
+
$options['verify'] = true;
|
276 |
}
|
277 |
+
|
278 |
$params = [];
|
279 |
$context = $this->getDefaultContext($request);
|
280 |
+
|
281 |
+
if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
|
282 |
throw new \InvalidArgumentException('on_headers must be callable');
|
283 |
}
|
284 |
+
|
285 |
if (!empty($options)) {
|
286 |
foreach ($options as $key => $value) {
|
287 |
$method = "add_{$key}";
|
290 |
}
|
291 |
}
|
292 |
}
|
293 |
+
|
294 |
if (isset($options['stream_context'])) {
|
295 |
+
if (!is_array($options['stream_context'])) {
|
296 |
throw new \InvalidArgumentException('stream_context must be an array');
|
297 |
}
|
298 |
+
$context = array_replace_recursive(
|
299 |
+
$context,
|
300 |
+
$options['stream_context']
|
301 |
+
);
|
302 |
}
|
303 |
+
|
304 |
// Microsoft NTLM authentication only supported with curl handler
|
305 |
+
if (isset($options['auth'])
|
306 |
+
&& is_array($options['auth'])
|
307 |
+
&& isset($options['auth'][2])
|
308 |
+
&& 'ntlm' == $options['auth'][2]
|
309 |
+
) {
|
310 |
throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
|
311 |
}
|
312 |
+
|
313 |
$uri = $this->resolveHost($request, $options);
|
314 |
+
|
315 |
+
$context = $this->createResource(
|
316 |
+
function () use ($context, $params) {
|
317 |
+
return stream_context_create($context, $params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
}
|
319 |
+
);
|
320 |
+
|
321 |
+
return $this->createResource(
|
322 |
+
function () use ($uri, &$http_response_header, $context, $options) {
|
323 |
+
$resource = fopen((string) $uri, 'r', null, $context);
|
324 |
+
$this->lastHeaders = $http_response_header;
|
325 |
+
|
326 |
+
if (isset($options['read_timeout'])) {
|
327 |
+
$readTimeout = $options['read_timeout'];
|
328 |
+
$sec = (int) $readTimeout;
|
329 |
+
$usec = ($readTimeout - $sec) * 100000;
|
330 |
+
stream_set_timeout($resource, $sec, $usec);
|
331 |
+
}
|
332 |
+
|
333 |
+
return $resource;
|
334 |
+
}
|
335 |
+
);
|
336 |
}
|
337 |
+
|
338 |
+
private function resolveHost(RequestInterface $request, array $options)
|
339 |
{
|
340 |
$uri = $request->getUri();
|
341 |
+
|
342 |
+
if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
|
343 |
if ('v4' === $options['force_ip_resolve']) {
|
344 |
+
$records = dns_get_record($uri->getHost(), DNS_A);
|
345 |
if (!isset($records[0]['ip'])) {
|
346 |
+
throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
|
347 |
}
|
348 |
$uri = $uri->withHost($records[0]['ip']);
|
349 |
} elseif ('v6' === $options['force_ip_resolve']) {
|
350 |
+
$records = dns_get_record($uri->getHost(), DNS_AAAA);
|
351 |
if (!isset($records[0]['ipv6'])) {
|
352 |
+
throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
|
353 |
}
|
354 |
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
355 |
}
|
356 |
}
|
357 |
+
|
358 |
return $uri;
|
359 |
}
|
360 |
+
|
361 |
+
private function getDefaultContext(RequestInterface $request)
|
362 |
{
|
363 |
$headers = '';
|
364 |
foreach ($request->getHeaders() as $name => $value) {
|
365 |
foreach ($value as $val) {
|
366 |
+
$headers .= "$name: $val\r\n";
|
367 |
}
|
368 |
}
|
369 |
+
|
370 |
+
$context = [
|
371 |
+
'http' => [
|
372 |
+
'method' => $request->getMethod(),
|
373 |
+
'header' => $headers,
|
374 |
+
'protocol_version' => $request->getProtocolVersion(),
|
375 |
+
'ignore_errors' => true,
|
376 |
+
'follow_location' => 0,
|
377 |
+
],
|
378 |
+
];
|
379 |
+
|
380 |
$body = (string) $request->getBody();
|
381 |
+
|
382 |
if (!empty($body)) {
|
383 |
$context['http']['content'] = $body;
|
384 |
// Prevent the HTTP handler from adding a Content-Type header.
|
386 |
$context['http']['header'] .= "Content-Type:\r\n";
|
387 |
}
|
388 |
}
|
389 |
+
|
390 |
+
$context['http']['header'] = rtrim($context['http']['header']);
|
391 |
+
|
392 |
return $context;
|
393 |
}
|
394 |
+
|
395 |
+
private function add_proxy(RequestInterface $request, &$options, $value, &$params)
|
396 |
{
|
397 |
+
if (!is_array($value)) {
|
398 |
$options['http']['proxy'] = $value;
|
399 |
} else {
|
400 |
$scheme = $request->getUri()->getScheme();
|
401 |
if (isset($value[$scheme])) {
|
402 |
+
if (!isset($value['no'])
|
403 |
+
|| !\GuzzleHttp\is_host_in_noproxy(
|
404 |
+
$request->getUri()->getHost(),
|
405 |
+
$value['no']
|
406 |
+
)
|
407 |
+
) {
|
408 |
$options['http']['proxy'] = $value[$scheme];
|
409 |
}
|
410 |
}
|
411 |
}
|
412 |
}
|
413 |
+
|
414 |
+
private function add_timeout(RequestInterface $request, &$options, $value, &$params)
|
415 |
{
|
416 |
if ($value > 0) {
|
417 |
$options['http']['timeout'] = $value;
|
418 |
}
|
419 |
}
|
420 |
+
|
421 |
+
private function add_verify(RequestInterface $request, &$options, $value, &$params)
|
422 |
{
|
423 |
+
if ($value === true) {
|
424 |
// PHP 5.6 or greater will find the system cert by default. When
|
425 |
// < 5.6, use the Guzzle bundled cacert.
|
426 |
+
if (PHP_VERSION_ID < 50600) {
|
427 |
+
$options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
|
428 |
}
|
429 |
+
} elseif (is_string($value)) {
|
430 |
$options['ssl']['cafile'] = $value;
|
431 |
+
if (!file_exists($value)) {
|
432 |
+
throw new \RuntimeException("SSL CA bundle not found: $value");
|
433 |
}
|
434 |
+
} elseif ($value === false) {
|
435 |
+
$options['ssl']['verify_peer'] = false;
|
436 |
+
$options['ssl']['verify_peer_name'] = false;
|
437 |
return;
|
438 |
} else {
|
439 |
throw new \InvalidArgumentException('Invalid verify request option');
|
440 |
}
|
441 |
+
|
442 |
+
$options['ssl']['verify_peer'] = true;
|
443 |
+
$options['ssl']['verify_peer_name'] = true;
|
444 |
+
$options['ssl']['allow_self_signed'] = false;
|
445 |
}
|
446 |
+
|
447 |
+
private function add_cert(RequestInterface $request, &$options, $value, &$params)
|
448 |
{
|
449 |
+
if (is_array($value)) {
|
450 |
$options['ssl']['passphrase'] = $value[1];
|
451 |
$value = $value[0];
|
452 |
}
|
453 |
+
|
454 |
+
if (!file_exists($value)) {
|
455 |
throw new \RuntimeException("SSL certificate not found: {$value}");
|
456 |
}
|
457 |
+
|
458 |
$options['ssl']['local_cert'] = $value;
|
459 |
}
|
460 |
+
|
461 |
+
private function add_progress(RequestInterface $request, &$options, $value, &$params)
|
462 |
{
|
463 |
+
$this->addNotification(
|
464 |
+
$params,
|
465 |
+
function ($code, $a, $b, $c, $transferred, $total) use ($value) {
|
466 |
+
if ($code == STREAM_NOTIFY_PROGRESS) {
|
467 |
+
$value($total, $transferred, null, null);
|
468 |
+
}
|
469 |
}
|
470 |
+
);
|
471 |
}
|
472 |
+
|
473 |
+
private function add_debug(RequestInterface $request, &$options, $value, &$params)
|
474 |
{
|
475 |
+
if ($value === false) {
|
476 |
return;
|
477 |
}
|
478 |
+
|
479 |
+
static $map = [
|
480 |
+
STREAM_NOTIFY_CONNECT => 'CONNECT',
|
481 |
+
STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
|
482 |
+
STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
|
483 |
+
STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
|
484 |
+
STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
|
485 |
+
STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
|
486 |
+
STREAM_NOTIFY_PROGRESS => 'PROGRESS',
|
487 |
+
STREAM_NOTIFY_FAILURE => 'FAILURE',
|
488 |
+
STREAM_NOTIFY_COMPLETED => 'COMPLETED',
|
489 |
+
STREAM_NOTIFY_RESOLVE => 'RESOLVE',
|
490 |
+
];
|
491 |
+
static $args = ['severity', 'message', 'message_code',
|
492 |
+
'bytes_transferred', 'bytes_max'];
|
493 |
+
|
494 |
+
$value = \GuzzleHttp\debug_resource($value);
|
495 |
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
|
496 |
+
$this->addNotification(
|
497 |
+
$params,
|
498 |
+
function () use ($ident, $value, $map, $args) {
|
499 |
+
$passed = func_get_args();
|
500 |
+
$code = array_shift($passed);
|
501 |
+
fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
|
502 |
+
foreach (array_filter($passed) as $i => $v) {
|
503 |
+
fwrite($value, $args[$i] . ': "' . $v . '" ');
|
504 |
+
}
|
505 |
+
fwrite($value, "\n");
|
506 |
}
|
507 |
+
);
|
|
|
508 |
}
|
509 |
+
|
510 |
private function addNotification(array &$params, callable $notify)
|
511 |
{
|
512 |
// Wrap the existing function if needed.
|
513 |
if (!isset($params['notification'])) {
|
514 |
$params['notification'] = $notify;
|
515 |
} else {
|
516 |
+
$params['notification'] = $this->callArray([
|
517 |
+
$params['notification'],
|
518 |
+
$notify
|
519 |
+
]);
|
520 |
}
|
521 |
}
|
522 |
+
|
523 |
private function callArray(array $functions)
|
524 |
{
|
525 |
+
return function () use ($functions) {
|
526 |
+
$args = func_get_args();
|
527 |
foreach ($functions as $fn) {
|
528 |
+
call_user_func_array($fn, $args);
|
529 |
}
|
530 |
};
|
531 |
}
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
/**
|
7 |
* Creates a composed Guzzle handler function by stacking middlewares on top of
|
8 |
* an HTTP handler function.
|
@@ -11,10 +11,13 @@ class HandlerStack
|
|
11 |
{
|
12 |
/** @var callable */
|
13 |
private $handler;
|
|
|
14 |
/** @var array */
|
15 |
private $stack = [];
|
|
|
16 |
/** @var callable|null */
|
17 |
private $cached;
|
|
|
18 |
/**
|
19 |
* Creates a default handler stack that can be used by clients.
|
20 |
*
|
@@ -35,12 +38,14 @@ class HandlerStack
|
|
35 |
public static function create(callable $handler = null)
|
36 |
{
|
37 |
$stack = new self($handler ?: choose_handler());
|
38 |
-
$stack->push(
|
39 |
-
$stack->push(
|
40 |
-
$stack->push(
|
41 |
-
$stack->push(
|
|
|
42 |
return $stack;
|
43 |
}
|
|
|
44 |
/**
|
45 |
* @param callable $handler Underlying HTTP handler.
|
46 |
*/
|
@@ -48,17 +53,20 @@ class HandlerStack
|
|
48 |
{
|
49 |
$this->handler = $handler;
|
50 |
}
|
|
|
51 |
/**
|
52 |
* Invokes the handler stack as a composed handler
|
53 |
*
|
54 |
* @param RequestInterface $request
|
55 |
* @param array $options
|
56 |
*/
|
57 |
-
public function __invoke(
|
58 |
{
|
59 |
$handler = $this->resolve();
|
|
|
60 |
return $handler($request, $options);
|
61 |
}
|
|
|
62 |
/**
|
63 |
* Dumps a string representation of the stack.
|
64 |
*
|
@@ -71,19 +79,23 @@ class HandlerStack
|
|
71 |
if ($this->handler) {
|
72 |
$stack[] = "0) Handler: " . $this->debugCallable($this->handler);
|
73 |
}
|
|
|
74 |
$result = '';
|
75 |
-
foreach (
|
76 |
$depth++;
|
77 |
$str = "{$depth}) Name: '{$tuple[1]}', ";
|
78 |
$str .= "Function: " . $this->debugCallable($tuple[0]);
|
79 |
$result = "> {$str}\n{$result}";
|
80 |
$stack[] = $str;
|
81 |
}
|
82 |
-
|
|
|
83 |
$result .= "< {$stack[$k]}\n";
|
84 |
}
|
|
|
85 |
return $result;
|
86 |
}
|
|
|
87 |
/**
|
88 |
* Set the HTTP handler that actually returns a promise.
|
89 |
*
|
@@ -95,6 +107,7 @@ class HandlerStack
|
|
95 |
$this->handler = $handler;
|
96 |
$this->cached = null;
|
97 |
}
|
|
|
98 |
/**
|
99 |
* Returns true if the builder has a handler.
|
100 |
*
|
@@ -104,6 +117,7 @@ class HandlerStack
|
|
104 |
{
|
105 |
return (bool) $this->handler;
|
106 |
}
|
|
|
107 |
/**
|
108 |
* Unshift a middleware to the bottom of the stack.
|
109 |
*
|
@@ -112,9 +126,10 @@ class HandlerStack
|
|
112 |
*/
|
113 |
public function unshift(callable $middleware, $name = null)
|
114 |
{
|
115 |
-
|
116 |
$this->cached = null;
|
117 |
}
|
|
|
118 |
/**
|
119 |
* Push a middleware to the top of the stack.
|
120 |
*
|
@@ -126,6 +141,7 @@ class HandlerStack
|
|
126 |
$this->stack[] = [$middleware, $name];
|
127 |
$this->cached = null;
|
128 |
}
|
|
|
129 |
/**
|
130 |
* Add a middleware before another middleware by name.
|
131 |
*
|
@@ -135,8 +151,9 @@ class HandlerStack
|
|
135 |
*/
|
136 |
public function before($findName, callable $middleware, $withName = '')
|
137 |
{
|
138 |
-
$this->splice($findName, $withName, $middleware,
|
139 |
}
|
|
|
140 |
/**
|
141 |
* Add a middleware after another middleware by name.
|
142 |
*
|
@@ -146,8 +163,9 @@ class HandlerStack
|
|
146 |
*/
|
147 |
public function after($findName, callable $middleware, $withName = '')
|
148 |
{
|
149 |
-
$this->splice($findName, $withName, $middleware,
|
150 |
}
|
|
|
151 |
/**
|
152 |
* Remove a middleware by instance or name from the stack.
|
153 |
*
|
@@ -156,11 +174,15 @@ class HandlerStack
|
|
156 |
public function remove($remove)
|
157 |
{
|
158 |
$this->cached = null;
|
159 |
-
$idx =
|
160 |
-
$this->stack =
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
163 |
}
|
|
|
164 |
/**
|
165 |
* Compose the middleware and handler into a single callable function.
|
166 |
*
|
@@ -172,13 +194,17 @@ class HandlerStack
|
|
172 |
if (!($prev = $this->handler)) {
|
173 |
throw new \LogicException('No handler has been specified');
|
174 |
}
|
175 |
-
|
|
|
176 |
$prev = $fn[0]($prev);
|
177 |
}
|
|
|
178 |
$this->cached = $prev;
|
179 |
}
|
|
|
180 |
return $this->cached;
|
181 |
}
|
|
|
182 |
/**
|
183 |
* @param $name
|
184 |
* @return int
|
@@ -190,8 +216,10 @@ class HandlerStack
|
|
190 |
return $k;
|
191 |
}
|
192 |
}
|
193 |
-
|
|
|
194 |
}
|
|
|
195 |
/**
|
196 |
* Splices a function into the middleware list at a specific position.
|
197 |
*
|
@@ -205,20 +233,22 @@ class HandlerStack
|
|
205 |
$this->cached = null;
|
206 |
$idx = $this->findByName($findName);
|
207 |
$tuple = [$middleware, $withName];
|
|
|
208 |
if ($before) {
|
209 |
if ($idx === 0) {
|
210 |
-
|
211 |
} else {
|
212 |
$replacement = [$tuple, $this->stack[$idx]];
|
213 |
-
|
214 |
}
|
215 |
-
} elseif ($idx ===
|
216 |
$this->stack[] = $tuple;
|
217 |
} else {
|
218 |
$replacement = [$this->stack[$idx], $tuple];
|
219 |
-
|
220 |
}
|
221 |
}
|
|
|
222 |
/**
|
223 |
* Provides a debug string for a given callable.
|
224 |
*
|
@@ -228,12 +258,16 @@ class HandlerStack
|
|
228 |
*/
|
229 |
private function debugCallable($fn)
|
230 |
{
|
231 |
-
if (
|
232 |
return "callable({$fn})";
|
233 |
}
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
236 |
}
|
237 |
-
|
|
|
238 |
}
|
239 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Creates a composed Guzzle handler function by stacking middlewares on top of
|
8 |
* an HTTP handler function.
|
11 |
{
|
12 |
/** @var callable */
|
13 |
private $handler;
|
14 |
+
|
15 |
/** @var array */
|
16 |
private $stack = [];
|
17 |
+
|
18 |
/** @var callable|null */
|
19 |
private $cached;
|
20 |
+
|
21 |
/**
|
22 |
* Creates a default handler stack that can be used by clients.
|
23 |
*
|
38 |
public static function create(callable $handler = null)
|
39 |
{
|
40 |
$stack = new self($handler ?: choose_handler());
|
41 |
+
$stack->push(Middleware::httpErrors(), 'http_errors');
|
42 |
+
$stack->push(Middleware::redirect(), 'allow_redirects');
|
43 |
+
$stack->push(Middleware::cookies(), 'cookies');
|
44 |
+
$stack->push(Middleware::prepareBody(), 'prepare_body');
|
45 |
+
|
46 |
return $stack;
|
47 |
}
|
48 |
+
|
49 |
/**
|
50 |
* @param callable $handler Underlying HTTP handler.
|
51 |
*/
|
53 |
{
|
54 |
$this->handler = $handler;
|
55 |
}
|
56 |
+
|
57 |
/**
|
58 |
* Invokes the handler stack as a composed handler
|
59 |
*
|
60 |
* @param RequestInterface $request
|
61 |
* @param array $options
|
62 |
*/
|
63 |
+
public function __invoke(RequestInterface $request, array $options)
|
64 |
{
|
65 |
$handler = $this->resolve();
|
66 |
+
|
67 |
return $handler($request, $options);
|
68 |
}
|
69 |
+
|
70 |
/**
|
71 |
* Dumps a string representation of the stack.
|
72 |
*
|
79 |
if ($this->handler) {
|
80 |
$stack[] = "0) Handler: " . $this->debugCallable($this->handler);
|
81 |
}
|
82 |
+
|
83 |
$result = '';
|
84 |
+
foreach (array_reverse($this->stack) as $tuple) {
|
85 |
$depth++;
|
86 |
$str = "{$depth}) Name: '{$tuple[1]}', ";
|
87 |
$str .= "Function: " . $this->debugCallable($tuple[0]);
|
88 |
$result = "> {$str}\n{$result}";
|
89 |
$stack[] = $str;
|
90 |
}
|
91 |
+
|
92 |
+
foreach (array_keys($stack) as $k) {
|
93 |
$result .= "< {$stack[$k]}\n";
|
94 |
}
|
95 |
+
|
96 |
return $result;
|
97 |
}
|
98 |
+
|
99 |
/**
|
100 |
* Set the HTTP handler that actually returns a promise.
|
101 |
*
|
107 |
$this->handler = $handler;
|
108 |
$this->cached = null;
|
109 |
}
|
110 |
+
|
111 |
/**
|
112 |
* Returns true if the builder has a handler.
|
113 |
*
|
117 |
{
|
118 |
return (bool) $this->handler;
|
119 |
}
|
120 |
+
|
121 |
/**
|
122 |
* Unshift a middleware to the bottom of the stack.
|
123 |
*
|
126 |
*/
|
127 |
public function unshift(callable $middleware, $name = null)
|
128 |
{
|
129 |
+
array_unshift($this->stack, [$middleware, $name]);
|
130 |
$this->cached = null;
|
131 |
}
|
132 |
+
|
133 |
/**
|
134 |
* Push a middleware to the top of the stack.
|
135 |
*
|
141 |
$this->stack[] = [$middleware, $name];
|
142 |
$this->cached = null;
|
143 |
}
|
144 |
+
|
145 |
/**
|
146 |
* Add a middleware before another middleware by name.
|
147 |
*
|
151 |
*/
|
152 |
public function before($findName, callable $middleware, $withName = '')
|
153 |
{
|
154 |
+
$this->splice($findName, $withName, $middleware, true);
|
155 |
}
|
156 |
+
|
157 |
/**
|
158 |
* Add a middleware after another middleware by name.
|
159 |
*
|
163 |
*/
|
164 |
public function after($findName, callable $middleware, $withName = '')
|
165 |
{
|
166 |
+
$this->splice($findName, $withName, $middleware, false);
|
167 |
}
|
168 |
+
|
169 |
/**
|
170 |
* Remove a middleware by instance or name from the stack.
|
171 |
*
|
174 |
public function remove($remove)
|
175 |
{
|
176 |
$this->cached = null;
|
177 |
+
$idx = is_callable($remove) ? 0 : 1;
|
178 |
+
$this->stack = array_values(array_filter(
|
179 |
+
$this->stack,
|
180 |
+
function ($tuple) use ($idx, $remove) {
|
181 |
+
return $tuple[$idx] !== $remove;
|
182 |
+
}
|
183 |
+
));
|
184 |
}
|
185 |
+
|
186 |
/**
|
187 |
* Compose the middleware and handler into a single callable function.
|
188 |
*
|
194 |
if (!($prev = $this->handler)) {
|
195 |
throw new \LogicException('No handler has been specified');
|
196 |
}
|
197 |
+
|
198 |
+
foreach (array_reverse($this->stack) as $fn) {
|
199 |
$prev = $fn[0]($prev);
|
200 |
}
|
201 |
+
|
202 |
$this->cached = $prev;
|
203 |
}
|
204 |
+
|
205 |
return $this->cached;
|
206 |
}
|
207 |
+
|
208 |
/**
|
209 |
* @param $name
|
210 |
* @return int
|
216 |
return $k;
|
217 |
}
|
218 |
}
|
219 |
+
|
220 |
+
throw new \InvalidArgumentException("Middleware not found: $name");
|
221 |
}
|
222 |
+
|
223 |
/**
|
224 |
* Splices a function into the middleware list at a specific position.
|
225 |
*
|
233 |
$this->cached = null;
|
234 |
$idx = $this->findByName($findName);
|
235 |
$tuple = [$middleware, $withName];
|
236 |
+
|
237 |
if ($before) {
|
238 |
if ($idx === 0) {
|
239 |
+
array_unshift($this->stack, $tuple);
|
240 |
} else {
|
241 |
$replacement = [$tuple, $this->stack[$idx]];
|
242 |
+
array_splice($this->stack, $idx, 1, $replacement);
|
243 |
}
|
244 |
+
} elseif ($idx === count($this->stack) - 1) {
|
245 |
$this->stack[] = $tuple;
|
246 |
} else {
|
247 |
$replacement = [$this->stack[$idx], $tuple];
|
248 |
+
array_splice($this->stack, $idx, 1, $replacement);
|
249 |
}
|
250 |
}
|
251 |
+
|
252 |
/**
|
253 |
* Provides a debug string for a given callable.
|
254 |
*
|
258 |
*/
|
259 |
private function debugCallable($fn)
|
260 |
{
|
261 |
+
if (is_string($fn)) {
|
262 |
return "callable({$fn})";
|
263 |
}
|
264 |
+
|
265 |
+
if (is_array($fn)) {
|
266 |
+
return is_string($fn[0])
|
267 |
+
? "callable({$fn[0]}::{$fn[1]})"
|
268 |
+
: "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
|
269 |
}
|
270 |
+
|
271 |
+
return 'callable(' . spl_object_hash($fn) . ')';
|
272 |
}
|
273 |
}
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\MessageInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
8 |
/**
|
9 |
* Formats log messages using variable substitutions for requests, responses,
|
10 |
* and other transactional data.
|
@@ -42,8 +42,10 @@ class MessageFormatter
|
|
42 |
const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
|
43 |
const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
44 |
const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
|
|
45 |
/** @var string Template used to format log messages */
|
46 |
private $template;
|
|
|
47 |
/**
|
48 |
* @param string $template Log message template
|
49 |
*/
|
@@ -51,6 +53,7 @@ class MessageFormatter
|
|
51 |
{
|
52 |
$this->template = $template ?: self::CLF;
|
53 |
}
|
|
|
54 |
/**
|
55 |
* Returns a formatted message string.
|
56 |
*
|
@@ -60,92 +63,118 @@ class MessageFormatter
|
|
60 |
*
|
61 |
* @return string
|
62 |
*/
|
63 |
-
public function format(
|
64 |
-
|
|
|
|
|
|
|
65 |
$cache = [];
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
$result =
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
}
|
143 |
-
|
|
|
144 |
{
|
145 |
$result = '';
|
146 |
foreach ($message->getHeaders() as $name => $values) {
|
147 |
-
$result .= $name . ': ' .
|
148 |
}
|
149 |
-
|
|
|
150 |
}
|
151 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use Psr\Http\Message\MessageInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
|
|
|
|
|
|
|
8 |
/**
|
9 |
* Formats log messages using variable substitutions for requests, responses,
|
10 |
* and other transactional data.
|
42 |
const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
|
43 |
const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
44 |
const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
45 |
+
|
46 |
/** @var string Template used to format log messages */
|
47 |
private $template;
|
48 |
+
|
49 |
/**
|
50 |
* @param string $template Log message template
|
51 |
*/
|
53 |
{
|
54 |
$this->template = $template ?: self::CLF;
|
55 |
}
|
56 |
+
|
57 |
/**
|
58 |
* Returns a formatted message string.
|
59 |
*
|
63 |
*
|
64 |
* @return string
|
65 |
*/
|
66 |
+
public function format(
|
67 |
+
RequestInterface $request,
|
68 |
+
ResponseInterface $response = null,
|
69 |
+
\Exception $error = null
|
70 |
+
) {
|
71 |
$cache = [];
|
72 |
+
|
73 |
+
return preg_replace_callback(
|
74 |
+
'/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
|
75 |
+
function (array $matches) use ($request, $response, $error, &$cache) {
|
76 |
+
if (isset($cache[$matches[1]])) {
|
77 |
+
return $cache[$matches[1]];
|
78 |
+
}
|
79 |
+
|
80 |
+
$result = '';
|
81 |
+
switch ($matches[1]) {
|
82 |
+
case 'request':
|
83 |
+
$result = Psr7\str($request);
|
84 |
+
break;
|
85 |
+
case 'response':
|
86 |
+
$result = $response ? Psr7\str($response) : '';
|
87 |
+
break;
|
88 |
+
case 'req_headers':
|
89 |
+
$result = trim($request->getMethod()
|
90 |
+
. ' ' . $request->getRequestTarget())
|
91 |
+
. ' HTTP/' . $request->getProtocolVersion() . "\r\n"
|
92 |
+
. $this->headers($request);
|
93 |
+
break;
|
94 |
+
case 'res_headers':
|
95 |
+
$result = $response ?
|
96 |
+
sprintf(
|
97 |
+
'HTTP/%s %d %s',
|
98 |
+
$response->getProtocolVersion(),
|
99 |
+
$response->getStatusCode(),
|
100 |
+
$response->getReasonPhrase()
|
101 |
+
) . "\r\n" . $this->headers($response)
|
102 |
+
: 'NULL';
|
103 |
+
break;
|
104 |
+
case 'req_body':
|
105 |
+
$result = $request->getBody();
|
106 |
+
break;
|
107 |
+
case 'res_body':
|
108 |
+
$result = $response ? $response->getBody() : 'NULL';
|
109 |
+
break;
|
110 |
+
case 'ts':
|
111 |
+
case 'date_iso_8601':
|
112 |
+
$result = gmdate('c');
|
113 |
+
break;
|
114 |
+
case 'date_common_log':
|
115 |
+
$result = date('d/M/Y:H:i:s O');
|
116 |
+
break;
|
117 |
+
case 'method':
|
118 |
+
$result = $request->getMethod();
|
119 |
+
break;
|
120 |
+
case 'version':
|
121 |
+
$result = $request->getProtocolVersion();
|
122 |
+
break;
|
123 |
+
case 'uri':
|
124 |
+
case 'url':
|
125 |
+
$result = $request->getUri();
|
126 |
+
break;
|
127 |
+
case 'target':
|
128 |
+
$result = $request->getRequestTarget();
|
129 |
+
break;
|
130 |
+
case 'req_version':
|
131 |
+
$result = $request->getProtocolVersion();
|
132 |
+
break;
|
133 |
+
case 'res_version':
|
134 |
+
$result = $response
|
135 |
+
? $response->getProtocolVersion()
|
136 |
+
: 'NULL';
|
137 |
+
break;
|
138 |
+
case 'host':
|
139 |
+
$result = $request->getHeaderLine('Host');
|
140 |
+
break;
|
141 |
+
case 'hostname':
|
142 |
+
$result = gethostname();
|
143 |
+
break;
|
144 |
+
case 'code':
|
145 |
+
$result = $response ? $response->getStatusCode() : 'NULL';
|
146 |
+
break;
|
147 |
+
case 'phrase':
|
148 |
+
$result = $response ? $response->getReasonPhrase() : 'NULL';
|
149 |
+
break;
|
150 |
+
case 'error':
|
151 |
+
$result = $error ? $error->getMessage() : 'NULL';
|
152 |
+
break;
|
153 |
+
default:
|
154 |
+
// handle prefixed dynamic headers
|
155 |
+
if (strpos($matches[1], 'req_header_') === 0) {
|
156 |
+
$result = $request->getHeaderLine(substr($matches[1], 11));
|
157 |
+
} elseif (strpos($matches[1], 'res_header_') === 0) {
|
158 |
+
$result = $response
|
159 |
+
? $response->getHeaderLine(substr($matches[1], 11))
|
160 |
+
: 'NULL';
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
$cache[$matches[1]] = $result;
|
165 |
+
return $result;
|
166 |
+
},
|
167 |
+
$this->template
|
168 |
+
);
|
169 |
}
|
170 |
+
|
171 |
+
private function headers(MessageInterface $message)
|
172 |
{
|
173 |
$result = '';
|
174 |
foreach ($message->getHeaders() as $name => $values) {
|
175 |
+
$result .= $name . ': ' . implode(', ', $values) . "\r\n";
|
176 |
}
|
177 |
+
|
178 |
+
return trim($result);
|
179 |
}
|
180 |
}
|
@@ -1,14 +1,14 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Cookie\CookieJarInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\RequestException;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\RejectedPromise;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
10 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Log\LoggerInterface;
|
11 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Log\LogLevel;
|
12 |
/**
|
13 |
* Functions used to create and wrap handlers with handler middleware.
|
14 |
*/
|
@@ -25,21 +25,25 @@ final class Middleware
|
|
25 |
public static function cookies()
|
26 |
{
|
27 |
return function (callable $handler) {
|
28 |
-
return function ($request, array $options) use($handler) {
|
29 |
if (empty($options['cookies'])) {
|
30 |
return $handler($request, $options);
|
31 |
-
} elseif (
|
32 |
-
throw new \InvalidArgumentException('
|
33 |
}
|
34 |
$cookieJar = $options['cookies'];
|
35 |
$request = $cookieJar->withCookieHeader($request);
|
36 |
-
return $handler($request, $options)
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
|
|
|
|
40 |
};
|
41 |
};
|
42 |
}
|
|
|
43 |
/**
|
44 |
* Middleware that throws exceptions for 4xx or 5xx responses when the
|
45 |
* "http_error" request option is set to true.
|
@@ -49,20 +53,23 @@ final class Middleware
|
|
49 |
public static function httpErrors()
|
50 |
{
|
51 |
return function (callable $handler) {
|
52 |
-
return function ($request, array $options) use($handler) {
|
53 |
if (empty($options['http_errors'])) {
|
54 |
return $handler($request, $options);
|
55 |
}
|
56 |
-
return $handler($request, $options)->then(
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
60 |
}
|
61 |
-
|
62 |
-
});
|
63 |
};
|
64 |
};
|
65 |
}
|
|
|
66 |
/**
|
67 |
* Middleware that pushes history data to an ArrayAccess container.
|
68 |
*
|
@@ -73,21 +80,36 @@ final class Middleware
|
|
73 |
*/
|
74 |
public static function history(&$container)
|
75 |
{
|
76 |
-
if (
|
77 |
throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
|
78 |
}
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
};
|
89 |
};
|
90 |
}
|
|
|
91 |
/**
|
92 |
* Middleware that invokes a callback before and after sending a request.
|
93 |
*
|
@@ -103,8 +125,8 @@ final class Middleware
|
|
103 |
*/
|
104 |
public static function tap(callable $before = null, callable $after = null)
|
105 |
{
|
106 |
-
return function (callable $handler) use($before, $after) {
|
107 |
-
return function ($request, array $options) use($handler, $before, $after) {
|
108 |
if ($before) {
|
109 |
$before($request, $options);
|
110 |
}
|
@@ -116,6 +138,7 @@ final class Middleware
|
|
116 |
};
|
117 |
};
|
118 |
}
|
|
|
119 |
/**
|
120 |
* Middleware that handles request redirects.
|
121 |
*
|
@@ -124,9 +147,10 @@ final class Middleware
|
|
124 |
public static function redirect()
|
125 |
{
|
126 |
return function (callable $handler) {
|
127 |
-
return new
|
128 |
};
|
129 |
}
|
|
|
130 |
/**
|
131 |
* Middleware that retries requests based on the boolean result of
|
132 |
* invoking the provided "decider" function.
|
@@ -144,10 +168,11 @@ final class Middleware
|
|
144 |
*/
|
145 |
public static function retry(callable $decider, callable $delay = null)
|
146 |
{
|
147 |
-
return function (callable $handler) use($decider, $delay) {
|
148 |
-
return new
|
149 |
};
|
150 |
}
|
|
|
151 |
/**
|
152 |
* Middleware that logs requests, responses, and errors using a message
|
153 |
* formatter.
|
@@ -158,23 +183,29 @@ final class Middleware
|
|
158 |
*
|
159 |
* @return callable Returns a function that accepts the next handler.
|
160 |
*/
|
161 |
-
public static function log(
|
162 |
{
|
163 |
-
return function (callable $handler) use($logger, $formatter, $logLevel) {
|
164 |
-
return function ($request, array $options) use($handler, $logger, $formatter, $logLevel) {
|
165 |
-
return $handler($request, $options)->then(
|
166 |
-
$
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
$
|
172 |
-
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
|
|
|
|
175 |
};
|
176 |
};
|
177 |
}
|
|
|
178 |
/**
|
179 |
* This middleware adds a default content-type if possible, a default
|
180 |
* content-length or transfer-encoding header, and the expect header.
|
@@ -184,9 +215,10 @@ final class Middleware
|
|
184 |
public static function prepareBody()
|
185 |
{
|
186 |
return function (callable $handler) {
|
187 |
-
return new
|
188 |
};
|
189 |
}
|
|
|
190 |
/**
|
191 |
* Middleware that applies a map function to the request before passing to
|
192 |
* the next handler.
|
@@ -197,12 +229,13 @@ final class Middleware
|
|
197 |
*/
|
198 |
public static function mapRequest(callable $fn)
|
199 |
{
|
200 |
-
return function (callable $handler) use($fn) {
|
201 |
-
return function ($request, array $options) use($handler, $fn) {
|
202 |
return $handler($fn($request), $options);
|
203 |
};
|
204 |
};
|
205 |
}
|
|
|
206 |
/**
|
207 |
* Middleware that applies a map function to the resolved promise's
|
208 |
* response.
|
@@ -213,8 +246,8 @@ final class Middleware
|
|
213 |
*/
|
214 |
public static function mapResponse(callable $fn)
|
215 |
{
|
216 |
-
return function (callable $handler) use($fn) {
|
217 |
-
return function ($request, array $options) use($handler, $fn) {
|
218 |
return $handler($request, $options)->then($fn);
|
219 |
};
|
220 |
};
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Cookie\CookieJarInterface;
|
5 |
+
use GuzzleHttp\Exception\RequestException;
|
6 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
use Psr\Http\Message\ResponseInterface;
|
9 |
+
use Psr\Log\LoggerInterface;
|
10 |
+
use Psr\Log\LogLevel;
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Functions used to create and wrap handlers with handler middleware.
|
14 |
*/
|
25 |
public static function cookies()
|
26 |
{
|
27 |
return function (callable $handler) {
|
28 |
+
return function ($request, array $options) use ($handler) {
|
29 |
if (empty($options['cookies'])) {
|
30 |
return $handler($request, $options);
|
31 |
+
} elseif (!($options['cookies'] instanceof CookieJarInterface)) {
|
32 |
+
throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
|
33 |
}
|
34 |
$cookieJar = $options['cookies'];
|
35 |
$request = $cookieJar->withCookieHeader($request);
|
36 |
+
return $handler($request, $options)
|
37 |
+
->then(
|
38 |
+
function ($response) use ($cookieJar, $request) {
|
39 |
+
$cookieJar->extractCookies($request, $response);
|
40 |
+
return $response;
|
41 |
+
}
|
42 |
+
);
|
43 |
};
|
44 |
};
|
45 |
}
|
46 |
+
|
47 |
/**
|
48 |
* Middleware that throws exceptions for 4xx or 5xx responses when the
|
49 |
* "http_error" request option is set to true.
|
53 |
public static function httpErrors()
|
54 |
{
|
55 |
return function (callable $handler) {
|
56 |
+
return function ($request, array $options) use ($handler) {
|
57 |
if (empty($options['http_errors'])) {
|
58 |
return $handler($request, $options);
|
59 |
}
|
60 |
+
return $handler($request, $options)->then(
|
61 |
+
function (ResponseInterface $response) use ($request, $handler) {
|
62 |
+
$code = $response->getStatusCode();
|
63 |
+
if ($code < 400) {
|
64 |
+
return $response;
|
65 |
+
}
|
66 |
+
throw RequestException::create($request, $response);
|
67 |
}
|
68 |
+
);
|
|
|
69 |
};
|
70 |
};
|
71 |
}
|
72 |
+
|
73 |
/**
|
74 |
* Middleware that pushes history data to an ArrayAccess container.
|
75 |
*
|
80 |
*/
|
81 |
public static function history(&$container)
|
82 |
{
|
83 |
+
if (!is_array($container) && !$container instanceof \ArrayAccess) {
|
84 |
throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
|
85 |
}
|
86 |
+
|
87 |
+
return function (callable $handler) use (&$container) {
|
88 |
+
return function ($request, array $options) use ($handler, &$container) {
|
89 |
+
return $handler($request, $options)->then(
|
90 |
+
function ($value) use ($request, &$container, $options) {
|
91 |
+
$container[] = [
|
92 |
+
'request' => $request,
|
93 |
+
'response' => $value,
|
94 |
+
'error' => null,
|
95 |
+
'options' => $options
|
96 |
+
];
|
97 |
+
return $value;
|
98 |
+
},
|
99 |
+
function ($reason) use ($request, &$container, $options) {
|
100 |
+
$container[] = [
|
101 |
+
'request' => $request,
|
102 |
+
'response' => null,
|
103 |
+
'error' => $reason,
|
104 |
+
'options' => $options
|
105 |
+
];
|
106 |
+
return \GuzzleHttp\Promise\rejection_for($reason);
|
107 |
+
}
|
108 |
+
);
|
109 |
};
|
110 |
};
|
111 |
}
|
112 |
+
|
113 |
/**
|
114 |
* Middleware that invokes a callback before and after sending a request.
|
115 |
*
|
125 |
*/
|
126 |
public static function tap(callable $before = null, callable $after = null)
|
127 |
{
|
128 |
+
return function (callable $handler) use ($before, $after) {
|
129 |
+
return function ($request, array $options) use ($handler, $before, $after) {
|
130 |
if ($before) {
|
131 |
$before($request, $options);
|
132 |
}
|
138 |
};
|
139 |
};
|
140 |
}
|
141 |
+
|
142 |
/**
|
143 |
* Middleware that handles request redirects.
|
144 |
*
|
147 |
public static function redirect()
|
148 |
{
|
149 |
return function (callable $handler) {
|
150 |
+
return new RedirectMiddleware($handler);
|
151 |
};
|
152 |
}
|
153 |
+
|
154 |
/**
|
155 |
* Middleware that retries requests based on the boolean result of
|
156 |
* invoking the provided "decider" function.
|
168 |
*/
|
169 |
public static function retry(callable $decider, callable $delay = null)
|
170 |
{
|
171 |
+
return function (callable $handler) use ($decider, $delay) {
|
172 |
+
return new RetryMiddleware($decider, $handler, $delay);
|
173 |
};
|
174 |
}
|
175 |
+
|
176 |
/**
|
177 |
* Middleware that logs requests, responses, and errors using a message
|
178 |
* formatter.
|
183 |
*
|
184 |
* @return callable Returns a function that accepts the next handler.
|
185 |
*/
|
186 |
+
public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
|
187 |
{
|
188 |
+
return function (callable $handler) use ($logger, $formatter, $logLevel) {
|
189 |
+
return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
|
190 |
+
return $handler($request, $options)->then(
|
191 |
+
function ($response) use ($logger, $request, $formatter, $logLevel) {
|
192 |
+
$message = $formatter->format($request, $response);
|
193 |
+
$logger->log($logLevel, $message);
|
194 |
+
return $response;
|
195 |
+
},
|
196 |
+
function ($reason) use ($logger, $request, $formatter) {
|
197 |
+
$response = $reason instanceof RequestException
|
198 |
+
? $reason->getResponse()
|
199 |
+
: null;
|
200 |
+
$message = $formatter->format($request, $response, $reason);
|
201 |
+
$logger->notice($message);
|
202 |
+
return \GuzzleHttp\Promise\rejection_for($reason);
|
203 |
+
}
|
204 |
+
);
|
205 |
};
|
206 |
};
|
207 |
}
|
208 |
+
|
209 |
/**
|
210 |
* This middleware adds a default content-type if possible, a default
|
211 |
* content-length or transfer-encoding header, and the expect header.
|
215 |
public static function prepareBody()
|
216 |
{
|
217 |
return function (callable $handler) {
|
218 |
+
return new PrepareBodyMiddleware($handler);
|
219 |
};
|
220 |
}
|
221 |
+
|
222 |
/**
|
223 |
* Middleware that applies a map function to the request before passing to
|
224 |
* the next handler.
|
229 |
*/
|
230 |
public static function mapRequest(callable $fn)
|
231 |
{
|
232 |
+
return function (callable $handler) use ($fn) {
|
233 |
+
return function ($request, array $options) use ($handler, $fn) {
|
234 |
return $handler($fn($request), $options);
|
235 |
};
|
236 |
};
|
237 |
}
|
238 |
+
|
239 |
/**
|
240 |
* Middleware that applies a map function to the resolved promise's
|
241 |
* response.
|
246 |
*/
|
247 |
public static function mapResponse(callable $fn)
|
248 |
{
|
249 |
+
return function (callable $handler) use ($fn) {
|
250 |
+
return function ($request, array $options) use ($handler, $fn) {
|
251 |
return $handler($request, $options)->then($fn);
|
252 |
};
|
253 |
};
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromisorInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\EachPromise;
|
8 |
/**
|
9 |
* Sends and iterator of requests concurrently using a capped pool size.
|
10 |
*
|
@@ -16,10 +16,11 @@ use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\EachPromise;
|
|
16 |
* "request_options" array that should be merged on top of any existing
|
17 |
* options, and the function MUST then return a wait-able promise.
|
18 |
*/
|
19 |
-
class Pool implements
|
20 |
{
|
21 |
/** @var EachPromise */
|
22 |
private $each;
|
|
|
23 |
/**
|
24 |
* @param ClientInterface $client Client used to send the requests.
|
25 |
* @param array|\Iterator $requests Requests or functions that return
|
@@ -30,38 +31,49 @@ class Pool implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromisorInterf
|
|
30 |
* - fulfilled: (callable) Function to invoke when a request completes.
|
31 |
* - rejected: (callable) Function to invoke when a request is rejected.
|
32 |
*/
|
33 |
-
public function __construct(
|
34 |
-
|
|
|
|
|
|
|
35 |
// Backwards compatibility.
|
36 |
if (isset($config['pool_size'])) {
|
37 |
$config['concurrency'] = $config['pool_size'];
|
38 |
} elseif (!isset($config['concurrency'])) {
|
39 |
$config['concurrency'] = 25;
|
40 |
}
|
|
|
41 |
if (isset($config['options'])) {
|
42 |
$opts = $config['options'];
|
43 |
unset($config['options']);
|
44 |
} else {
|
45 |
$opts = [];
|
46 |
}
|
47 |
-
|
48 |
-
$
|
|
|
49 |
foreach ($iterable as $key => $rfn) {
|
50 |
-
if ($rfn instanceof
|
51 |
-
|
52 |
-
} elseif (
|
53 |
-
|
54 |
} else {
|
55 |
-
throw new \InvalidArgumentException('Each value yielded by '
|
|
|
|
|
|
|
56 |
}
|
57 |
}
|
58 |
};
|
59 |
-
|
|
|
60 |
}
|
|
|
61 |
public function promise()
|
62 |
{
|
63 |
return $this->each->promise();
|
64 |
}
|
|
|
65 |
/**
|
66 |
* Sends multiple requests concurrently and returns an array of responses
|
67 |
* and exceptions that uses the same ordering as the provided requests.
|
@@ -79,25 +91,30 @@ class Pool implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromisorInterf
|
|
79 |
* in the same order that the requests were sent.
|
80 |
* @throws \InvalidArgumentException if the event format is incorrect.
|
81 |
*/
|
82 |
-
public static function batch(
|
83 |
-
|
|
|
|
|
|
|
84 |
$res = [];
|
85 |
self::cmpCallback($options, 'fulfilled', $res);
|
86 |
self::cmpCallback($options, 'rejected', $res);
|
87 |
$pool = new static($client, $requests, $options);
|
88 |
$pool->promise()->wait();
|
89 |
-
|
|
|
90 |
return $res;
|
91 |
}
|
|
|
92 |
private static function cmpCallback(array &$options, $name, array &$results)
|
93 |
{
|
94 |
if (!isset($options[$name])) {
|
95 |
-
$options[$name] = function ($v, $k) use(&$results) {
|
96 |
$results[$k] = $v;
|
97 |
};
|
98 |
} else {
|
99 |
$currentFn = $options[$name];
|
100 |
-
$options[$name] = function ($v, $k) use(&$results, $currentFn) {
|
101 |
$currentFn($v, $k);
|
102 |
$results[$k] = $v;
|
103 |
};
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Promise\PromisorInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use GuzzleHttp\Promise\EachPromise;
|
7 |
|
|
|
|
|
|
|
8 |
/**
|
9 |
* Sends and iterator of requests concurrently using a capped pool size.
|
10 |
*
|
16 |
* "request_options" array that should be merged on top of any existing
|
17 |
* options, and the function MUST then return a wait-able promise.
|
18 |
*/
|
19 |
+
class Pool implements PromisorInterface
|
20 |
{
|
21 |
/** @var EachPromise */
|
22 |
private $each;
|
23 |
+
|
24 |
/**
|
25 |
* @param ClientInterface $client Client used to send the requests.
|
26 |
* @param array|\Iterator $requests Requests or functions that return
|
31 |
* - fulfilled: (callable) Function to invoke when a request completes.
|
32 |
* - rejected: (callable) Function to invoke when a request is rejected.
|
33 |
*/
|
34 |
+
public function __construct(
|
35 |
+
ClientInterface $client,
|
36 |
+
$requests,
|
37 |
+
array $config = []
|
38 |
+
) {
|
39 |
// Backwards compatibility.
|
40 |
if (isset($config['pool_size'])) {
|
41 |
$config['concurrency'] = $config['pool_size'];
|
42 |
} elseif (!isset($config['concurrency'])) {
|
43 |
$config['concurrency'] = 25;
|
44 |
}
|
45 |
+
|
46 |
if (isset($config['options'])) {
|
47 |
$opts = $config['options'];
|
48 |
unset($config['options']);
|
49 |
} else {
|
50 |
$opts = [];
|
51 |
}
|
52 |
+
|
53 |
+
$iterable = \GuzzleHttp\Promise\iter_for($requests);
|
54 |
+
$requests = function () use ($iterable, $client, $opts) {
|
55 |
foreach ($iterable as $key => $rfn) {
|
56 |
+
if ($rfn instanceof RequestInterface) {
|
57 |
+
yield $key => $client->sendAsync($rfn, $opts);
|
58 |
+
} elseif (is_callable($rfn)) {
|
59 |
+
yield $key => $rfn($opts);
|
60 |
} else {
|
61 |
+
throw new \InvalidArgumentException('Each value yielded by '
|
62 |
+
. 'the iterator must be a Psr7\Http\Message\RequestInterface '
|
63 |
+
. 'or a callable that returns a promise that fulfills '
|
64 |
+
. 'with a Psr7\Message\Http\ResponseInterface object.');
|
65 |
}
|
66 |
}
|
67 |
};
|
68 |
+
|
69 |
+
$this->each = new EachPromise($requests(), $config);
|
70 |
}
|
71 |
+
|
72 |
public function promise()
|
73 |
{
|
74 |
return $this->each->promise();
|
75 |
}
|
76 |
+
|
77 |
/**
|
78 |
* Sends multiple requests concurrently and returns an array of responses
|
79 |
* and exceptions that uses the same ordering as the provided requests.
|
91 |
* in the same order that the requests were sent.
|
92 |
* @throws \InvalidArgumentException if the event format is incorrect.
|
93 |
*/
|
94 |
+
public static function batch(
|
95 |
+
ClientInterface $client,
|
96 |
+
$requests,
|
97 |
+
array $options = []
|
98 |
+
) {
|
99 |
$res = [];
|
100 |
self::cmpCallback($options, 'fulfilled', $res);
|
101 |
self::cmpCallback($options, 'rejected', $res);
|
102 |
$pool = new static($client, $requests, $options);
|
103 |
$pool->promise()->wait();
|
104 |
+
ksort($res);
|
105 |
+
|
106 |
return $res;
|
107 |
}
|
108 |
+
|
109 |
private static function cmpCallback(array &$options, $name, array &$results)
|
110 |
{
|
111 |
if (!isset($options[$name])) {
|
112 |
+
$options[$name] = function ($v, $k) use (&$results) {
|
113 |
$results[$k] = $v;
|
114 |
};
|
115 |
} else {
|
116 |
$currentFn = $options[$name];
|
117 |
+
$options[$name] = function ($v, $k) use (&$results, $currentFn) {
|
118 |
$currentFn($v, $k);
|
119 |
$results[$k] = $v;
|
120 |
};
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
8 |
/**
|
9 |
* Prepares requests that contain a body, adding the Content-Length,
|
10 |
* Content-Type, and Expect headers.
|
@@ -13,6 +13,7 @@ class PrepareBodyMiddleware
|
|
13 |
{
|
14 |
/** @var callable */
|
15 |
private $nextHandler;
|
|
|
16 |
/**
|
17 |
* @param callable $nextHandler Next handler to invoke.
|
18 |
*/
|
@@ -20,30 +21,37 @@ class PrepareBodyMiddleware
|
|
20 |
{
|
21 |
$this->nextHandler = $nextHandler;
|
22 |
}
|
|
|
23 |
/**
|
24 |
* @param RequestInterface $request
|
25 |
* @param array $options
|
26 |
*
|
27 |
* @return PromiseInterface
|
28 |
*/
|
29 |
-
public function __invoke(
|
30 |
{
|
31 |
$fn = $this->nextHandler;
|
|
|
32 |
// Don't do anything if the request has no body.
|
33 |
if ($request->getBody()->getSize() === 0) {
|
34 |
return $fn($request, $options);
|
35 |
}
|
|
|
36 |
$modify = [];
|
|
|
37 |
// Add a default content-type if possible.
|
38 |
if (!$request->hasHeader('Content-Type')) {
|
39 |
if ($uri = $request->getBody()->getMetadata('uri')) {
|
40 |
-
if ($type =
|
41 |
$modify['set_headers']['Content-Type'] = $type;
|
42 |
}
|
43 |
}
|
44 |
}
|
|
|
45 |
// Add a default content-length or transfer-encoding header.
|
46 |
-
if (!$request->hasHeader('Content-Length')
|
|
|
|
|
47 |
$size = $request->getBody()->getSize();
|
48 |
if ($size !== null) {
|
49 |
$modify['set_headers']['Content-Length'] = $size;
|
@@ -51,34 +59,46 @@ class PrepareBodyMiddleware
|
|
51 |
$modify['set_headers']['Transfer-Encoding'] = 'chunked';
|
52 |
}
|
53 |
}
|
|
|
54 |
// Add the expect header if needed.
|
55 |
$this->addExpectHeader($request, $options, $modify);
|
56 |
-
|
|
|
57 |
}
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
|
|
60 |
// Determine if the Expect header should be used
|
61 |
if ($request->hasHeader('Expect')) {
|
62 |
return;
|
63 |
}
|
|
|
64 |
$expect = isset($options['expect']) ? $options['expect'] : null;
|
|
|
65 |
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
|
66 |
-
if ($expect ===
|
67 |
return;
|
68 |
}
|
|
|
69 |
// The expect header is unconditionally enabled
|
70 |
-
if ($expect ===
|
71 |
$modify['set_headers']['Expect'] = '100-Continue';
|
72 |
return;
|
73 |
}
|
|
|
74 |
// By default, send the expect header when the payload is > 1mb
|
75 |
if ($expect === null) {
|
76 |
$expect = 1048576;
|
77 |
}
|
|
|
78 |
// Always add if the body cannot be rewound, the size cannot be
|
79 |
// determined, or the size is greater than the cutoff threshold
|
80 |
$body = $request->getBody();
|
81 |
$size = $body->getSize();
|
|
|
82 |
if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
|
83 |
$modify['set_headers']['Expect'] = '100-Continue';
|
84 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use GuzzleHttp\Psr7;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
|
|
|
|
|
|
|
8 |
/**
|
9 |
* Prepares requests that contain a body, adding the Content-Length,
|
10 |
* Content-Type, and Expect headers.
|
13 |
{
|
14 |
/** @var callable */
|
15 |
private $nextHandler;
|
16 |
+
|
17 |
/**
|
18 |
* @param callable $nextHandler Next handler to invoke.
|
19 |
*/
|
21 |
{
|
22 |
$this->nextHandler = $nextHandler;
|
23 |
}
|
24 |
+
|
25 |
/**
|
26 |
* @param RequestInterface $request
|
27 |
* @param array $options
|
28 |
*
|
29 |
* @return PromiseInterface
|
30 |
*/
|
31 |
+
public function __invoke(RequestInterface $request, array $options)
|
32 |
{
|
33 |
$fn = $this->nextHandler;
|
34 |
+
|
35 |
// Don't do anything if the request has no body.
|
36 |
if ($request->getBody()->getSize() === 0) {
|
37 |
return $fn($request, $options);
|
38 |
}
|
39 |
+
|
40 |
$modify = [];
|
41 |
+
|
42 |
// Add a default content-type if possible.
|
43 |
if (!$request->hasHeader('Content-Type')) {
|
44 |
if ($uri = $request->getBody()->getMetadata('uri')) {
|
45 |
+
if ($type = Psr7\mimetype_from_filename($uri)) {
|
46 |
$modify['set_headers']['Content-Type'] = $type;
|
47 |
}
|
48 |
}
|
49 |
}
|
50 |
+
|
51 |
// Add a default content-length or transfer-encoding header.
|
52 |
+
if (!$request->hasHeader('Content-Length')
|
53 |
+
&& !$request->hasHeader('Transfer-Encoding')
|
54 |
+
) {
|
55 |
$size = $request->getBody()->getSize();
|
56 |
if ($size !== null) {
|
57 |
$modify['set_headers']['Content-Length'] = $size;
|
59 |
$modify['set_headers']['Transfer-Encoding'] = 'chunked';
|
60 |
}
|
61 |
}
|
62 |
+
|
63 |
// Add the expect header if needed.
|
64 |
$this->addExpectHeader($request, $options, $modify);
|
65 |
+
|
66 |
+
return $fn(Psr7\modify_request($request, $modify), $options);
|
67 |
}
|
68 |
+
|
69 |
+
private function addExpectHeader(
|
70 |
+
RequestInterface $request,
|
71 |
+
array $options,
|
72 |
+
array &$modify
|
73 |
+
) {
|
74 |
// Determine if the Expect header should be used
|
75 |
if ($request->hasHeader('Expect')) {
|
76 |
return;
|
77 |
}
|
78 |
+
|
79 |
$expect = isset($options['expect']) ? $options['expect'] : null;
|
80 |
+
|
81 |
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
|
82 |
+
if ($expect === false || $request->getProtocolVersion() < 1.1) {
|
83 |
return;
|
84 |
}
|
85 |
+
|
86 |
// The expect header is unconditionally enabled
|
87 |
+
if ($expect === true) {
|
88 |
$modify['set_headers']['Expect'] = '100-Continue';
|
89 |
return;
|
90 |
}
|
91 |
+
|
92 |
// By default, send the expect header when the payload is > 1mb
|
93 |
if ($expect === null) {
|
94 |
$expect = 1048576;
|
95 |
}
|
96 |
+
|
97 |
// Always add if the body cannot be rewound, the size cannot be
|
98 |
// determined, or the size is greater than the cutoff threshold
|
99 |
$body = $request->getBody();
|
100 |
$size = $body->getSize();
|
101 |
+
|
102 |
if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
|
103 |
$modify['set_headers']['Expect'] = '100-Continue';
|
104 |
}
|
@@ -1,14 +1,14 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\BadResponseException;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Exception\TooManyRedirectsException;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
10 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
11 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
12 |
/**
|
13 |
* Request redirect middleware.
|
14 |
*
|
@@ -18,10 +18,20 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
|
18 |
class RedirectMiddleware
|
19 |
{
|
20 |
const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
|
|
21 |
const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
/** @var callable */
|
24 |
private $nextHandler;
|
|
|
25 |
/**
|
26 |
* @param callable $nextHandler Next handler to invoke.
|
27 |
*/
|
@@ -29,33 +39,40 @@ class RedirectMiddleware
|
|
29 |
{
|
30 |
$this->nextHandler = $nextHandler;
|
31 |
}
|
|
|
32 |
/**
|
33 |
* @param RequestInterface $request
|
34 |
* @param array $options
|
35 |
*
|
36 |
* @return PromiseInterface
|
37 |
*/
|
38 |
-
public function __invoke(
|
39 |
{
|
40 |
$fn = $this->nextHandler;
|
|
|
41 |
if (empty($options['allow_redirects'])) {
|
42 |
return $fn($request, $options);
|
43 |
}
|
44 |
-
|
|
|
45 |
$options['allow_redirects'] = self::$defaultSettings;
|
46 |
-
} elseif (
|
47 |
throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
|
48 |
} else {
|
49 |
// Merge the default settings with the provided settings
|
50 |
$options['allow_redirects'] += self::$defaultSettings;
|
51 |
}
|
|
|
52 |
if (empty($options['allow_redirects']['max'])) {
|
53 |
return $fn($request, $options);
|
54 |
}
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
58 |
}
|
|
|
59 |
/**
|
60 |
* @param RequestInterface $request
|
61 |
* @param array $options
|
@@ -63,46 +80,77 @@ class RedirectMiddleware
|
|
63 |
*
|
64 |
* @return ResponseInterface|PromiseInterface
|
65 |
*/
|
66 |
-
public function checkRedirect(
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
69 |
return $response;
|
70 |
}
|
|
|
71 |
$this->guardMax($request, $options);
|
72 |
$nextRequest = $this->modifyRequest($request, $options, $response);
|
|
|
73 |
if (isset($options['allow_redirects']['on_redirect'])) {
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
|
|
76 |
/** @var PromiseInterface|ResponseInterface $promise */
|
77 |
$promise = $this($nextRequest, $options);
|
|
|
78 |
// Add headers to be able to track history of redirects.
|
79 |
if (!empty($options['allow_redirects']['track_redirects'])) {
|
80 |
-
return $this->withTracking(
|
|
|
|
|
|
|
|
|
81 |
}
|
|
|
82 |
return $promise;
|
83 |
}
|
84 |
-
|
|
|
85 |
{
|
86 |
-
return $promise->then(
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
96 |
}
|
97 |
-
|
|
|
98 |
{
|
99 |
-
$current = isset($options['__redirect_count'])
|
|
|
|
|
100 |
$options['__redirect_count'] = $current + 1;
|
101 |
$max = $options['allow_redirects']['max'];
|
|
|
102 |
if ($options['__redirect_count'] > $max) {
|
103 |
-
throw new
|
|
|
|
|
|
|
104 |
}
|
105 |
}
|
|
|
106 |
/**
|
107 |
* @param RequestInterface $request
|
108 |
* @param array $options
|
@@ -110,35 +158,48 @@ class RedirectMiddleware
|
|
110 |
*
|
111 |
* @return RequestInterface
|
112 |
*/
|
113 |
-
public function modifyRequest(
|
114 |
-
|
|
|
|
|
|
|
115 |
// Request modifications to apply.
|
116 |
$modify = [];
|
117 |
$protocols = $options['allow_redirects']['protocols'];
|
|
|
118 |
// Use a GET request if this is an entity enclosing request and we are
|
119 |
// not forcing RFC compliance, but rather emulating what all browsers
|
120 |
// would do.
|
121 |
$statusCode = $response->getStatusCode();
|
122 |
-
if ($statusCode == 303 ||
|
|
|
|
|
123 |
$modify['method'] = 'GET';
|
124 |
$modify['body'] = '';
|
125 |
}
|
|
|
126 |
$modify['uri'] = $this->redirectUri($request, $response, $protocols);
|
127 |
-
|
|
|
128 |
// Add the Referer header if it is told to do so and only
|
129 |
// add the header if we are not redirecting from https to http.
|
130 |
-
if ($options['allow_redirects']['referer']
|
|
|
|
|
131 |
$uri = $request->getUri()->withUserInfo('', '');
|
132 |
$modify['set_headers']['Referer'] = (string) $uri;
|
133 |
} else {
|
134 |
$modify['remove_headers'][] = 'Referer';
|
135 |
}
|
|
|
136 |
// Remove Authorization header if host is different.
|
137 |
if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
|
138 |
$modify['remove_headers'][] = 'Authorization';
|
139 |
}
|
140 |
-
|
|
|
141 |
}
|
|
|
142 |
/**
|
143 |
* Set the appropriate URL on the request based on the location header
|
144 |
*
|
@@ -148,13 +209,29 @@ class RedirectMiddleware
|
|
148 |
*
|
149 |
* @return UriInterface
|
150 |
*/
|
151 |
-
private function redirectUri(
|
152 |
-
|
153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
// Ensure that the redirect URI is allowed based on the protocols.
|
155 |
-
if (
|
156 |
-
throw new
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
}
|
|
|
158 |
return $location;
|
159 |
}
|
160 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Exception\BadResponseException;
|
5 |
+
use GuzzleHttp\Exception\TooManyRedirectsException;
|
6 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
use Psr\Http\Message\RequestInterface;
|
9 |
+
use Psr\Http\Message\ResponseInterface;
|
10 |
+
use Psr\Http\Message\UriInterface;
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Request redirect middleware.
|
14 |
*
|
18 |
class RedirectMiddleware
|
19 |
{
|
20 |
const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
21 |
+
|
22 |
const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
23 |
+
|
24 |
+
public static $defaultSettings = [
|
25 |
+
'max' => 5,
|
26 |
+
'protocols' => ['http', 'https'],
|
27 |
+
'strict' => false,
|
28 |
+
'referer' => false,
|
29 |
+
'track_redirects' => false,
|
30 |
+
];
|
31 |
+
|
32 |
/** @var callable */
|
33 |
private $nextHandler;
|
34 |
+
|
35 |
/**
|
36 |
* @param callable $nextHandler Next handler to invoke.
|
37 |
*/
|
39 |
{
|
40 |
$this->nextHandler = $nextHandler;
|
41 |
}
|
42 |
+
|
43 |
/**
|
44 |
* @param RequestInterface $request
|
45 |
* @param array $options
|
46 |
*
|
47 |
* @return PromiseInterface
|
48 |
*/
|
49 |
+
public function __invoke(RequestInterface $request, array $options)
|
50 |
{
|
51 |
$fn = $this->nextHandler;
|
52 |
+
|
53 |
if (empty($options['allow_redirects'])) {
|
54 |
return $fn($request, $options);
|
55 |
}
|
56 |
+
|
57 |
+
if ($options['allow_redirects'] === true) {
|
58 |
$options['allow_redirects'] = self::$defaultSettings;
|
59 |
+
} elseif (!is_array($options['allow_redirects'])) {
|
60 |
throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
|
61 |
} else {
|
62 |
// Merge the default settings with the provided settings
|
63 |
$options['allow_redirects'] += self::$defaultSettings;
|
64 |
}
|
65 |
+
|
66 |
if (empty($options['allow_redirects']['max'])) {
|
67 |
return $fn($request, $options);
|
68 |
}
|
69 |
+
|
70 |
+
return $fn($request, $options)
|
71 |
+
->then(function (ResponseInterface $response) use ($request, $options) {
|
72 |
+
return $this->checkRedirect($request, $options, $response);
|
73 |
+
});
|
74 |
}
|
75 |
+
|
76 |
/**
|
77 |
* @param RequestInterface $request
|
78 |
* @param array $options
|
80 |
*
|
81 |
* @return ResponseInterface|PromiseInterface
|
82 |
*/
|
83 |
+
public function checkRedirect(
|
84 |
+
RequestInterface $request,
|
85 |
+
array $options,
|
86 |
+
ResponseInterface $response
|
87 |
+
) {
|
88 |
+
if (substr($response->getStatusCode(), 0, 1) != '3'
|
89 |
+
|| !$response->hasHeader('Location')
|
90 |
+
) {
|
91 |
return $response;
|
92 |
}
|
93 |
+
|
94 |
$this->guardMax($request, $options);
|
95 |
$nextRequest = $this->modifyRequest($request, $options, $response);
|
96 |
+
|
97 |
if (isset($options['allow_redirects']['on_redirect'])) {
|
98 |
+
call_user_func(
|
99 |
+
$options['allow_redirects']['on_redirect'],
|
100 |
+
$request,
|
101 |
+
$response,
|
102 |
+
$nextRequest->getUri()
|
103 |
+
);
|
104 |
}
|
105 |
+
|
106 |
/** @var PromiseInterface|ResponseInterface $promise */
|
107 |
$promise = $this($nextRequest, $options);
|
108 |
+
|
109 |
// Add headers to be able to track history of redirects.
|
110 |
if (!empty($options['allow_redirects']['track_redirects'])) {
|
111 |
+
return $this->withTracking(
|
112 |
+
$promise,
|
113 |
+
(string) $nextRequest->getUri(),
|
114 |
+
$response->getStatusCode()
|
115 |
+
);
|
116 |
}
|
117 |
+
|
118 |
return $promise;
|
119 |
}
|
120 |
+
|
121 |
+
private function withTracking(PromiseInterface $promise, $uri, $statusCode)
|
122 |
{
|
123 |
+
return $promise->then(
|
124 |
+
function (ResponseInterface $response) use ($uri, $statusCode) {
|
125 |
+
// Note that we are pushing to the front of the list as this
|
126 |
+
// would be an earlier response than what is currently present
|
127 |
+
// in the history header.
|
128 |
+
$historyHeader = $response->getHeader(self::HISTORY_HEADER);
|
129 |
+
$statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
|
130 |
+
array_unshift($historyHeader, $uri);
|
131 |
+
array_unshift($statusHeader, $statusCode);
|
132 |
+
return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
|
133 |
+
->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
|
134 |
+
}
|
135 |
+
);
|
136 |
}
|
137 |
+
|
138 |
+
private function guardMax(RequestInterface $request, array &$options)
|
139 |
{
|
140 |
+
$current = isset($options['__redirect_count'])
|
141 |
+
? $options['__redirect_count']
|
142 |
+
: 0;
|
143 |
$options['__redirect_count'] = $current + 1;
|
144 |
$max = $options['allow_redirects']['max'];
|
145 |
+
|
146 |
if ($options['__redirect_count'] > $max) {
|
147 |
+
throw new TooManyRedirectsException(
|
148 |
+
"Will not follow more than {$max} redirects",
|
149 |
+
$request
|
150 |
+
);
|
151 |
}
|
152 |
}
|
153 |
+
|
154 |
/**
|
155 |
* @param RequestInterface $request
|
156 |
* @param array $options
|
158 |
*
|
159 |
* @return RequestInterface
|
160 |
*/
|
161 |
+
public function modifyRequest(
|
162 |
+
RequestInterface $request,
|
163 |
+
array $options,
|
164 |
+
ResponseInterface $response
|
165 |
+
) {
|
166 |
// Request modifications to apply.
|
167 |
$modify = [];
|
168 |
$protocols = $options['allow_redirects']['protocols'];
|
169 |
+
|
170 |
// Use a GET request if this is an entity enclosing request and we are
|
171 |
// not forcing RFC compliance, but rather emulating what all browsers
|
172 |
// would do.
|
173 |
$statusCode = $response->getStatusCode();
|
174 |
+
if ($statusCode == 303 ||
|
175 |
+
($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict'])
|
176 |
+
) {
|
177 |
$modify['method'] = 'GET';
|
178 |
$modify['body'] = '';
|
179 |
}
|
180 |
+
|
181 |
$modify['uri'] = $this->redirectUri($request, $response, $protocols);
|
182 |
+
Psr7\rewind_body($request);
|
183 |
+
|
184 |
// Add the Referer header if it is told to do so and only
|
185 |
// add the header if we are not redirecting from https to http.
|
186 |
+
if ($options['allow_redirects']['referer']
|
187 |
+
&& $modify['uri']->getScheme() === $request->getUri()->getScheme()
|
188 |
+
) {
|
189 |
$uri = $request->getUri()->withUserInfo('', '');
|
190 |
$modify['set_headers']['Referer'] = (string) $uri;
|
191 |
} else {
|
192 |
$modify['remove_headers'][] = 'Referer';
|
193 |
}
|
194 |
+
|
195 |
// Remove Authorization header if host is different.
|
196 |
if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
|
197 |
$modify['remove_headers'][] = 'Authorization';
|
198 |
}
|
199 |
+
|
200 |
+
return Psr7\modify_request($request, $modify);
|
201 |
}
|
202 |
+
|
203 |
/**
|
204 |
* Set the appropriate URL on the request based on the location header
|
205 |
*
|
209 |
*
|
210 |
* @return UriInterface
|
211 |
*/
|
212 |
+
private function redirectUri(
|
213 |
+
RequestInterface $request,
|
214 |
+
ResponseInterface $response,
|
215 |
+
array $protocols
|
216 |
+
) {
|
217 |
+
$location = Psr7\UriResolver::resolve(
|
218 |
+
$request->getUri(),
|
219 |
+
new Psr7\Uri($response->getHeaderLine('Location'))
|
220 |
+
);
|
221 |
+
|
222 |
// Ensure that the redirect URI is allowed based on the protocols.
|
223 |
+
if (!in_array($location->getScheme(), $protocols)) {
|
224 |
+
throw new BadResponseException(
|
225 |
+
sprintf(
|
226 |
+
'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
|
227 |
+
$location,
|
228 |
+
implode(', ', $protocols)
|
229 |
+
),
|
230 |
+
$request,
|
231 |
+
$response
|
232 |
+
);
|
233 |
}
|
234 |
+
|
235 |
return $location;
|
236 |
}
|
237 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp;
|
4 |
|
5 |
/**
|
6 |
* This class contains a list of built-in Guzzle request options.
|
@@ -33,6 +32,7 @@ final class RequestOptions
|
|
33 |
* from the on_redirect function is ignored.
|
34 |
*/
|
35 |
const ALLOW_REDIRECTS = 'allow_redirects';
|
|
|
36 |
/**
|
37 |
* auth: (array) Pass an array of HTTP authentication parameters to use
|
38 |
* with the request. The array must contain the username in index [0],
|
@@ -41,11 +41,13 @@ final class RequestOptions
|
|
41 |
* for a request.
|
42 |
*/
|
43 |
const AUTH = 'auth';
|
|
|
44 |
/**
|
45 |
* body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
|
46 |
* Body to send in the request.
|
47 |
*/
|
48 |
const BODY = 'body';
|
|
|
49 |
/**
|
50 |
* cert: (string|array) Set to a string to specify the path to a file
|
51 |
* containing a PEM formatted SSL client side certificate. If a password
|
@@ -54,6 +56,7 @@ final class RequestOptions
|
|
54 |
* in the second array element.
|
55 |
*/
|
56 |
const CERT = 'cert';
|
|
|
57 |
/**
|
58 |
* cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
|
59 |
* Specifies whether or not cookies are used in a request or what cookie
|
@@ -62,28 +65,33 @@ final class RequestOptions
|
|
62 |
* an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
|
63 |
*/
|
64 |
const COOKIES = 'cookies';
|
|
|
65 |
/**
|
66 |
* connect_timeout: (float, default=0) Float describing the number of
|
67 |
* seconds to wait while trying to connect to a server. Use 0 to wait
|
68 |
* indefinitely (the default behavior).
|
69 |
*/
|
70 |
const CONNECT_TIMEOUT = 'connect_timeout';
|
|
|
71 |
/**
|
72 |
* debug: (bool|resource) Set to true or set to a PHP stream returned by
|
73 |
* fopen() enable debug output with the HTTP handler used to send a
|
74 |
* request.
|
75 |
*/
|
76 |
const DEBUG = 'debug';
|
|
|
77 |
/**
|
78 |
* decode_content: (bool, default=true) Specify whether or not
|
79 |
* Content-Encoding responses (gzip, deflate, etc.) are automatically
|
80 |
* decoded.
|
81 |
*/
|
82 |
const DECODE_CONTENT = 'decode_content';
|
|
|
83 |
/**
|
84 |
* delay: (int) The amount of time to delay before sending in milliseconds.
|
85 |
*/
|
86 |
const DELAY = 'delay';
|
|
|
87 |
/**
|
88 |
* expect: (bool|integer) Controls the behavior of the
|
89 |
* "Expect: 100-Continue" header.
|
@@ -101,6 +109,7 @@ final class RequestOptions
|
|
101 |
* using HTTP/1.1.
|
102 |
*/
|
103 |
const EXPECT = 'expect';
|
|
|
104 |
/**
|
105 |
* form_params: (array) Associative array of form field names to values
|
106 |
* where each value is a string or array of strings. Sets the Content-Type
|
@@ -108,11 +117,13 @@ final class RequestOptions
|
|
108 |
* is already present.
|
109 |
*/
|
110 |
const FORM_PARAMS = 'form_params';
|
|
|
111 |
/**
|
112 |
* headers: (array) Associative array of HTTP headers. Each value MUST be
|
113 |
* a string or array of strings.
|
114 |
*/
|
115 |
const HEADERS = 'headers';
|
|
|
116 |
/**
|
117 |
* http_errors: (bool, default=true) Set to false to disable exceptions
|
118 |
* when a non- successful HTTP response is received. By default,
|
@@ -120,12 +131,14 @@ final class RequestOptions
|
|
120 |
* works if your handler has the `httpErrors` middleware.
|
121 |
*/
|
122 |
const HTTP_ERRORS = 'http_errors';
|
|
|
123 |
/**
|
124 |
* json: (mixed) Adds JSON data to a request. The provided value is JSON
|
125 |
* encoded and a Content-Type header of application/json will be added to
|
126 |
* the request if no Content-Type header is already present.
|
127 |
*/
|
128 |
const JSON = 'json';
|
|
|
129 |
/**
|
130 |
* multipart: (array) Array of associative arrays, each containing a
|
131 |
* required "name" key mapping to the form field, name, a required
|
@@ -136,12 +149,14 @@ final class RequestOptions
|
|
136 |
* will be added to the part.
|
137 |
*/
|
138 |
const MULTIPART = 'multipart';
|
|
|
139 |
/**
|
140 |
* on_headers: (callable) A callable that is invoked when the HTTP headers
|
141 |
* of the response have been received but the body has not yet begun to
|
142 |
* download.
|
143 |
*/
|
144 |
const ON_HEADERS = 'on_headers';
|
|
|
145 |
/**
|
146 |
* on_stats: (callable) allows you to get access to transfer statistics of
|
147 |
* a request and access the lower level transfer details of the handler
|
@@ -152,6 +167,7 @@ final class RequestOptions
|
|
152 |
* taken to send the request.
|
153 |
*/
|
154 |
const ON_STATS = 'on_stats';
|
|
|
155 |
/**
|
156 |
* progress: (callable) Defines a function to invoke when transfer
|
157 |
* progress is made. The function accepts the following positional
|
@@ -160,12 +176,14 @@ final class RequestOptions
|
|
160 |
* uploaded, the number of bytes uploaded so far.
|
161 |
*/
|
162 |
const PROGRESS = 'progress';
|
|
|
163 |
/**
|
164 |
* proxy: (string|array) Pass a string to specify an HTTP proxy, or an
|
165 |
* array to specify different proxies for different protocols (where the
|
166 |
* key is the protocol and the value is a proxy string).
|
167 |
*/
|
168 |
const PROXY = 'proxy';
|
|
|
169 |
/**
|
170 |
* query: (array|string) Associative array of query string values to add
|
171 |
* to the request. This option uses PHP's http_build_query() to create
|
@@ -173,12 +191,14 @@ final class RequestOptions
|
|
173 |
* control than what this method provides
|
174 |
*/
|
175 |
const QUERY = 'query';
|
|
|
176 |
/**
|
177 |
* sink: (resource|string|StreamInterface) Where the data of the
|
178 |
* response is written to. Defaults to a PHP temp stream. Providing a
|
179 |
* string will write data to a file by the given name.
|
180 |
*/
|
181 |
const SINK = 'sink';
|
|
|
182 |
/**
|
183 |
* synchronous: (bool) Set to true to inform HTTP handlers that you intend
|
184 |
* on waiting on the response. This can be useful for optimizations. Note
|
@@ -186,6 +206,7 @@ final class RequestOptions
|
|
186 |
* client methods.
|
187 |
*/
|
188 |
const SYNCHRONOUS = 'synchronous';
|
|
|
189 |
/**
|
190 |
* ssl_key: (array|string) Specify the path to a file containing a private
|
191 |
* SSL key in PEM format. If a password is required, then set to an array
|
@@ -193,11 +214,13 @@ final class RequestOptions
|
|
193 |
* by the password required for the certificate in the second element.
|
194 |
*/
|
195 |
const SSL_KEY = 'ssl_key';
|
|
|
196 |
/**
|
197 |
* stream: Set to true to attempt to stream a response rather than
|
198 |
* download it all up-front.
|
199 |
*/
|
200 |
const STREAM = 'stream';
|
|
|
201 |
/**
|
202 |
* verify: (bool|string, default=true) Describes the SSL certificate
|
203 |
* verification behavior of a request. Set to true to enable SSL
|
@@ -207,20 +230,24 @@ final class RequestOptions
|
|
207 |
* disk to enable verification using a custom certificate.
|
208 |
*/
|
209 |
const VERIFY = 'verify';
|
|
|
210 |
/**
|
211 |
* timeout: (float, default=0) Float describing the timeout of the
|
212 |
* request in seconds. Use 0 to wait indefinitely (the default behavior).
|
213 |
*/
|
214 |
const TIMEOUT = 'timeout';
|
|
|
215 |
/**
|
216 |
* read_timeout: (float, default=default_socket_timeout ini setting) Float describing
|
217 |
* the body read timeout, for stream requests.
|
218 |
*/
|
219 |
const READ_TIMEOUT = 'read_timeout';
|
|
|
220 |
/**
|
221 |
* version: (float) Specifies the HTTP protocol version to attempt to use.
|
222 |
*/
|
223 |
const VERSION = 'version';
|
|
|
224 |
/**
|
225 |
* force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
|
226 |
*/
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
|
|
3 |
|
4 |
/**
|
5 |
* This class contains a list of built-in Guzzle request options.
|
32 |
* from the on_redirect function is ignored.
|
33 |
*/
|
34 |
const ALLOW_REDIRECTS = 'allow_redirects';
|
35 |
+
|
36 |
/**
|
37 |
* auth: (array) Pass an array of HTTP authentication parameters to use
|
38 |
* with the request. The array must contain the username in index [0],
|
41 |
* for a request.
|
42 |
*/
|
43 |
const AUTH = 'auth';
|
44 |
+
|
45 |
/**
|
46 |
* body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
|
47 |
* Body to send in the request.
|
48 |
*/
|
49 |
const BODY = 'body';
|
50 |
+
|
51 |
/**
|
52 |
* cert: (string|array) Set to a string to specify the path to a file
|
53 |
* containing a PEM formatted SSL client side certificate. If a password
|
56 |
* in the second array element.
|
57 |
*/
|
58 |
const CERT = 'cert';
|
59 |
+
|
60 |
/**
|
61 |
* cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
|
62 |
* Specifies whether or not cookies are used in a request or what cookie
|
65 |
* an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
|
66 |
*/
|
67 |
const COOKIES = 'cookies';
|
68 |
+
|
69 |
/**
|
70 |
* connect_timeout: (float, default=0) Float describing the number of
|
71 |
* seconds to wait while trying to connect to a server. Use 0 to wait
|
72 |
* indefinitely (the default behavior).
|
73 |
*/
|
74 |
const CONNECT_TIMEOUT = 'connect_timeout';
|
75 |
+
|
76 |
/**
|
77 |
* debug: (bool|resource) Set to true or set to a PHP stream returned by
|
78 |
* fopen() enable debug output with the HTTP handler used to send a
|
79 |
* request.
|
80 |
*/
|
81 |
const DEBUG = 'debug';
|
82 |
+
|
83 |
/**
|
84 |
* decode_content: (bool, default=true) Specify whether or not
|
85 |
* Content-Encoding responses (gzip, deflate, etc.) are automatically
|
86 |
* decoded.
|
87 |
*/
|
88 |
const DECODE_CONTENT = 'decode_content';
|
89 |
+
|
90 |
/**
|
91 |
* delay: (int) The amount of time to delay before sending in milliseconds.
|
92 |
*/
|
93 |
const DELAY = 'delay';
|
94 |
+
|
95 |
/**
|
96 |
* expect: (bool|integer) Controls the behavior of the
|
97 |
* "Expect: 100-Continue" header.
|
109 |
* using HTTP/1.1.
|
110 |
*/
|
111 |
const EXPECT = 'expect';
|
112 |
+
|
113 |
/**
|
114 |
* form_params: (array) Associative array of form field names to values
|
115 |
* where each value is a string or array of strings. Sets the Content-Type
|
117 |
* is already present.
|
118 |
*/
|
119 |
const FORM_PARAMS = 'form_params';
|
120 |
+
|
121 |
/**
|
122 |
* headers: (array) Associative array of HTTP headers. Each value MUST be
|
123 |
* a string or array of strings.
|
124 |
*/
|
125 |
const HEADERS = 'headers';
|
126 |
+
|
127 |
/**
|
128 |
* http_errors: (bool, default=true) Set to false to disable exceptions
|
129 |
* when a non- successful HTTP response is received. By default,
|
131 |
* works if your handler has the `httpErrors` middleware.
|
132 |
*/
|
133 |
const HTTP_ERRORS = 'http_errors';
|
134 |
+
|
135 |
/**
|
136 |
* json: (mixed) Adds JSON data to a request. The provided value is JSON
|
137 |
* encoded and a Content-Type header of application/json will be added to
|
138 |
* the request if no Content-Type header is already present.
|
139 |
*/
|
140 |
const JSON = 'json';
|
141 |
+
|
142 |
/**
|
143 |
* multipart: (array) Array of associative arrays, each containing a
|
144 |
* required "name" key mapping to the form field, name, a required
|
149 |
* will be added to the part.
|
150 |
*/
|
151 |
const MULTIPART = 'multipart';
|
152 |
+
|
153 |
/**
|
154 |
* on_headers: (callable) A callable that is invoked when the HTTP headers
|
155 |
* of the response have been received but the body has not yet begun to
|
156 |
* download.
|
157 |
*/
|
158 |
const ON_HEADERS = 'on_headers';
|
159 |
+
|
160 |
/**
|
161 |
* on_stats: (callable) allows you to get access to transfer statistics of
|
162 |
* a request and access the lower level transfer details of the handler
|
167 |
* taken to send the request.
|
168 |
*/
|
169 |
const ON_STATS = 'on_stats';
|
170 |
+
|
171 |
/**
|
172 |
* progress: (callable) Defines a function to invoke when transfer
|
173 |
* progress is made. The function accepts the following positional
|
176 |
* uploaded, the number of bytes uploaded so far.
|
177 |
*/
|
178 |
const PROGRESS = 'progress';
|
179 |
+
|
180 |
/**
|
181 |
* proxy: (string|array) Pass a string to specify an HTTP proxy, or an
|
182 |
* array to specify different proxies for different protocols (where the
|
183 |
* key is the protocol and the value is a proxy string).
|
184 |
*/
|
185 |
const PROXY = 'proxy';
|
186 |
+
|
187 |
/**
|
188 |
* query: (array|string) Associative array of query string values to add
|
189 |
* to the request. This option uses PHP's http_build_query() to create
|
191 |
* control than what this method provides
|
192 |
*/
|
193 |
const QUERY = 'query';
|
194 |
+
|
195 |
/**
|
196 |
* sink: (resource|string|StreamInterface) Where the data of the
|
197 |
* response is written to. Defaults to a PHP temp stream. Providing a
|
198 |
* string will write data to a file by the given name.
|
199 |
*/
|
200 |
const SINK = 'sink';
|
201 |
+
|
202 |
/**
|
203 |
* synchronous: (bool) Set to true to inform HTTP handlers that you intend
|
204 |
* on waiting on the response. This can be useful for optimizations. Note
|
206 |
* client methods.
|
207 |
*/
|
208 |
const SYNCHRONOUS = 'synchronous';
|
209 |
+
|
210 |
/**
|
211 |
* ssl_key: (array|string) Specify the path to a file containing a private
|
212 |
* SSL key in PEM format. If a password is required, then set to an array
|
214 |
* by the password required for the certificate in the second element.
|
215 |
*/
|
216 |
const SSL_KEY = 'ssl_key';
|
217 |
+
|
218 |
/**
|
219 |
* stream: Set to true to attempt to stream a response rather than
|
220 |
* download it all up-front.
|
221 |
*/
|
222 |
const STREAM = 'stream';
|
223 |
+
|
224 |
/**
|
225 |
* verify: (bool|string, default=true) Describes the SSL certificate
|
226 |
* verification behavior of a request. Set to true to enable SSL
|
230 |
* disk to enable verification using a custom certificate.
|
231 |
*/
|
232 |
const VERIFY = 'verify';
|
233 |
+
|
234 |
/**
|
235 |
* timeout: (float, default=0) Float describing the timeout of the
|
236 |
* request in seconds. Use 0 to wait indefinitely (the default behavior).
|
237 |
*/
|
238 |
const TIMEOUT = 'timeout';
|
239 |
+
|
240 |
/**
|
241 |
* read_timeout: (float, default=default_socket_timeout ini setting) Float describing
|
242 |
* the body read timeout, for stream requests.
|
243 |
*/
|
244 |
const READ_TIMEOUT = 'read_timeout';
|
245 |
+
|
246 |
/**
|
247 |
* version: (float) Specifies the HTTP protocol version to attempt to use.
|
248 |
*/
|
249 |
const VERSION = 'version';
|
250 |
+
|
251 |
/**
|
252 |
* force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
|
253 |
*/
|
@@ -1,12 +1,12 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\RejectedPromise;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
10 |
/**
|
11 |
* Middleware that retries requests based on the boolean result of
|
12 |
* invoking the provided "decider" function.
|
@@ -15,8 +15,10 @@ class RetryMiddleware
|
|
15 |
{
|
16 |
/** @var callable */
|
17 |
private $nextHandler;
|
|
|
18 |
/** @var callable */
|
19 |
private $decider;
|
|
|
20 |
/**
|
21 |
* @param callable $decider Function that accepts the number of retries,
|
22 |
* a request, [response], and [exception] and
|
@@ -27,12 +29,16 @@ class RetryMiddleware
|
|
27 |
* and [response] and returns the number of
|
28 |
* milliseconds to delay.
|
29 |
*/
|
30 |
-
public function __construct(
|
31 |
-
|
|
|
|
|
|
|
32 |
$this->decider = $decider;
|
33 |
$this->nextHandler = $nextHandler;
|
34 |
$this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
|
35 |
}
|
|
|
36 |
/**
|
37 |
* Default exponential backoff delay function.
|
38 |
*
|
@@ -42,43 +48,65 @@ class RetryMiddleware
|
|
42 |
*/
|
43 |
public static function exponentialDelay($retries)
|
44 |
{
|
45 |
-
return (int)
|
46 |
}
|
|
|
47 |
/**
|
48 |
* @param RequestInterface $request
|
49 |
* @param array $options
|
50 |
*
|
51 |
* @return PromiseInterface
|
52 |
*/
|
53 |
-
public function __invoke(
|
54 |
{
|
55 |
if (!isset($options['retries'])) {
|
56 |
$options['retries'] = 0;
|
57 |
}
|
|
|
58 |
$fn = $this->nextHandler;
|
59 |
-
return $fn($request, $options)
|
|
|
|
|
|
|
|
|
60 |
}
|
61 |
-
|
|
|
62 |
{
|
63 |
-
return function ($value) use($req, $options) {
|
64 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
return $value;
|
66 |
}
|
67 |
return $this->doRetry($req, $options, $value);
|
68 |
};
|
69 |
}
|
70 |
-
|
|
|
71 |
{
|
72 |
-
return function ($reason) use($req, $options) {
|
73 |
-
if (
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
76 |
return $this->doRetry($req, $options);
|
77 |
};
|
78 |
}
|
79 |
-
|
|
|
80 |
{
|
81 |
-
$options['delay'] =
|
|
|
82 |
return $this($request, $options);
|
83 |
}
|
84 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
use Psr\Http\Message\ResponseInterface;
|
9 |
|
|
|
|
|
|
|
|
|
|
|
10 |
/**
|
11 |
* Middleware that retries requests based on the boolean result of
|
12 |
* invoking the provided "decider" function.
|
15 |
{
|
16 |
/** @var callable */
|
17 |
private $nextHandler;
|
18 |
+
|
19 |
/** @var callable */
|
20 |
private $decider;
|
21 |
+
|
22 |
/**
|
23 |
* @param callable $decider Function that accepts the number of retries,
|
24 |
* a request, [response], and [exception] and
|
29 |
* and [response] and returns the number of
|
30 |
* milliseconds to delay.
|
31 |
*/
|
32 |
+
public function __construct(
|
33 |
+
callable $decider,
|
34 |
+
callable $nextHandler,
|
35 |
+
callable $delay = null
|
36 |
+
) {
|
37 |
$this->decider = $decider;
|
38 |
$this->nextHandler = $nextHandler;
|
39 |
$this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
|
40 |
}
|
41 |
+
|
42 |
/**
|
43 |
* Default exponential backoff delay function.
|
44 |
*
|
48 |
*/
|
49 |
public static function exponentialDelay($retries)
|
50 |
{
|
51 |
+
return (int) pow(2, $retries - 1);
|
52 |
}
|
53 |
+
|
54 |
/**
|
55 |
* @param RequestInterface $request
|
56 |
* @param array $options
|
57 |
*
|
58 |
* @return PromiseInterface
|
59 |
*/
|
60 |
+
public function __invoke(RequestInterface $request, array $options)
|
61 |
{
|
62 |
if (!isset($options['retries'])) {
|
63 |
$options['retries'] = 0;
|
64 |
}
|
65 |
+
|
66 |
$fn = $this->nextHandler;
|
67 |
+
return $fn($request, $options)
|
68 |
+
->then(
|
69 |
+
$this->onFulfilled($request, $options),
|
70 |
+
$this->onRejected($request, $options)
|
71 |
+
);
|
72 |
}
|
73 |
+
|
74 |
+
private function onFulfilled(RequestInterface $req, array $options)
|
75 |
{
|
76 |
+
return function ($value) use ($req, $options) {
|
77 |
+
if (!call_user_func(
|
78 |
+
$this->decider,
|
79 |
+
$options['retries'],
|
80 |
+
$req,
|
81 |
+
$value,
|
82 |
+
null
|
83 |
+
)) {
|
84 |
return $value;
|
85 |
}
|
86 |
return $this->doRetry($req, $options, $value);
|
87 |
};
|
88 |
}
|
89 |
+
|
90 |
+
private function onRejected(RequestInterface $req, array $options)
|
91 |
{
|
92 |
+
return function ($reason) use ($req, $options) {
|
93 |
+
if (!call_user_func(
|
94 |
+
$this->decider,
|
95 |
+
$options['retries'],
|
96 |
+
$req,
|
97 |
+
null,
|
98 |
+
$reason
|
99 |
+
)) {
|
100 |
+
return \GuzzleHttp\Promise\rejection_for($reason);
|
101 |
}
|
102 |
return $this->doRetry($req, $options);
|
103 |
};
|
104 |
}
|
105 |
+
|
106 |
+
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
|
107 |
{
|
108 |
+
$options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
|
109 |
+
|
110 |
return $this($request, $options);
|
111 |
}
|
112 |
}
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
8 |
/**
|
9 |
* Represents data at the point after it was transferred either successfully
|
10 |
* or after a network error.
|
@@ -16,6 +16,7 @@ final class TransferStats
|
|
16 |
private $transferTime;
|
17 |
private $handlerStats;
|
18 |
private $handlerErrorData;
|
|
|
19 |
/**
|
20 |
* @param RequestInterface $request Request that was sent.
|
21 |
* @param ResponseInterface $response Response received (if any)
|
@@ -23,14 +24,20 @@ final class TransferStats
|
|
23 |
* @param mixed $handlerErrorData Handler error data.
|
24 |
* @param array $handlerStats Handler specific stats.
|
25 |
*/
|
26 |
-
public function __construct(
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
28 |
$this->request = $request;
|
29 |
$this->response = $response;
|
30 |
$this->transferTime = $transferTime;
|
31 |
$this->handlerErrorData = $handlerErrorData;
|
32 |
$this->handlerStats = $handlerStats;
|
33 |
}
|
|
|
34 |
/**
|
35 |
* @return RequestInterface
|
36 |
*/
|
@@ -38,6 +45,7 @@ final class TransferStats
|
|
38 |
{
|
39 |
return $this->request;
|
40 |
}
|
|
|
41 |
/**
|
42 |
* Returns the response that was received (if any).
|
43 |
*
|
@@ -47,6 +55,7 @@ final class TransferStats
|
|
47 |
{
|
48 |
return $this->response;
|
49 |
}
|
|
|
50 |
/**
|
51 |
* Returns true if a response was received.
|
52 |
*
|
@@ -56,6 +65,7 @@ final class TransferStats
|
|
56 |
{
|
57 |
return $this->response !== null;
|
58 |
}
|
|
|
59 |
/**
|
60 |
* Gets handler specific error data.
|
61 |
*
|
@@ -69,6 +79,7 @@ final class TransferStats
|
|
69 |
{
|
70 |
return $this->handlerErrorData;
|
71 |
}
|
|
|
72 |
/**
|
73 |
* Get the effective URI the request was sent to.
|
74 |
*
|
@@ -78,6 +89,7 @@ final class TransferStats
|
|
78 |
{
|
79 |
return $this->request->getUri();
|
80 |
}
|
|
|
81 |
/**
|
82 |
* Get the estimated time the request was being transferred by the handler.
|
83 |
*
|
@@ -87,6 +99,7 @@ final class TransferStats
|
|
87 |
{
|
88 |
return $this->transferTime;
|
89 |
}
|
|
|
90 |
/**
|
91 |
* Gets an array of all of the handler specific transfer data.
|
92 |
*
|
@@ -96,6 +109,7 @@ final class TransferStats
|
|
96 |
{
|
97 |
return $this->handlerStats;
|
98 |
}
|
|
|
99 |
/**
|
100 |
* Get a specific handler statistic from the handler by name.
|
101 |
*
|
@@ -105,6 +119,8 @@ final class TransferStats
|
|
105 |
*/
|
106 |
public function getHandlerStat($stat)
|
107 |
{
|
108 |
-
return isset($this->handlerStats[$stat])
|
|
|
|
|
109 |
}
|
110 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
use Psr\Http\Message\UriInterface;
|
7 |
|
|
|
|
|
|
|
8 |
/**
|
9 |
* Represents data at the point after it was transferred either successfully
|
10 |
* or after a network error.
|
16 |
private $transferTime;
|
17 |
private $handlerStats;
|
18 |
private $handlerErrorData;
|
19 |
+
|
20 |
/**
|
21 |
* @param RequestInterface $request Request that was sent.
|
22 |
* @param ResponseInterface $response Response received (if any)
|
24 |
* @param mixed $handlerErrorData Handler error data.
|
25 |
* @param array $handlerStats Handler specific stats.
|
26 |
*/
|
27 |
+
public function __construct(
|
28 |
+
RequestInterface $request,
|
29 |
+
ResponseInterface $response = null,
|
30 |
+
$transferTime = null,
|
31 |
+
$handlerErrorData = null,
|
32 |
+
$handlerStats = []
|
33 |
+
) {
|
34 |
$this->request = $request;
|
35 |
$this->response = $response;
|
36 |
$this->transferTime = $transferTime;
|
37 |
$this->handlerErrorData = $handlerErrorData;
|
38 |
$this->handlerStats = $handlerStats;
|
39 |
}
|
40 |
+
|
41 |
/**
|
42 |
* @return RequestInterface
|
43 |
*/
|
45 |
{
|
46 |
return $this->request;
|
47 |
}
|
48 |
+
|
49 |
/**
|
50 |
* Returns the response that was received (if any).
|
51 |
*
|
55 |
{
|
56 |
return $this->response;
|
57 |
}
|
58 |
+
|
59 |
/**
|
60 |
* Returns true if a response was received.
|
61 |
*
|
65 |
{
|
66 |
return $this->response !== null;
|
67 |
}
|
68 |
+
|
69 |
/**
|
70 |
* Gets handler specific error data.
|
71 |
*
|
79 |
{
|
80 |
return $this->handlerErrorData;
|
81 |
}
|
82 |
+
|
83 |
/**
|
84 |
* Get the effective URI the request was sent to.
|
85 |
*
|
89 |
{
|
90 |
return $this->request->getUri();
|
91 |
}
|
92 |
+
|
93 |
/**
|
94 |
* Get the estimated time the request was being transferred by the handler.
|
95 |
*
|
99 |
{
|
100 |
return $this->transferTime;
|
101 |
}
|
102 |
+
|
103 |
/**
|
104 |
* Gets an array of all of the handler specific transfer data.
|
105 |
*
|
109 |
{
|
110 |
return $this->handlerStats;
|
111 |
}
|
112 |
+
|
113 |
/**
|
114 |
* Get a specific handler statistic from the handler by name.
|
115 |
*
|
119 |
*/
|
120 |
public function getHandlerStat($stat)
|
121 |
{
|
122 |
+
return isset($this->handlerStats[$stat])
|
123 |
+
? $this->handlerStats[$stat]
|
124 |
+
: null;
|
125 |
}
|
126 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp;
|
4 |
|
5 |
/**
|
6 |
* Expands URI templates. Userland implementation of PECL uri_template.
|
@@ -11,23 +10,47 @@ class UriTemplate
|
|
11 |
{
|
12 |
/** @var string URI template */
|
13 |
private $template;
|
|
|
14 |
/** @var array Variables to use in the template expansion */
|
15 |
private $variables;
|
|
|
16 |
/** @var array Hash for quick operator lookups */
|
17 |
-
private static $operatorHash = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
/** @var array Delimiters */
|
19 |
-
private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
|
|
|
|
|
20 |
/** @var array Percent encoded delimiters */
|
21 |
-
private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
|
|
|
|
|
|
|
22 |
public function expand($template, array $variables)
|
23 |
{
|
24 |
-
if (
|
25 |
return $template;
|
26 |
}
|
|
|
27 |
$this->template = $template;
|
28 |
$this->variables = $variables;
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
30 |
}
|
|
|
31 |
/**
|
32 |
* Parse an expression into parts
|
33 |
*
|
@@ -38,30 +61,34 @@ class UriTemplate
|
|
38 |
private function parseExpression($expression)
|
39 |
{
|
40 |
$result = [];
|
|
|
41 |
if (isset(self::$operatorHash[$expression[0]])) {
|
42 |
$result['operator'] = $expression[0];
|
43 |
-
$expression =
|
44 |
} else {
|
45 |
$result['operator'] = '';
|
46 |
}
|
47 |
-
|
48 |
-
|
|
|
49 |
$varspec = [];
|
50 |
-
if ($colonPos =
|
51 |
-
$varspec['value'] =
|
52 |
$varspec['modifier'] = ':';
|
53 |
-
$varspec['position'] = (int)
|
54 |
-
} elseif (
|
55 |
$varspec['modifier'] = '*';
|
56 |
-
$varspec['value'] =
|
57 |
} else {
|
58 |
$varspec['value'] = (string) $value;
|
59 |
$varspec['modifier'] = '';
|
60 |
}
|
61 |
$result['values'][] = $varspec;
|
62 |
}
|
|
|
63 |
return $result;
|
64 |
}
|
|
|
65 |
/**
|
66 |
* Process an expansion
|
67 |
*
|
@@ -72,40 +99,51 @@ class UriTemplate
|
|
72 |
private function expandMatch(array $matches)
|
73 |
{
|
74 |
static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
|
|
|
75 |
$replacements = [];
|
76 |
$parsed = self::parseExpression($matches[1]);
|
77 |
$prefix = self::$operatorHash[$parsed['operator']]['prefix'];
|
78 |
$joiner = self::$operatorHash[$parsed['operator']]['joiner'];
|
79 |
$useQuery = self::$operatorHash[$parsed['operator']]['query'];
|
|
|
80 |
foreach ($parsed['values'] as $value) {
|
81 |
if (!isset($this->variables[$value['value']])) {
|
82 |
continue;
|
83 |
}
|
|
|
84 |
$variable = $this->variables[$value['value']];
|
85 |
$actuallyUseQuery = $useQuery;
|
86 |
$expanded = '';
|
87 |
-
|
|
|
88 |
$isAssoc = $this->isAssoc($variable);
|
89 |
$kvp = [];
|
90 |
foreach ($variable as $key => $var) {
|
91 |
if ($isAssoc) {
|
92 |
-
$key =
|
93 |
-
$isNestedArray =
|
94 |
} else {
|
95 |
-
$isNestedArray =
|
96 |
}
|
|
|
97 |
if (!$isNestedArray) {
|
98 |
-
$var =
|
99 |
-
if ($parsed['operator'] === '+' ||
|
|
|
|
|
100 |
$var = $this->decodeReserved($var);
|
101 |
}
|
102 |
}
|
|
|
103 |
if ($value['modifier'] === '*') {
|
104 |
if ($isAssoc) {
|
105 |
if ($isNestedArray) {
|
106 |
// Nested arrays must allow for deeply nested
|
107 |
// structures.
|
108 |
-
$var =
|
|
|
|
|
|
|
109 |
} else {
|
110 |
$var = $key . '=' . $var;
|
111 |
}
|
@@ -113,16 +151,18 @@ class UriTemplate
|
|
113 |
$var = $value['value'] . '=' . $var;
|
114 |
}
|
115 |
}
|
|
|
116 |
$kvp[$key] = $var;
|
117 |
}
|
|
|
118 |
if (empty($variable)) {
|
119 |
-
$actuallyUseQuery =
|
120 |
} elseif ($value['modifier'] === '*') {
|
121 |
-
$expanded =
|
122 |
if ($isAssoc) {
|
123 |
// Don't prepend the value name when using the explode
|
124 |
// modifier with an associative array.
|
125 |
-
$actuallyUseQuery =
|
126 |
}
|
127 |
} else {
|
128 |
if ($isAssoc) {
|
@@ -134,17 +174,18 @@ class UriTemplate
|
|
134 |
$v = $k . ',' . $v;
|
135 |
}
|
136 |
}
|
137 |
-
$expanded =
|
138 |
}
|
139 |
} else {
|
140 |
if ($value['modifier'] === ':') {
|
141 |
-
$variable =
|
142 |
}
|
143 |
-
$expanded =
|
144 |
if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
|
145 |
$expanded = $this->decodeReserved($expanded);
|
146 |
}
|
147 |
}
|
|
|
148 |
if ($actuallyUseQuery) {
|
149 |
if (!$expanded && $joiner !== '&') {
|
150 |
$expanded = $value['value'];
|
@@ -152,14 +193,18 @@ class UriTemplate
|
|
152 |
$expanded = $value['value'] . '=' . $expanded;
|
153 |
}
|
154 |
}
|
|
|
155 |
$replacements[] = $expanded;
|
156 |
}
|
157 |
-
|
|
|
158 |
if ($ret && $prefix) {
|
159 |
return $prefix . $ret;
|
160 |
}
|
|
|
161 |
return $ret;
|
162 |
}
|
|
|
163 |
/**
|
164 |
* Determines if an array is associative.
|
165 |
*
|
@@ -174,8 +219,9 @@ class UriTemplate
|
|
174 |
*/
|
175 |
private function isAssoc(array $array)
|
176 |
{
|
177 |
-
return $array &&
|
178 |
}
|
|
|
179 |
/**
|
180 |
* Removes percent encoding on reserved characters (used with + and #
|
181 |
* modifiers).
|
@@ -186,6 +232,6 @@ class UriTemplate
|
|
186 |
*/
|
187 |
private function decodeReserved($string)
|
188 |
{
|
189 |
-
return
|
190 |
}
|
191 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
|
|
3 |
|
4 |
/**
|
5 |
* Expands URI templates. Userland implementation of PECL uri_template.
|
10 |
{
|
11 |
/** @var string URI template */
|
12 |
private $template;
|
13 |
+
|
14 |
/** @var array Variables to use in the template expansion */
|
15 |
private $variables;
|
16 |
+
|
17 |
/** @var array Hash for quick operator lookups */
|
18 |
+
private static $operatorHash = [
|
19 |
+
'' => ['prefix' => '', 'joiner' => ',', 'query' => false],
|
20 |
+
'+' => ['prefix' => '', 'joiner' => ',', 'query' => false],
|
21 |
+
'#' => ['prefix' => '#', 'joiner' => ',', 'query' => false],
|
22 |
+
'.' => ['prefix' => '.', 'joiner' => '.', 'query' => false],
|
23 |
+
'/' => ['prefix' => '/', 'joiner' => '/', 'query' => false],
|
24 |
+
';' => ['prefix' => ';', 'joiner' => ';', 'query' => true],
|
25 |
+
'?' => ['prefix' => '?', 'joiner' => '&', 'query' => true],
|
26 |
+
'&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]
|
27 |
+
];
|
28 |
+
|
29 |
/** @var array Delimiters */
|
30 |
+
private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
|
31 |
+
'&', '\'', '(', ')', '*', '+', ',', ';', '='];
|
32 |
+
|
33 |
/** @var array Percent encoded delimiters */
|
34 |
+
private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
|
35 |
+
'%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
|
36 |
+
'%3B', '%3D'];
|
37 |
+
|
38 |
public function expand($template, array $variables)
|
39 |
{
|
40 |
+
if (false === strpos($template, '{')) {
|
41 |
return $template;
|
42 |
}
|
43 |
+
|
44 |
$this->template = $template;
|
45 |
$this->variables = $variables;
|
46 |
+
|
47 |
+
return preg_replace_callback(
|
48 |
+
'/\{([^\}]+)\}/',
|
49 |
+
[$this, 'expandMatch'],
|
50 |
+
$this->template
|
51 |
+
);
|
52 |
}
|
53 |
+
|
54 |
/**
|
55 |
* Parse an expression into parts
|
56 |
*
|
61 |
private function parseExpression($expression)
|
62 |
{
|
63 |
$result = [];
|
64 |
+
|
65 |
if (isset(self::$operatorHash[$expression[0]])) {
|
66 |
$result['operator'] = $expression[0];
|
67 |
+
$expression = substr($expression, 1);
|
68 |
} else {
|
69 |
$result['operator'] = '';
|
70 |
}
|
71 |
+
|
72 |
+
foreach (explode(',', $expression) as $value) {
|
73 |
+
$value = trim($value);
|
74 |
$varspec = [];
|
75 |
+
if ($colonPos = strpos($value, ':')) {
|
76 |
+
$varspec['value'] = substr($value, 0, $colonPos);
|
77 |
$varspec['modifier'] = ':';
|
78 |
+
$varspec['position'] = (int) substr($value, $colonPos + 1);
|
79 |
+
} elseif (substr($value, -1) === '*') {
|
80 |
$varspec['modifier'] = '*';
|
81 |
+
$varspec['value'] = substr($value, 0, -1);
|
82 |
} else {
|
83 |
$varspec['value'] = (string) $value;
|
84 |
$varspec['modifier'] = '';
|
85 |
}
|
86 |
$result['values'][] = $varspec;
|
87 |
}
|
88 |
+
|
89 |
return $result;
|
90 |
}
|
91 |
+
|
92 |
/**
|
93 |
* Process an expansion
|
94 |
*
|
99 |
private function expandMatch(array $matches)
|
100 |
{
|
101 |
static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
|
102 |
+
|
103 |
$replacements = [];
|
104 |
$parsed = self::parseExpression($matches[1]);
|
105 |
$prefix = self::$operatorHash[$parsed['operator']]['prefix'];
|
106 |
$joiner = self::$operatorHash[$parsed['operator']]['joiner'];
|
107 |
$useQuery = self::$operatorHash[$parsed['operator']]['query'];
|
108 |
+
|
109 |
foreach ($parsed['values'] as $value) {
|
110 |
if (!isset($this->variables[$value['value']])) {
|
111 |
continue;
|
112 |
}
|
113 |
+
|
114 |
$variable = $this->variables[$value['value']];
|
115 |
$actuallyUseQuery = $useQuery;
|
116 |
$expanded = '';
|
117 |
+
|
118 |
+
if (is_array($variable)) {
|
119 |
$isAssoc = $this->isAssoc($variable);
|
120 |
$kvp = [];
|
121 |
foreach ($variable as $key => $var) {
|
122 |
if ($isAssoc) {
|
123 |
+
$key = rawurlencode($key);
|
124 |
+
$isNestedArray = is_array($var);
|
125 |
} else {
|
126 |
+
$isNestedArray = false;
|
127 |
}
|
128 |
+
|
129 |
if (!$isNestedArray) {
|
130 |
+
$var = rawurlencode($var);
|
131 |
+
if ($parsed['operator'] === '+' ||
|
132 |
+
$parsed['operator'] === '#'
|
133 |
+
) {
|
134 |
$var = $this->decodeReserved($var);
|
135 |
}
|
136 |
}
|
137 |
+
|
138 |
if ($value['modifier'] === '*') {
|
139 |
if ($isAssoc) {
|
140 |
if ($isNestedArray) {
|
141 |
// Nested arrays must allow for deeply nested
|
142 |
// structures.
|
143 |
+
$var = strtr(
|
144 |
+
http_build_query([$key => $var]),
|
145 |
+
$rfc1738to3986
|
146 |
+
);
|
147 |
} else {
|
148 |
$var = $key . '=' . $var;
|
149 |
}
|
151 |
$var = $value['value'] . '=' . $var;
|
152 |
}
|
153 |
}
|
154 |
+
|
155 |
$kvp[$key] = $var;
|
156 |
}
|
157 |
+
|
158 |
if (empty($variable)) {
|
159 |
+
$actuallyUseQuery = false;
|
160 |
} elseif ($value['modifier'] === '*') {
|
161 |
+
$expanded = implode($joiner, $kvp);
|
162 |
if ($isAssoc) {
|
163 |
// Don't prepend the value name when using the explode
|
164 |
// modifier with an associative array.
|
165 |
+
$actuallyUseQuery = false;
|
166 |
}
|
167 |
} else {
|
168 |
if ($isAssoc) {
|
174 |
$v = $k . ',' . $v;
|
175 |
}
|
176 |
}
|
177 |
+
$expanded = implode(',', $kvp);
|
178 |
}
|
179 |
} else {
|
180 |
if ($value['modifier'] === ':') {
|
181 |
+
$variable = substr($variable, 0, $value['position']);
|
182 |
}
|
183 |
+
$expanded = rawurlencode($variable);
|
184 |
if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
|
185 |
$expanded = $this->decodeReserved($expanded);
|
186 |
}
|
187 |
}
|
188 |
+
|
189 |
if ($actuallyUseQuery) {
|
190 |
if (!$expanded && $joiner !== '&') {
|
191 |
$expanded = $value['value'];
|
193 |
$expanded = $value['value'] . '=' . $expanded;
|
194 |
}
|
195 |
}
|
196 |
+
|
197 |
$replacements[] = $expanded;
|
198 |
}
|
199 |
+
|
200 |
+
$ret = implode($joiner, $replacements);
|
201 |
if ($ret && $prefix) {
|
202 |
return $prefix . $ret;
|
203 |
}
|
204 |
+
|
205 |
return $ret;
|
206 |
}
|
207 |
+
|
208 |
/**
|
209 |
* Determines if an array is associative.
|
210 |
*
|
219 |
*/
|
220 |
private function isAssoc(array $array)
|
221 |
{
|
222 |
+
return $array && array_keys($array)[0] !== 0;
|
223 |
}
|
224 |
+
|
225 |
/**
|
226 |
* Removes percent encoding on reserved characters (used with + and #
|
227 |
* modifiers).
|
232 |
*/
|
233 |
private function decodeReserved($string)
|
234 |
{
|
235 |
+
return str_replace(self::$delimsPct, self::$delims, $string);
|
236 |
}
|
237 |
}
|
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlHandler;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\CurlMultiHandler;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\Proxy;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\StreamHandler;
|
9 |
/**
|
10 |
* Expands a URI template
|
11 |
*
|
@@ -16,17 +16,20 @@ use _PhpScoper5bbb1f4b001f3\GuzzleHttp\Handler\StreamHandler;
|
|
16 |
*/
|
17 |
function uri_template($template, array $variables)
|
18 |
{
|
19 |
-
if (
|
20 |
// @codeCoverageIgnoreStart
|
21 |
-
return \
|
22 |
// @codeCoverageIgnoreEnd
|
23 |
}
|
|
|
24 |
static $uriTemplate;
|
25 |
if (!$uriTemplate) {
|
26 |
-
$uriTemplate = new
|
27 |
}
|
|
|
28 |
return $uriTemplate->expand($template, $variables);
|
29 |
}
|
|
|
30 |
/**
|
31 |
* Debug function used to describe the provided value type and class.
|
32 |
*
|
@@ -37,18 +40,19 @@ function uri_template($template, array $variables)
|
|
37 |
*/
|
38 |
function describe_type($input)
|
39 |
{
|
40 |
-
switch (
|
41 |
case 'object':
|
42 |
-
return 'object(' .
|
43 |
case 'array':
|
44 |
-
return 'array(' .
|
45 |
default:
|
46 |
-
|
47 |
-
|
48 |
// normalize float vs double
|
49 |
-
return
|
50 |
}
|
51 |
}
|
|
|
52 |
/**
|
53 |
* Parses an array of header lines into an associative array of headers.
|
54 |
*
|
@@ -59,12 +63,17 @@ function describe_type($input)
|
|
59 |
function headers_from_lines($lines)
|
60 |
{
|
61 |
$headers = [];
|
|
|
62 |
foreach ($lines as $line) {
|
63 |
-
$parts =
|
64 |
-
$headers[
|
|
|
|
|
65 |
}
|
|
|
66 |
return $headers;
|
67 |
}
|
|
|
68 |
/**
|
69 |
* Returns a debug stream based on the provided variable.
|
70 |
*
|
@@ -74,13 +83,15 @@ function headers_from_lines($lines)
|
|
74 |
*/
|
75 |
function debug_resource($value = null)
|
76 |
{
|
77 |
-
if (
|
78 |
return $value;
|
79 |
-
} elseif (
|
80 |
-
return
|
81 |
}
|
82 |
-
|
|
|
83 |
}
|
|
|
84 |
/**
|
85 |
* Chooses and creates a default handler to use based on the environment.
|
86 |
*
|
@@ -92,20 +103,26 @@ function debug_resource($value = null)
|
|
92 |
function choose_handler()
|
93 |
{
|
94 |
$handler = null;
|
95 |
-
if (
|
96 |
-
$handler =
|
97 |
-
} elseif (
|
98 |
-
$handler = new
|
99 |
-
} elseif (
|
100 |
-
$handler = new
|
101 |
}
|
102 |
-
|
103 |
-
|
|
|
|
|
|
|
104 |
} elseif (!$handler) {
|
105 |
-
throw new \RuntimeException('GuzzleHttp requires cURL, the '
|
|
|
106 |
}
|
|
|
107 |
return $handler;
|
108 |
}
|
|
|
109 |
/**
|
110 |
* Get the default User-Agent string to use with Guzzle
|
111 |
*
|
@@ -114,15 +131,18 @@ function choose_handler()
|
|
114 |
function default_user_agent()
|
115 |
{
|
116 |
static $defaultAgent = '';
|
|
|
117 |
if (!$defaultAgent) {
|
118 |
-
$defaultAgent = 'GuzzleHttp/' .
|
119 |
-
if (
|
120 |
$defaultAgent .= ' curl/' . \curl_version()['version'];
|
121 |
}
|
122 |
-
$defaultAgent .= ' PHP/' .
|
123 |
}
|
|
|
124 |
return $defaultAgent;
|
125 |
}
|
|
|
126 |
/**
|
127 |
* Returns the default cacert bundle for the current system.
|
128 |
*
|
@@ -157,21 +177,26 @@ function default_ca_bundle()
|
|
157 |
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
158 |
'C:\\windows\\curl-ca-bundle.crt',
|
159 |
];
|
|
|
160 |
if ($cached) {
|
161 |
return $cached;
|
162 |
}
|
163 |
-
|
|
|
164 |
return $cached = $ca;
|
165 |
}
|
166 |
-
|
|
|
167 |
return $cached = $ca;
|
168 |
}
|
|
|
169 |
foreach ($cafiles as $filename) {
|
170 |
-
if (
|
171 |
return $cached = $filename;
|
172 |
}
|
173 |
}
|
174 |
-
|
|
|
175 |
No system CA bundle could be found in any of the the common system locations.
|
176 |
PHP versions earlier than 5.6 are not properly configured to use the system's
|
177 |
CA bundle by default. In order to verify peer certificates, you will need to
|
@@ -185,8 +210,9 @@ ini setting to point to the path to the file, allowing you to omit the 'verify'
|
|
185 |
request option. See http://curl.haxx.se/docs/sslcerts.html for more
|
186 |
information.
|
187 |
EOT
|
188 |
-
);
|
189 |
}
|
|
|
190 |
/**
|
191 |
* Creates an associative array of lowercase header names to the actual
|
192 |
* header casing.
|
@@ -198,11 +224,13 @@ EOT
|
|
198 |
function normalize_header_keys(array $headers)
|
199 |
{
|
200 |
$result = [];
|
201 |
-
foreach (
|
202 |
-
$result[
|
203 |
}
|
|
|
204 |
return $result;
|
205 |
}
|
|
|
206 |
/**
|
207 |
* Returns true if the provided host matches any of the no proxy areas.
|
208 |
*
|
@@ -224,34 +252,38 @@ function normalize_header_keys(array $headers)
|
|
224 |
*/
|
225 |
function is_host_in_noproxy($host, array $noProxyArray)
|
226 |
{
|
227 |
-
if (
|
228 |
throw new \InvalidArgumentException('Empty host provided');
|
229 |
}
|
|
|
230 |
// Strip port if present.
|
231 |
-
if (
|
232 |
-
$host =
|
233 |
}
|
|
|
234 |
foreach ($noProxyArray as $area) {
|
235 |
// Always match on wildcards.
|
236 |
if ($area === '*') {
|
237 |
-
return
|
238 |
} elseif (empty($area)) {
|
239 |
// Don't match on empty values.
|
240 |
continue;
|
241 |
} elseif ($area === $host) {
|
242 |
// Exact matches.
|
243 |
-
return
|
244 |
} else {
|
245 |
// Special match if the area when prefixed with ".". Remove any
|
246 |
// existing leading "." and add a new leading ".".
|
247 |
-
$area = '.' .
|
248 |
-
if (
|
249 |
-
return
|
250 |
}
|
251 |
}
|
252 |
}
|
253 |
-
|
|
|
254 |
}
|
|
|
255 |
/**
|
256 |
* Wrapper for json_decode that throws when an error occurs.
|
257 |
*
|
@@ -265,14 +297,18 @@ function is_host_in_noproxy($host, array $noProxyArray)
|
|
265 |
* @throws \InvalidArgumentException if the JSON cannot be decoded.
|
266 |
* @link http://www.php.net/manual/en/function.json-decode.php
|
267 |
*/
|
268 |
-
function json_decode($json, $assoc =
|
269 |
{
|
270 |
$data = \json_decode($json, $assoc, $depth, $options);
|
271 |
-
if (
|
272 |
-
throw new \InvalidArgumentException(
|
|
|
|
|
273 |
}
|
|
|
274 |
return $data;
|
275 |
}
|
|
|
276 |
/**
|
277 |
* Wrapper for JSON encoding that throws when an error occurs.
|
278 |
*
|
@@ -287,8 +323,11 @@ function json_decode($json, $assoc = \false, $depth = 512, $options = 0)
|
|
287 |
function json_encode($value, $options = 0, $depth = 512)
|
288 |
{
|
289 |
$json = \json_encode($value, $options, $depth);
|
290 |
-
if (
|
291 |
-
throw new \InvalidArgumentException(
|
|
|
|
|
292 |
}
|
|
|
293 |
return $json;
|
294 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
|
4 |
+
use GuzzleHttp\Handler\CurlHandler;
|
5 |
+
use GuzzleHttp\Handler\CurlMultiHandler;
|
6 |
+
use GuzzleHttp\Handler\Proxy;
|
7 |
+
use GuzzleHttp\Handler\StreamHandler;
|
8 |
|
|
|
|
|
|
|
|
|
9 |
/**
|
10 |
* Expands a URI template
|
11 |
*
|
16 |
*/
|
17 |
function uri_template($template, array $variables)
|
18 |
{
|
19 |
+
if (extension_loaded('uri_template')) {
|
20 |
// @codeCoverageIgnoreStart
|
21 |
+
return \uri_template($template, $variables);
|
22 |
// @codeCoverageIgnoreEnd
|
23 |
}
|
24 |
+
|
25 |
static $uriTemplate;
|
26 |
if (!$uriTemplate) {
|
27 |
+
$uriTemplate = new UriTemplate();
|
28 |
}
|
29 |
+
|
30 |
return $uriTemplate->expand($template, $variables);
|
31 |
}
|
32 |
+
|
33 |
/**
|
34 |
* Debug function used to describe the provided value type and class.
|
35 |
*
|
40 |
*/
|
41 |
function describe_type($input)
|
42 |
{
|
43 |
+
switch (gettype($input)) {
|
44 |
case 'object':
|
45 |
+
return 'object(' . get_class($input) . ')';
|
46 |
case 'array':
|
47 |
+
return 'array(' . count($input) . ')';
|
48 |
default:
|
49 |
+
ob_start();
|
50 |
+
var_dump($input);
|
51 |
// normalize float vs double
|
52 |
+
return str_replace('double(', 'float(', rtrim(ob_get_clean()));
|
53 |
}
|
54 |
}
|
55 |
+
|
56 |
/**
|
57 |
* Parses an array of header lines into an associative array of headers.
|
58 |
*
|
63 |
function headers_from_lines($lines)
|
64 |
{
|
65 |
$headers = [];
|
66 |
+
|
67 |
foreach ($lines as $line) {
|
68 |
+
$parts = explode(':', $line, 2);
|
69 |
+
$headers[trim($parts[0])][] = isset($parts[1])
|
70 |
+
? trim($parts[1])
|
71 |
+
: null;
|
72 |
}
|
73 |
+
|
74 |
return $headers;
|
75 |
}
|
76 |
+
|
77 |
/**
|
78 |
* Returns a debug stream based on the provided variable.
|
79 |
*
|
83 |
*/
|
84 |
function debug_resource($value = null)
|
85 |
{
|
86 |
+
if (is_resource($value)) {
|
87 |
return $value;
|
88 |
+
} elseif (defined('STDOUT')) {
|
89 |
+
return STDOUT;
|
90 |
}
|
91 |
+
|
92 |
+
return fopen('php://output', 'w');
|
93 |
}
|
94 |
+
|
95 |
/**
|
96 |
* Chooses and creates a default handler to use based on the environment.
|
97 |
*
|
103 |
function choose_handler()
|
104 |
{
|
105 |
$handler = null;
|
106 |
+
if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
|
107 |
+
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
|
108 |
+
} elseif (function_exists('curl_exec')) {
|
109 |
+
$handler = new CurlHandler();
|
110 |
+
} elseif (function_exists('curl_multi_exec')) {
|
111 |
+
$handler = new CurlMultiHandler();
|
112 |
}
|
113 |
+
|
114 |
+
if (ini_get('allow_url_fopen')) {
|
115 |
+
$handler = $handler
|
116 |
+
? Proxy::wrapStreaming($handler, new StreamHandler())
|
117 |
+
: new StreamHandler();
|
118 |
} elseif (!$handler) {
|
119 |
+
throw new \RuntimeException('GuzzleHttp requires cURL, the '
|
120 |
+
. 'allow_url_fopen ini setting, or a custom HTTP handler.');
|
121 |
}
|
122 |
+
|
123 |
return $handler;
|
124 |
}
|
125 |
+
|
126 |
/**
|
127 |
* Get the default User-Agent string to use with Guzzle
|
128 |
*
|
131 |
function default_user_agent()
|
132 |
{
|
133 |
static $defaultAgent = '';
|
134 |
+
|
135 |
if (!$defaultAgent) {
|
136 |
+
$defaultAgent = 'GuzzleHttp/' . Client::VERSION;
|
137 |
+
if (extension_loaded('curl') && function_exists('curl_version')) {
|
138 |
$defaultAgent .= ' curl/' . \curl_version()['version'];
|
139 |
}
|
140 |
+
$defaultAgent .= ' PHP/' . PHP_VERSION;
|
141 |
}
|
142 |
+
|
143 |
return $defaultAgent;
|
144 |
}
|
145 |
+
|
146 |
/**
|
147 |
* Returns the default cacert bundle for the current system.
|
148 |
*
|
177 |
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
178 |
'C:\\windows\\curl-ca-bundle.crt',
|
179 |
];
|
180 |
+
|
181 |
if ($cached) {
|
182 |
return $cached;
|
183 |
}
|
184 |
+
|
185 |
+
if ($ca = ini_get('openssl.cafile')) {
|
186 |
return $cached = $ca;
|
187 |
}
|
188 |
+
|
189 |
+
if ($ca = ini_get('curl.cainfo')) {
|
190 |
return $cached = $ca;
|
191 |
}
|
192 |
+
|
193 |
foreach ($cafiles as $filename) {
|
194 |
+
if (file_exists($filename)) {
|
195 |
return $cached = $filename;
|
196 |
}
|
197 |
}
|
198 |
+
|
199 |
+
throw new \RuntimeException(<<< EOT
|
200 |
No system CA bundle could be found in any of the the common system locations.
|
201 |
PHP versions earlier than 5.6 are not properly configured to use the system's
|
202 |
CA bundle by default. In order to verify peer certificates, you will need to
|
210 |
request option. See http://curl.haxx.se/docs/sslcerts.html for more
|
211 |
information.
|
212 |
EOT
|
213 |
+
);
|
214 |
}
|
215 |
+
|
216 |
/**
|
217 |
* Creates an associative array of lowercase header names to the actual
|
218 |
* header casing.
|
224 |
function normalize_header_keys(array $headers)
|
225 |
{
|
226 |
$result = [];
|
227 |
+
foreach (array_keys($headers) as $key) {
|
228 |
+
$result[strtolower($key)] = $key;
|
229 |
}
|
230 |
+
|
231 |
return $result;
|
232 |
}
|
233 |
+
|
234 |
/**
|
235 |
* Returns true if the provided host matches any of the no proxy areas.
|
236 |
*
|
252 |
*/
|
253 |
function is_host_in_noproxy($host, array $noProxyArray)
|
254 |
{
|
255 |
+
if (strlen($host) === 0) {
|
256 |
throw new \InvalidArgumentException('Empty host provided');
|
257 |
}
|
258 |
+
|
259 |
// Strip port if present.
|
260 |
+
if (strpos($host, ':')) {
|
261 |
+
$host = explode($host, ':', 2)[0];
|
262 |
}
|
263 |
+
|
264 |
foreach ($noProxyArray as $area) {
|
265 |
// Always match on wildcards.
|
266 |
if ($area === '*') {
|
267 |
+
return true;
|
268 |
} elseif (empty($area)) {
|
269 |
// Don't match on empty values.
|
270 |
continue;
|
271 |
} elseif ($area === $host) {
|
272 |
// Exact matches.
|
273 |
+
return true;
|
274 |
} else {
|
275 |
// Special match if the area when prefixed with ".". Remove any
|
276 |
// existing leading "." and add a new leading ".".
|
277 |
+
$area = '.' . ltrim($area, '.');
|
278 |
+
if (substr($host, -(strlen($area))) === $area) {
|
279 |
+
return true;
|
280 |
}
|
281 |
}
|
282 |
}
|
283 |
+
|
284 |
+
return false;
|
285 |
}
|
286 |
+
|
287 |
/**
|
288 |
* Wrapper for json_decode that throws when an error occurs.
|
289 |
*
|
297 |
* @throws \InvalidArgumentException if the JSON cannot be decoded.
|
298 |
* @link http://www.php.net/manual/en/function.json-decode.php
|
299 |
*/
|
300 |
+
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
|
301 |
{
|
302 |
$data = \json_decode($json, $assoc, $depth, $options);
|
303 |
+
if (JSON_ERROR_NONE !== json_last_error()) {
|
304 |
+
throw new \InvalidArgumentException(
|
305 |
+
'json_decode error: ' . json_last_error_msg()
|
306 |
+
);
|
307 |
}
|
308 |
+
|
309 |
return $data;
|
310 |
}
|
311 |
+
|
312 |
/**
|
313 |
* Wrapper for JSON encoding that throws when an error occurs.
|
314 |
*
|
323 |
function json_encode($value, $options = 0, $depth = 512)
|
324 |
{
|
325 |
$json = \json_encode($value, $options, $depth);
|
326 |
+
if (JSON_ERROR_NONE !== json_last_error()) {
|
327 |
+
throw new \InvalidArgumentException(
|
328 |
+
'json_encode error: ' . json_last_error_msg()
|
329 |
+
);
|
330 |
}
|
331 |
+
|
332 |
return $json;
|
333 |
}
|
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
// Don't redefine the functions if included multiple times.
|
6 |
-
if (
|
7 |
require __DIR__ . '/functions.php';
|
8 |
}
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
// Don't redefine the functions if included multiple times.
|
4 |
+
if (!function_exists('GuzzleHttp\uri_template')) {
|
5 |
require __DIR__ . '/functions.php';
|
6 |
}
|
@@ -1,38 +1,34 @@
|
|
1 |
{
|
2 |
-
"name": "guzzlehttp
|
3 |
"description": "Guzzle promises library",
|
4 |
-
"keywords": [
|
5 |
-
"promise"
|
6 |
-
],
|
7 |
"license": "MIT",
|
8 |
"authors": [
|
9 |
{
|
10 |
"name": "Michael Dowling",
|
11 |
"email": "mtdowling@gmail.com",
|
12 |
-
"homepage": "https
|
13 |
}
|
14 |
],
|
15 |
"require": {
|
16 |
"php": ">=5.5.0"
|
17 |
},
|
18 |
"require-dev": {
|
19 |
-
"phpunit
|
20 |
},
|
21 |
"autoload": {
|
22 |
"psr-4": {
|
23 |
-
"
|
24 |
},
|
25 |
-
"files": [
|
26 |
-
"src\/functions_include.php"
|
27 |
-
]
|
28 |
},
|
29 |
"scripts": {
|
30 |
-
"test": "vendor
|
31 |
-
"test-ci": "vendor
|
32 |
},
|
33 |
"extra": {
|
34 |
"branch-alias": {
|
35 |
"dev-master": "1.4-dev"
|
36 |
}
|
37 |
}
|
38 |
-
}
|
1 |
{
|
2 |
+
"name": "guzzlehttp/promises",
|
3 |
"description": "Guzzle promises library",
|
4 |
+
"keywords": ["promise"],
|
|
|
|
|
5 |
"license": "MIT",
|
6 |
"authors": [
|
7 |
{
|
8 |
"name": "Michael Dowling",
|
9 |
"email": "mtdowling@gmail.com",
|
10 |
+
"homepage": "https://github.com/mtdowling"
|
11 |
}
|
12 |
],
|
13 |
"require": {
|
14 |
"php": ">=5.5.0"
|
15 |
},
|
16 |
"require-dev": {
|
17 |
+
"phpunit/phpunit": "^4.0"
|
18 |
},
|
19 |
"autoload": {
|
20 |
"psr-4": {
|
21 |
+
"GuzzleHttp\\Promise\\": "src/"
|
22 |
},
|
23 |
+
"files": ["src/functions_include.php"]
|
|
|
|
|
24 |
},
|
25 |
"scripts": {
|
26 |
+
"test": "vendor/bin/phpunit",
|
27 |
+
"test-ci": "vendor/bin/phpunit --coverage-text"
|
28 |
},
|
29 |
"extra": {
|
30 |
"branch-alias": {
|
31 |
"dev-master": "1.4-dev"
|
32 |
}
|
33 |
}
|
34 |
+
}
|
@@ -1,14 +1,16 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* Exception thrown when too many errors occur in the some() or any() methods.
|
7 |
*/
|
8 |
-
class AggregateException extends
|
9 |
{
|
10 |
public function __construct($msg, array $reasons)
|
11 |
{
|
12 |
-
parent::__construct(
|
|
|
|
|
|
|
13 |
}
|
14 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* Exception thrown when too many errors occur in the some() or any() methods.
|
6 |
*/
|
7 |
+
class AggregateException extends RejectionException
|
8 |
{
|
9 |
public function __construct($msg, array $reasons)
|
10 |
{
|
11 |
+
parent::__construct(
|
12 |
+
$reasons,
|
13 |
+
sprintf('%s; %d rejected promises', $msg, count($reasons))
|
14 |
+
);
|
15 |
}
|
16 |
}
|
@@ -1,10 +1,9 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* Exception that is set as the reason for a promise that has been cancelled.
|
7 |
*/
|
8 |
-
class CancellationException extends
|
9 |
{
|
10 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* Exception that is set as the reason for a promise that has been cancelled.
|
6 |
*/
|
7 |
+
class CancellationException extends RejectionException
|
8 |
{
|
9 |
}
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
use Exception;
|
6 |
use Generator;
|
7 |
use Throwable;
|
|
|
8 |
/**
|
9 |
* Creates a promise that is resolved using a generator that yields values or
|
10 |
* promises (somewhat similar to C#'s async keyword).
|
@@ -40,63 +40,78 @@ use Throwable;
|
|
40 |
* @return Promise
|
41 |
* @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
|
42 |
*/
|
43 |
-
final class Coroutine implements
|
44 |
{
|
45 |
/**
|
46 |
* @var PromiseInterface|null
|
47 |
*/
|
48 |
private $currentPromise;
|
|
|
49 |
/**
|
50 |
* @var Generator
|
51 |
*/
|
52 |
private $generator;
|
|
|
53 |
/**
|
54 |
* @var Promise
|
55 |
*/
|
56 |
private $result;
|
|
|
57 |
public function __construct(callable $generatorFn)
|
58 |
{
|
59 |
$this->generator = $generatorFn();
|
60 |
-
$this->result = new
|
61 |
while (isset($this->currentPromise)) {
|
62 |
$this->currentPromise->wait();
|
63 |
}
|
64 |
});
|
65 |
$this->nextCoroutine($this->generator->current());
|
66 |
}
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
69 |
return $this->result->then($onFulfilled, $onRejected);
|
70 |
}
|
|
|
71 |
public function otherwise(callable $onRejected)
|
72 |
{
|
73 |
return $this->result->otherwise($onRejected);
|
74 |
}
|
75 |
-
|
|
|
76 |
{
|
77 |
return $this->result->wait($unwrap);
|
78 |
}
|
|
|
79 |
public function getState()
|
80 |
{
|
81 |
return $this->result->getState();
|
82 |
}
|
|
|
83 |
public function resolve($value)
|
84 |
{
|
85 |
$this->result->resolve($value);
|
86 |
}
|
|
|
87 |
public function reject($reason)
|
88 |
{
|
89 |
$this->result->reject($reason);
|
90 |
}
|
|
|
91 |
public function cancel()
|
92 |
{
|
93 |
$this->currentPromise->cancel();
|
94 |
$this->result->cancel();
|
95 |
}
|
|
|
96 |
private function nextCoroutine($yielded)
|
97 |
{
|
98 |
-
$this->currentPromise = promise_for($yielded)
|
|
|
99 |
}
|
|
|
100 |
/**
|
101 |
* @internal
|
102 |
*/
|
@@ -110,12 +125,13 @@ final class Coroutine implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Pro
|
|
110 |
} else {
|
111 |
$this->result->resolve($value);
|
112 |
}
|
113 |
-
} catch (
|
114 |
$this->result->reject($exception);
|
115 |
-
} catch (
|
116 |
$this->result->reject($throwable);
|
117 |
}
|
118 |
}
|
|
|
119 |
/**
|
120 |
* @internal
|
121 |
*/
|
@@ -126,9 +142,9 @@ final class Coroutine implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Pro
|
|
126 |
$nextYield = $this->generator->throw(exception_for($reason));
|
127 |
// The throw was caught, so keep iterating on the coroutine
|
128 |
$this->nextCoroutine($nextYield);
|
129 |
-
} catch (
|
130 |
$this->result->reject($exception);
|
131 |
-
} catch (
|
132 |
$this->result->reject($throwable);
|
133 |
}
|
134 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
use Exception;
|
5 |
use Generator;
|
6 |
use Throwable;
|
7 |
+
|
8 |
/**
|
9 |
* Creates a promise that is resolved using a generator that yields values or
|
10 |
* promises (somewhat similar to C#'s async keyword).
|
40 |
* @return Promise
|
41 |
* @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
|
42 |
*/
|
43 |
+
final class Coroutine implements PromiseInterface
|
44 |
{
|
45 |
/**
|
46 |
* @var PromiseInterface|null
|
47 |
*/
|
48 |
private $currentPromise;
|
49 |
+
|
50 |
/**
|
51 |
* @var Generator
|
52 |
*/
|
53 |
private $generator;
|
54 |
+
|
55 |
/**
|
56 |
* @var Promise
|
57 |
*/
|
58 |
private $result;
|
59 |
+
|
60 |
public function __construct(callable $generatorFn)
|
61 |
{
|
62 |
$this->generator = $generatorFn();
|
63 |
+
$this->result = new Promise(function () {
|
64 |
while (isset($this->currentPromise)) {
|
65 |
$this->currentPromise->wait();
|
66 |
}
|
67 |
});
|
68 |
$this->nextCoroutine($this->generator->current());
|
69 |
}
|
70 |
+
|
71 |
+
public function then(
|
72 |
+
callable $onFulfilled = null,
|
73 |
+
callable $onRejected = null
|
74 |
+
) {
|
75 |
return $this->result->then($onFulfilled, $onRejected);
|
76 |
}
|
77 |
+
|
78 |
public function otherwise(callable $onRejected)
|
79 |
{
|
80 |
return $this->result->otherwise($onRejected);
|
81 |
}
|
82 |
+
|
83 |
+
public function wait($unwrap = true)
|
84 |
{
|
85 |
return $this->result->wait($unwrap);
|
86 |
}
|
87 |
+
|
88 |
public function getState()
|
89 |
{
|
90 |
return $this->result->getState();
|
91 |
}
|
92 |
+
|
93 |
public function resolve($value)
|
94 |
{
|
95 |
$this->result->resolve($value);
|
96 |
}
|
97 |
+
|
98 |
public function reject($reason)
|
99 |
{
|
100 |
$this->result->reject($reason);
|
101 |
}
|
102 |
+
|
103 |
public function cancel()
|
104 |
{
|
105 |
$this->currentPromise->cancel();
|
106 |
$this->result->cancel();
|
107 |
}
|
108 |
+
|
109 |
private function nextCoroutine($yielded)
|
110 |
{
|
111 |
+
$this->currentPromise = promise_for($yielded)
|
112 |
+
->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
|
113 |
}
|
114 |
+
|
115 |
/**
|
116 |
* @internal
|
117 |
*/
|
125 |
} else {
|
126 |
$this->result->resolve($value);
|
127 |
}
|
128 |
+
} catch (Exception $exception) {
|
129 |
$this->result->reject($exception);
|
130 |
+
} catch (Throwable $throwable) {
|
131 |
$this->result->reject($throwable);
|
132 |
}
|
133 |
}
|
134 |
+
|
135 |
/**
|
136 |
* @internal
|
137 |
*/
|
142 |
$nextYield = $this->generator->throw(exception_for($reason));
|
143 |
// The throw was caught, so keep iterating on the coroutine
|
144 |
$this->nextCoroutine($nextYield);
|
145 |
+
} catch (Exception $exception) {
|
146 |
$this->result->reject($exception);
|
147 |
+
} catch (Throwable $throwable) {
|
148 |
$this->result->reject($throwable);
|
149 |
}
|
150 |
}
|
@@ -1,26 +1,32 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* Represents a promise that iterates over many promises and invokes
|
7 |
* side-effect functions in the process.
|
8 |
*/
|
9 |
-
class EachPromise implements
|
10 |
{
|
11 |
private $pending = [];
|
|
|
12 |
/** @var \Iterator */
|
13 |
private $iterable;
|
|
|
14 |
/** @var callable|int */
|
15 |
private $concurrency;
|
|
|
16 |
/** @var callable */
|
17 |
private $onFulfilled;
|
|
|
18 |
/** @var callable */
|
19 |
private $onRejected;
|
|
|
20 |
/** @var Promise */
|
21 |
private $aggregate;
|
|
|
22 |
/** @var bool */
|
23 |
private $mutex;
|
|
|
24 |
/**
|
25 |
* Configuration hash can include the following key value pairs:
|
26 |
*
|
@@ -45,21 +51,26 @@ class EachPromise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Promiso
|
|
45 |
public function __construct($iterable, array $config = [])
|
46 |
{
|
47 |
$this->iterable = iter_for($iterable);
|
|
|
48 |
if (isset($config['concurrency'])) {
|
49 |
$this->concurrency = $config['concurrency'];
|
50 |
}
|
|
|
51 |
if (isset($config['fulfilled'])) {
|
52 |
$this->onFulfilled = $config['fulfilled'];
|
53 |
}
|
|
|
54 |
if (isset($config['rejected'])) {
|
55 |
$this->onRejected = $config['rejected'];
|
56 |
}
|
57 |
}
|
|
|
58 |
public function promise()
|
59 |
{
|
60 |
if ($this->aggregate) {
|
61 |
return $this->aggregate;
|
62 |
}
|
|
|
63 |
try {
|
64 |
$this->createPromise();
|
65 |
$this->iterable->rewind();
|
@@ -69,45 +80,53 @@ class EachPromise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Promiso
|
|
69 |
} catch (\Exception $e) {
|
70 |
$this->aggregate->reject($e);
|
71 |
}
|
|
|
72 |
return $this->aggregate;
|
73 |
}
|
|
|
74 |
private function createPromise()
|
75 |
{
|
76 |
-
$this->mutex =
|
77 |
-
$this->aggregate = new
|
78 |
-
|
79 |
if (empty($this->pending) && !$this->iterable->valid()) {
|
80 |
$this->aggregate->resolve(null);
|
81 |
return;
|
82 |
}
|
|
|
83 |
// Consume a potentially fluctuating list of promises while
|
84 |
// ensuring that indexes are maintained (precluding array_shift).
|
85 |
-
while ($promise =
|
86 |
-
|
87 |
$promise->wait();
|
88 |
-
if ($this->aggregate->getState() !==
|
89 |
return;
|
90 |
}
|
91 |
}
|
92 |
});
|
|
|
93 |
// Clear the references when the promise is resolved.
|
94 |
$clearFn = function () {
|
95 |
$this->iterable = $this->concurrency = $this->pending = null;
|
96 |
$this->onFulfilled = $this->onRejected = null;
|
97 |
};
|
|
|
98 |
$this->aggregate->then($clearFn, $clearFn);
|
99 |
}
|
|
|
100 |
private function refillPending()
|
101 |
{
|
102 |
if (!$this->concurrency) {
|
103 |
// Add all pending promises.
|
104 |
-
while ($this->addPending() && $this->advanceIterator())
|
105 |
-
}
|
106 |
return;
|
107 |
}
|
|
|
108 |
// Add only up to N pending promises.
|
109 |
-
$concurrency =
|
110 |
-
|
|
|
|
|
111 |
// Concurrency may be set to 0 to disallow new promises.
|
112 |
if (!$concurrency) {
|
113 |
return;
|
@@ -118,58 +137,76 @@ class EachPromise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Promiso
|
|
118 |
// not advance the iterator after adding the first promise. This
|
119 |
// helps work around issues with generators that might not have the
|
120 |
// next value to yield until promise callbacks are called.
|
121 |
-
while (--$concurrency
|
122 |
-
|
|
|
123 |
}
|
|
|
124 |
private function addPending()
|
125 |
{
|
126 |
if (!$this->iterable || !$this->iterable->valid()) {
|
127 |
-
return
|
128 |
}
|
|
|
129 |
$promise = promise_for($this->iterable->current());
|
130 |
$idx = $this->iterable->key();
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
}
|
140 |
-
|
141 |
-
|
142 |
-
return
|
143 |
}
|
|
|
144 |
private function advanceIterator()
|
145 |
{
|
146 |
// Place a lock on the iterator so that we ensure to not recurse,
|
147 |
// preventing fatal generator errors.
|
148 |
if ($this->mutex) {
|
149 |
-
return
|
150 |
}
|
151 |
-
|
|
|
|
|
152 |
try {
|
153 |
$this->iterable->next();
|
154 |
-
$this->mutex =
|
155 |
-
return
|
156 |
} catch (\Throwable $e) {
|
157 |
$this->aggregate->reject($e);
|
158 |
-
$this->mutex =
|
159 |
-
return
|
160 |
} catch (\Exception $e) {
|
161 |
$this->aggregate->reject($e);
|
162 |
-
$this->mutex =
|
163 |
-
return
|
164 |
}
|
165 |
}
|
|
|
166 |
private function step($idx)
|
167 |
{
|
168 |
// If the promise was already resolved, then ignore this step.
|
169 |
-
if ($this->aggregate->getState() !==
|
170 |
return;
|
171 |
}
|
|
|
172 |
unset($this->pending[$idx]);
|
|
|
173 |
// Only refill pending promises if we are not locked, preventing the
|
174 |
// EachPromise to recursively invoke the provided iterator, which
|
175 |
// cause a fatal error: "Cannot resume an already running generator"
|
@@ -178,13 +215,15 @@ class EachPromise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Promiso
|
|
178 |
$this->refillPending();
|
179 |
}
|
180 |
}
|
|
|
181 |
private function checkIfFinished()
|
182 |
{
|
183 |
if (!$this->pending && !$this->iterable->valid()) {
|
184 |
// Resolve the promise if there's nothing left to do.
|
185 |
$this->aggregate->resolve(null);
|
186 |
-
return
|
187 |
}
|
188 |
-
|
|
|
189 |
}
|
190 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* Represents a promise that iterates over many promises and invokes
|
6 |
* side-effect functions in the process.
|
7 |
*/
|
8 |
+
class EachPromise implements PromisorInterface
|
9 |
{
|
10 |
private $pending = [];
|
11 |
+
|
12 |
/** @var \Iterator */
|
13 |
private $iterable;
|
14 |
+
|
15 |
/** @var callable|int */
|
16 |
private $concurrency;
|
17 |
+
|
18 |
/** @var callable */
|
19 |
private $onFulfilled;
|
20 |
+
|
21 |
/** @var callable */
|
22 |
private $onRejected;
|
23 |
+
|
24 |
/** @var Promise */
|
25 |
private $aggregate;
|
26 |
+
|
27 |
/** @var bool */
|
28 |
private $mutex;
|
29 |
+
|
30 |
/**
|
31 |
* Configuration hash can include the following key value pairs:
|
32 |
*
|
51 |
public function __construct($iterable, array $config = [])
|
52 |
{
|
53 |
$this->iterable = iter_for($iterable);
|
54 |
+
|
55 |
if (isset($config['concurrency'])) {
|
56 |
$this->concurrency = $config['concurrency'];
|
57 |
}
|
58 |
+
|
59 |
if (isset($config['fulfilled'])) {
|
60 |
$this->onFulfilled = $config['fulfilled'];
|
61 |
}
|
62 |
+
|
63 |
if (isset($config['rejected'])) {
|
64 |
$this->onRejected = $config['rejected'];
|
65 |
}
|
66 |
}
|
67 |
+
|
68 |
public function promise()
|
69 |
{
|
70 |
if ($this->aggregate) {
|
71 |
return $this->aggregate;
|
72 |
}
|
73 |
+
|
74 |
try {
|
75 |
$this->createPromise();
|
76 |
$this->iterable->rewind();
|
80 |
} catch (\Exception $e) {
|
81 |
$this->aggregate->reject($e);
|
82 |
}
|
83 |
+
|
84 |
return $this->aggregate;
|
85 |
}
|
86 |
+
|
87 |
private function createPromise()
|
88 |
{
|
89 |
+
$this->mutex = false;
|
90 |
+
$this->aggregate = new Promise(function () {
|
91 |
+
reset($this->pending);
|
92 |
if (empty($this->pending) && !$this->iterable->valid()) {
|
93 |
$this->aggregate->resolve(null);
|
94 |
return;
|
95 |
}
|
96 |
+
|
97 |
// Consume a potentially fluctuating list of promises while
|
98 |
// ensuring that indexes are maintained (precluding array_shift).
|
99 |
+
while ($promise = current($this->pending)) {
|
100 |
+
next($this->pending);
|
101 |
$promise->wait();
|
102 |
+
if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
|
103 |
return;
|
104 |
}
|
105 |
}
|
106 |
});
|
107 |
+
|
108 |
// Clear the references when the promise is resolved.
|
109 |
$clearFn = function () {
|
110 |
$this->iterable = $this->concurrency = $this->pending = null;
|
111 |
$this->onFulfilled = $this->onRejected = null;
|
112 |
};
|
113 |
+
|
114 |
$this->aggregate->then($clearFn, $clearFn);
|
115 |
}
|
116 |
+
|
117 |
private function refillPending()
|
118 |
{
|
119 |
if (!$this->concurrency) {
|
120 |
// Add all pending promises.
|
121 |
+
while ($this->addPending() && $this->advanceIterator());
|
|
|
122 |
return;
|
123 |
}
|
124 |
+
|
125 |
// Add only up to N pending promises.
|
126 |
+
$concurrency = is_callable($this->concurrency)
|
127 |
+
? call_user_func($this->concurrency, count($this->pending))
|
128 |
+
: $this->concurrency;
|
129 |
+
$concurrency = max($concurrency - count($this->pending), 0);
|
130 |
// Concurrency may be set to 0 to disallow new promises.
|
131 |
if (!$concurrency) {
|
132 |
return;
|
137 |
// not advance the iterator after adding the first promise. This
|
138 |
// helps work around issues with generators that might not have the
|
139 |
// next value to yield until promise callbacks are called.
|
140 |
+
while (--$concurrency
|
141 |
+
&& $this->advanceIterator()
|
142 |
+
&& $this->addPending());
|
143 |
}
|
144 |
+
|
145 |
private function addPending()
|
146 |
{
|
147 |
if (!$this->iterable || !$this->iterable->valid()) {
|
148 |
+
return false;
|
149 |
}
|
150 |
+
|
151 |
$promise = promise_for($this->iterable->current());
|
152 |
$idx = $this->iterable->key();
|
153 |
+
|
154 |
+
$this->pending[$idx] = $promise->then(
|
155 |
+
function ($value) use ($idx) {
|
156 |
+
if ($this->onFulfilled) {
|
157 |
+
call_user_func(
|
158 |
+
$this->onFulfilled, $value, $idx, $this->aggregate
|
159 |
+
);
|
160 |
+
}
|
161 |
+
$this->step($idx);
|
162 |
+
},
|
163 |
+
function ($reason) use ($idx) {
|
164 |
+
if ($this->onRejected) {
|
165 |
+
call_user_func(
|
166 |
+
$this->onRejected, $reason, $idx, $this->aggregate
|
167 |
+
);
|
168 |
+
}
|
169 |
+
$this->step($idx);
|
170 |
}
|
171 |
+
);
|
172 |
+
|
173 |
+
return true;
|
174 |
}
|
175 |
+
|
176 |
private function advanceIterator()
|
177 |
{
|
178 |
// Place a lock on the iterator so that we ensure to not recurse,
|
179 |
// preventing fatal generator errors.
|
180 |
if ($this->mutex) {
|
181 |
+
return false;
|
182 |
}
|
183 |
+
|
184 |
+
$this->mutex = true;
|
185 |
+
|
186 |
try {
|
187 |
$this->iterable->next();
|
188 |
+
$this->mutex = false;
|
189 |
+
return true;
|
190 |
} catch (\Throwable $e) {
|
191 |
$this->aggregate->reject($e);
|
192 |
+
$this->mutex = false;
|
193 |
+
return false;
|
194 |
} catch (\Exception $e) {
|
195 |
$this->aggregate->reject($e);
|
196 |
+
$this->mutex = false;
|
197 |
+
return false;
|
198 |
}
|
199 |
}
|
200 |
+
|
201 |
private function step($idx)
|
202 |
{
|
203 |
// If the promise was already resolved, then ignore this step.
|
204 |
+
if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
|
205 |
return;
|
206 |
}
|
207 |
+
|
208 |
unset($this->pending[$idx]);
|
209 |
+
|
210 |
// Only refill pending promises if we are not locked, preventing the
|
211 |
// EachPromise to recursively invoke the provided iterator, which
|
212 |
// cause a fatal error: "Cannot resume an already running generator"
|
215 |
$this->refillPending();
|
216 |
}
|
217 |
}
|
218 |
+
|
219 |
private function checkIfFinished()
|
220 |
{
|
221 |
if (!$this->pending && !$this->iterable->valid()) {
|
222 |
// Resolve the promise if there's nothing left to do.
|
223 |
$this->aggregate->resolve(null);
|
224 |
+
return true;
|
225 |
}
|
226 |
+
|
227 |
+
return false;
|
228 |
}
|
229 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* A promise that has been fulfilled.
|
@@ -8,26 +7,33 @@ namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
|
8 |
* Thenning off of this promise will invoke the onFulfilled callback
|
9 |
* immediately and ignore other callbacks.
|
10 |
*/
|
11 |
-
class FulfilledPromise implements
|
12 |
{
|
13 |
private $value;
|
|
|
14 |
public function __construct($value)
|
15 |
{
|
16 |
-
if (
|
17 |
-
throw new \InvalidArgumentException(
|
|
|
18 |
}
|
|
|
19 |
$this->value = $value;
|
20 |
}
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
23 |
// Return itself if there is no onFulfilled function.
|
24 |
if (!$onFulfilled) {
|
25 |
return $this;
|
26 |
}
|
|
|
27 |
$queue = queue();
|
28 |
-
$p = new
|
29 |
$value = $this->value;
|
30 |
-
$queue->add(static function () use($p, $value, $onFulfilled) {
|
31 |
if ($p->getState() === self::PENDING) {
|
32 |
try {
|
33 |
$p->resolve($onFulfilled($value));
|
@@ -38,30 +44,37 @@ class FulfilledPromise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Pr
|
|
38 |
}
|
39 |
}
|
40 |
});
|
|
|
41 |
return $p;
|
42 |
}
|
|
|
43 |
public function otherwise(callable $onRejected)
|
44 |
{
|
45 |
return $this->then(null, $onRejected);
|
46 |
}
|
47 |
-
|
|
|
48 |
{
|
49 |
return $unwrap ? $this->value : null;
|
50 |
}
|
|
|
51 |
public function getState()
|
52 |
{
|
53 |
return self::FULFILLED;
|
54 |
}
|
|
|
55 |
public function resolve($value)
|
56 |
{
|
57 |
if ($value !== $this->value) {
|
58 |
throw new \LogicException("Cannot resolve a fulfilled promise");
|
59 |
}
|
60 |
}
|
|
|
61 |
public function reject($reason)
|
62 |
{
|
63 |
throw new \LogicException("Cannot reject a fulfilled promise");
|
64 |
}
|
|
|
65 |
public function cancel()
|
66 |
{
|
67 |
// pass
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* A promise that has been fulfilled.
|
7 |
* Thenning off of this promise will invoke the onFulfilled callback
|
8 |
* immediately and ignore other callbacks.
|
9 |
*/
|
10 |
+
class FulfilledPromise implements PromiseInterface
|
11 |
{
|
12 |
private $value;
|
13 |
+
|
14 |
public function __construct($value)
|
15 |
{
|
16 |
+
if (method_exists($value, 'then')) {
|
17 |
+
throw new \InvalidArgumentException(
|
18 |
+
'You cannot create a FulfilledPromise with a promise.');
|
19 |
}
|
20 |
+
|
21 |
$this->value = $value;
|
22 |
}
|
23 |
+
|
24 |
+
public function then(
|
25 |
+
callable $onFulfilled = null,
|
26 |
+
callable $onRejected = null
|
27 |
+
) {
|
28 |
// Return itself if there is no onFulfilled function.
|
29 |
if (!$onFulfilled) {
|
30 |
return $this;
|
31 |
}
|
32 |
+
|
33 |
$queue = queue();
|
34 |
+
$p = new Promise([$queue, 'run']);
|
35 |
$value = $this->value;
|
36 |
+
$queue->add(static function () use ($p, $value, $onFulfilled) {
|
37 |
if ($p->getState() === self::PENDING) {
|
38 |
try {
|
39 |
$p->resolve($onFulfilled($value));
|
44 |
}
|
45 |
}
|
46 |
});
|
47 |
+
|
48 |
return $p;
|
49 |
}
|
50 |
+
|
51 |
public function otherwise(callable $onRejected)
|
52 |
{
|
53 |
return $this->then(null, $onRejected);
|
54 |
}
|
55 |
+
|
56 |
+
public function wait($unwrap = true, $defaultDelivery = null)
|
57 |
{
|
58 |
return $unwrap ? $this->value : null;
|
59 |
}
|
60 |
+
|
61 |
public function getState()
|
62 |
{
|
63 |
return self::FULFILLED;
|
64 |
}
|
65 |
+
|
66 |
public function resolve($value)
|
67 |
{
|
68 |
if ($value !== $this->value) {
|
69 |
throw new \LogicException("Cannot resolve a fulfilled promise");
|
70 |
}
|
71 |
}
|
72 |
+
|
73 |
public function reject($reason)
|
74 |
{
|
75 |
throw new \LogicException("Cannot reject a fulfilled promise");
|
76 |
}
|
77 |
+
|
78 |
public function cancel()
|
79 |
{
|
80 |
// pass
|
@@ -1,13 +1,12 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* Promises/A+ implementation that avoids recursion when possible.
|
7 |
*
|
8 |
* @link https://promisesaplus.com/
|
9 |
*/
|
10 |
-
class Promise implements
|
11 |
{
|
12 |
private $state = self::PENDING;
|
13 |
private $result;
|
@@ -15,43 +14,61 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
15 |
private $waitFn;
|
16 |
private $waitList;
|
17 |
private $handlers = [];
|
|
|
18 |
/**
|
19 |
* @param callable $waitFn Fn that when invoked resolves the promise.
|
20 |
* @param callable $cancelFn Fn that when invoked cancels the promise.
|
21 |
*/
|
22 |
-
public function __construct(
|
23 |
-
|
|
|
|
|
24 |
$this->waitFn = $waitFn;
|
25 |
$this->cancelFn = $cancelFn;
|
26 |
}
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
29 |
if ($this->state === self::PENDING) {
|
30 |
-
$p = new
|
31 |
$this->handlers[] = [$p, $onFulfilled, $onRejected];
|
32 |
$p->waitList = $this->waitList;
|
33 |
$p->waitList[] = $this;
|
34 |
return $p;
|
35 |
}
|
|
|
36 |
// Return a fulfilled promise and immediately invoke any callbacks.
|
37 |
if ($this->state === self::FULFILLED) {
|
38 |
-
return $onFulfilled
|
|
|
|
|
39 |
}
|
|
|
40 |
// It's either cancelled or rejected, so return a rejected promise
|
41 |
// and immediately invoke any callbacks.
|
42 |
$rejection = rejection_for($this->result);
|
43 |
return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
|
44 |
}
|
|
|
45 |
public function otherwise(callable $onRejected)
|
46 |
{
|
47 |
return $this->then(null, $onRejected);
|
48 |
}
|
49 |
-
|
|
|
50 |
{
|
51 |
$this->waitIfPending();
|
52 |
-
|
|
|
|
|
|
|
|
|
53 |
if ($unwrap) {
|
54 |
-
if ($this->result instanceof
|
|
|
|
|
55 |
return $inner;
|
56 |
} else {
|
57 |
// It's rejected so "unwrap" and throw an exception.
|
@@ -59,16 +76,20 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
59 |
}
|
60 |
}
|
61 |
}
|
|
|
62 |
public function getState()
|
63 |
{
|
64 |
return $this->state;
|
65 |
}
|
|
|
66 |
public function cancel()
|
67 |
{
|
68 |
if ($this->state !== self::PENDING) {
|
69 |
return;
|
70 |
}
|
|
|
71 |
$this->waitFn = $this->waitList = null;
|
|
|
72 |
if ($this->cancelFn) {
|
73 |
$fn = $this->cancelFn;
|
74 |
$this->cancelFn = null;
|
@@ -80,19 +101,23 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
80 |
$this->reject($e);
|
81 |
}
|
82 |
}
|
|
|
83 |
// Reject the promise only if it wasn't rejected in a then callback.
|
84 |
if ($this->state === self::PENDING) {
|
85 |
-
$this->reject(new
|
86 |
}
|
87 |
}
|
|
|
88 |
public function resolve($value)
|
89 |
{
|
90 |
$this->settle(self::FULFILLED, $value);
|
91 |
}
|
|
|
92 |
public function reject($reason)
|
93 |
{
|
94 |
$this->settle(self::REJECTED, $reason);
|
95 |
}
|
|
|
96 |
private function settle($state, $value)
|
97 |
{
|
98 |
if ($this->state !== self::PENDING) {
|
@@ -100,11 +125,15 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
100 |
if ($state === $this->state && $value === $this->result) {
|
101 |
return;
|
102 |
}
|
103 |
-
throw $this->state === $state
|
|
|
|
|
104 |
}
|
|
|
105 |
if ($value === $this) {
|
106 |
throw new \LogicException('Cannot fulfill or reject a promise with itself');
|
107 |
}
|
|
|
108 |
// Clear out the state of the promise but stash the handlers.
|
109 |
$this->state = $state;
|
110 |
$this->result = $value;
|
@@ -112,35 +141,43 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
112 |
$this->handlers = null;
|
113 |
$this->waitList = $this->waitFn = null;
|
114 |
$this->cancelFn = null;
|
|
|
115 |
if (!$handlers) {
|
116 |
return;
|
117 |
}
|
|
|
118 |
// If the value was not a settled promise or a thenable, then resolve
|
119 |
// it in the task queue using the correct ID.
|
120 |
-
if (
|
121 |
$id = $state === self::FULFILLED ? 1 : 2;
|
122 |
// It's a success, so resolve the handlers in the queue.
|
123 |
-
queue()->add(static function () use($id, $value, $handlers) {
|
124 |
foreach ($handlers as $handler) {
|
125 |
self::callHandler($id, $value, $handler);
|
126 |
}
|
127 |
});
|
128 |
-
} elseif ($value instanceof
|
|
|
|
|
129 |
// We can just merge our handlers onto the next promise.
|
130 |
-
$value->handlers =
|
131 |
} else {
|
132 |
// Resolve the handlers when the forwarded promise is resolved.
|
133 |
-
$value->then(
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
140 |
}
|
141 |
-
|
142 |
}
|
143 |
}
|
|
|
144 |
/**
|
145 |
* Call a stack of handlers using a specific callback index and value.
|
146 |
*
|
@@ -154,11 +191,13 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
154 |
{
|
155 |
/** @var PromiseInterface $promise */
|
156 |
$promise = $handler[0];
|
|
|
157 |
// The promise may have been cancelled or resolved before placing
|
158 |
// this thunk in the queue.
|
159 |
if ($promise->getState() !== self::PENDING) {
|
160 |
return;
|
161 |
}
|
|
|
162 |
try {
|
163 |
if (isset($handler[$index])) {
|
164 |
$promise->resolve($handler[$index]($value));
|
@@ -175,6 +214,7 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
175 |
$promise->reject($reason);
|
176 |
}
|
177 |
}
|
|
|
178 |
private function waitIfPending()
|
179 |
{
|
180 |
if ($this->state !== self::PENDING) {
|
@@ -185,19 +225,25 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
185 |
$this->invokeWaitList();
|
186 |
} else {
|
187 |
// If there's not wait function, then reject the promise.
|
188 |
-
$this->reject('Cannot wait on a promise that has '
|
|
|
|
|
|
|
189 |
}
|
|
|
190 |
queue()->run();
|
|
|
191 |
if ($this->state === self::PENDING) {
|
192 |
$this->reject('Invoking the wait callback did not resolve the promise');
|
193 |
}
|
194 |
}
|
|
|
195 |
private function invokeWaitFn()
|
196 |
{
|
197 |
try {
|
198 |
$wfn = $this->waitFn;
|
199 |
$this->waitFn = null;
|
200 |
-
$wfn(
|
201 |
} catch (\Exception $reason) {
|
202 |
if ($this->state === self::PENDING) {
|
203 |
// The promise has not been resolved yet, so reject the promise
|
@@ -210,18 +256,21 @@ class Promise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInte
|
|
210 |
}
|
211 |
}
|
212 |
}
|
|
|
213 |
private function invokeWaitList()
|
214 |
{
|
215 |
$waitList = $this->waitList;
|
216 |
$this->waitList = null;
|
|
|
217 |
foreach ($waitList as $result) {
|
218 |
-
while (
|
219 |
$result->waitIfPending();
|
220 |
-
|
|
|
221 |
$result = $result->result;
|
222 |
} else {
|
223 |
-
if ($result->result instanceof
|
224 |
-
$result->result->wait(
|
225 |
}
|
226 |
break;
|
227 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* Promises/A+ implementation that avoids recursion when possible.
|
6 |
*
|
7 |
* @link https://promisesaplus.com/
|
8 |
*/
|
9 |
+
class Promise implements PromiseInterface
|
10 |
{
|
11 |
private $state = self::PENDING;
|
12 |
private $result;
|
14 |
private $waitFn;
|
15 |
private $waitList;
|
16 |
private $handlers = [];
|
17 |
+
|
18 |
/**
|
19 |
* @param callable $waitFn Fn that when invoked resolves the promise.
|
20 |
* @param callable $cancelFn Fn that when invoked cancels the promise.
|
21 |
*/
|
22 |
+
public function __construct(
|
23 |
+
callable $waitFn = null,
|
24 |
+
callable $cancelFn = null
|
25 |
+
) {
|
26 |
$this->waitFn = $waitFn;
|
27 |
$this->cancelFn = $cancelFn;
|
28 |
}
|
29 |
+
|
30 |
+
public function then(
|
31 |
+
callable $onFulfilled = null,
|
32 |
+
callable $onRejected = null
|
33 |
+
) {
|
34 |
if ($this->state === self::PENDING) {
|
35 |
+
$p = new Promise(null, [$this, 'cancel']);
|
36 |
$this->handlers[] = [$p, $onFulfilled, $onRejected];
|
37 |
$p->waitList = $this->waitList;
|
38 |
$p->waitList[] = $this;
|
39 |
return $p;
|
40 |
}
|
41 |
+
|
42 |
// Return a fulfilled promise and immediately invoke any callbacks.
|
43 |
if ($this->state === self::FULFILLED) {
|
44 |
+
return $onFulfilled
|
45 |
+
? promise_for($this->result)->then($onFulfilled)
|
46 |
+
: promise_for($this->result);
|
47 |
}
|
48 |
+
|
49 |
// It's either cancelled or rejected, so return a rejected promise
|
50 |
// and immediately invoke any callbacks.
|
51 |
$rejection = rejection_for($this->result);
|
52 |
return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
|
53 |
}
|
54 |
+
|
55 |
public function otherwise(callable $onRejected)
|
56 |
{
|
57 |
return $this->then(null, $onRejected);
|
58 |
}
|
59 |
+
|
60 |
+
public function wait($unwrap = true)
|
61 |
{
|
62 |
$this->waitIfPending();
|
63 |
+
|
64 |
+
$inner = $this->result instanceof PromiseInterface
|
65 |
+
? $this->result->wait($unwrap)
|
66 |
+
: $this->result;
|
67 |
+
|
68 |
if ($unwrap) {
|
69 |
+
if ($this->result instanceof PromiseInterface
|
70 |
+
|| $this->state === self::FULFILLED
|
71 |
+
) {
|
72 |
return $inner;
|
73 |
} else {
|
74 |
// It's rejected so "unwrap" and throw an exception.
|
76 |
}
|
77 |
}
|
78 |
}
|
79 |
+
|
80 |
public function getState()
|
81 |
{
|
82 |
return $this->state;
|
83 |
}
|
84 |
+
|
85 |
public function cancel()
|
86 |
{
|
87 |
if ($this->state !== self::PENDING) {
|
88 |
return;
|
89 |
}
|
90 |
+
|
91 |
$this->waitFn = $this->waitList = null;
|
92 |
+
|
93 |
if ($this->cancelFn) {
|
94 |
$fn = $this->cancelFn;
|
95 |
$this->cancelFn = null;
|
101 |
$this->reject($e);
|
102 |
}
|
103 |
}
|
104 |
+
|
105 |
// Reject the promise only if it wasn't rejected in a then callback.
|
106 |
if ($this->state === self::PENDING) {
|
107 |
+
$this->reject(new CancellationException('Promise has been cancelled'));
|
108 |
}
|
109 |
}
|
110 |
+
|
111 |
public function resolve($value)
|
112 |
{
|
113 |
$this->settle(self::FULFILLED, $value);
|
114 |
}
|
115 |
+
|
116 |
public function reject($reason)
|
117 |
{
|
118 |
$this->settle(self::REJECTED, $reason);
|
119 |
}
|
120 |
+
|
121 |
private function settle($state, $value)
|
122 |
{
|
123 |
if ($this->state !== self::PENDING) {
|
125 |
if ($state === $this->state && $value === $this->result) {
|
126 |
return;
|
127 |
}
|
128 |
+
throw $this->state === $state
|
129 |
+
? new \LogicException("The promise is already {$state}.")
|
130 |
+
: new \LogicException("Cannot change a {$this->state} promise to {$state}");
|
131 |
}
|
132 |
+
|
133 |
if ($value === $this) {
|
134 |
throw new \LogicException('Cannot fulfill or reject a promise with itself');
|
135 |
}
|
136 |
+
|
137 |
// Clear out the state of the promise but stash the handlers.
|
138 |
$this->state = $state;
|
139 |
$this->result = $value;
|
141 |
$this->handlers = null;
|
142 |
$this->waitList = $this->waitFn = null;
|
143 |
$this->cancelFn = null;
|
144 |
+
|
145 |
if (!$handlers) {
|
146 |
return;
|
147 |
}
|
148 |
+
|
149 |
// If the value was not a settled promise or a thenable, then resolve
|
150 |
// it in the task queue using the correct ID.
|
151 |
+
if (!method_exists($value, 'then')) {
|
152 |
$id = $state === self::FULFILLED ? 1 : 2;
|
153 |
// It's a success, so resolve the handlers in the queue.
|
154 |
+
queue()->add(static function () use ($id, $value, $handlers) {
|
155 |
foreach ($handlers as $handler) {
|
156 |
self::callHandler($id, $value, $handler);
|
157 |
}
|
158 |
});
|
159 |
+
} elseif ($value instanceof Promise
|
160 |
+
&& $value->getState() === self::PENDING
|
161 |
+
) {
|
162 |
// We can just merge our handlers onto the next promise.
|
163 |
+
$value->handlers = array_merge($value->handlers, $handlers);
|
164 |
} else {
|
165 |
// Resolve the handlers when the forwarded promise is resolved.
|
166 |
+
$value->then(
|
167 |
+
static function ($value) use ($handlers) {
|
168 |
+
foreach ($handlers as $handler) {
|
169 |
+
self::callHandler(1, $value, $handler);
|
170 |
+
}
|
171 |
+
},
|
172 |
+
static function ($reason) use ($handlers) {
|
173 |
+
foreach ($handlers as $handler) {
|
174 |
+
self::callHandler(2, $reason, $handler);
|
175 |
+
}
|
176 |
}
|
177 |
+
);
|
178 |
}
|
179 |
}
|
180 |
+
|
181 |
/**
|
182 |
* Call a stack of handlers using a specific callback index and value.
|
183 |
*
|
191 |
{
|
192 |
/** @var PromiseInterface $promise */
|
193 |
$promise = $handler[0];
|
194 |
+
|
195 |
// The promise may have been cancelled or resolved before placing
|
196 |
// this thunk in the queue.
|
197 |
if ($promise->getState() !== self::PENDING) {
|
198 |
return;
|
199 |
}
|
200 |
+
|
201 |
try {
|
202 |
if (isset($handler[$index])) {
|
203 |
$promise->resolve($handler[$index]($value));
|
214 |
$promise->reject($reason);
|
215 |
}
|
216 |
}
|
217 |
+
|
218 |
private function waitIfPending()
|
219 |
{
|
220 |
if ($this->state !== self::PENDING) {
|
225 |
$this->invokeWaitList();
|
226 |
} else {
|
227 |
// If there's not wait function, then reject the promise.
|
228 |
+
$this->reject('Cannot wait on a promise that has '
|
229 |
+
. 'no internal wait function. You must provide a wait '
|
230 |
+
. 'function when constructing the promise to be able to '
|
231 |
+
. 'wait on a promise.');
|
232 |
}
|
233 |
+
|
234 |
queue()->run();
|
235 |
+
|
236 |
if ($this->state === self::PENDING) {
|
237 |
$this->reject('Invoking the wait callback did not resolve the promise');
|
238 |
}
|
239 |
}
|
240 |
+
|
241 |
private function invokeWaitFn()
|
242 |
{
|
243 |
try {
|
244 |
$wfn = $this->waitFn;
|
245 |
$this->waitFn = null;
|
246 |
+
$wfn(true);
|
247 |
} catch (\Exception $reason) {
|
248 |
if ($this->state === self::PENDING) {
|
249 |
// The promise has not been resolved yet, so reject the promise
|
256 |
}
|
257 |
}
|
258 |
}
|
259 |
+
|
260 |
private function invokeWaitList()
|
261 |
{
|
262 |
$waitList = $this->waitList;
|
263 |
$this->waitList = null;
|
264 |
+
|
265 |
foreach ($waitList as $result) {
|
266 |
+
while (true) {
|
267 |
$result->waitIfPending();
|
268 |
+
|
269 |
+
if ($result->result instanceof Promise) {
|
270 |
$result = $result->result;
|
271 |
} else {
|
272 |
+
if ($result->result instanceof PromiseInterface) {
|
273 |
+
$result->result->wait(false);
|
274 |
}
|
275 |
break;
|
276 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* A promise represents the eventual result of an asynchronous operation.
|
@@ -16,6 +15,7 @@ interface PromiseInterface
|
|
16 |
const PENDING = 'pending';
|
17 |
const FULFILLED = 'fulfilled';
|
18 |
const REJECTED = 'rejected';
|
|
|
19 |
/**
|
20 |
* Appends fulfillment and rejection handlers to the promise, and returns
|
21 |
* a new promise resolving to the return value of the called handler.
|
@@ -25,7 +25,11 @@ interface PromiseInterface
|
|
25 |
*
|
26 |
* @return PromiseInterface
|
27 |
*/
|
28 |
-
public function then(
|
|
|
|
|
|
|
|
|
29 |
/**
|
30 |
* Appends a rejection handler callback to the promise, and returns a new
|
31 |
* promise resolving to the return value of the callback if it is called,
|
@@ -37,6 +41,7 @@ interface PromiseInterface
|
|
37 |
* @return PromiseInterface
|
38 |
*/
|
39 |
public function otherwise(callable $onRejected);
|
|
|
40 |
/**
|
41 |
* Get the state of the promise ("pending", "rejected", or "fulfilled").
|
42 |
*
|
@@ -46,6 +51,7 @@ interface PromiseInterface
|
|
46 |
* @return string
|
47 |
*/
|
48 |
public function getState();
|
|
|
49 |
/**
|
50 |
* Resolve the promise with the given value.
|
51 |
*
|
@@ -53,6 +59,7 @@ interface PromiseInterface
|
|
53 |
* @throws \RuntimeException if the promise is already resolved.
|
54 |
*/
|
55 |
public function resolve($value);
|
|
|
56 |
/**
|
57 |
* Reject the promise with the given reason.
|
58 |
*
|
@@ -60,12 +67,14 @@ interface PromiseInterface
|
|
60 |
* @throws \RuntimeException if the promise is already resolved.
|
61 |
*/
|
62 |
public function reject($reason);
|
|
|
63 |
/**
|
64 |
* Cancels the promise if possible.
|
65 |
*
|
66 |
* @link https://github.com/promises-aplus/cancellation-spec/issues/7
|
67 |
*/
|
68 |
public function cancel();
|
|
|
69 |
/**
|
70 |
* Waits until the promise completes if possible.
|
71 |
*
|
@@ -80,5 +89,5 @@ interface PromiseInterface
|
|
80 |
* @throws \LogicException if the promise has no wait function or if the
|
81 |
* promise does not settle after waiting.
|
82 |
*/
|
83 |
-
public function wait($unwrap =
|
84 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* A promise represents the eventual result of an asynchronous operation.
|
15 |
const PENDING = 'pending';
|
16 |
const FULFILLED = 'fulfilled';
|
17 |
const REJECTED = 'rejected';
|
18 |
+
|
19 |
/**
|
20 |
* Appends fulfillment and rejection handlers to the promise, and returns
|
21 |
* a new promise resolving to the return value of the called handler.
|
25 |
*
|
26 |
* @return PromiseInterface
|
27 |
*/
|
28 |
+
public function then(
|
29 |
+
callable $onFulfilled = null,
|
30 |
+
callable $onRejected = null
|
31 |
+
);
|
32 |
+
|
33 |
/**
|
34 |
* Appends a rejection handler callback to the promise, and returns a new
|
35 |
* promise resolving to the return value of the callback if it is called,
|
41 |
* @return PromiseInterface
|
42 |
*/
|
43 |
public function otherwise(callable $onRejected);
|
44 |
+
|
45 |
/**
|
46 |
* Get the state of the promise ("pending", "rejected", or "fulfilled").
|
47 |
*
|
51 |
* @return string
|
52 |
*/
|
53 |
public function getState();
|
54 |
+
|
55 |
/**
|
56 |
* Resolve the promise with the given value.
|
57 |
*
|
59 |
* @throws \RuntimeException if the promise is already resolved.
|
60 |
*/
|
61 |
public function resolve($value);
|
62 |
+
|
63 |
/**
|
64 |
* Reject the promise with the given reason.
|
65 |
*
|
67 |
* @throws \RuntimeException if the promise is already resolved.
|
68 |
*/
|
69 |
public function reject($reason);
|
70 |
+
|
71 |
/**
|
72 |
* Cancels the promise if possible.
|
73 |
*
|
74 |
* @link https://github.com/promises-aplus/cancellation-spec/issues/7
|
75 |
*/
|
76 |
public function cancel();
|
77 |
+
|
78 |
/**
|
79 |
* Waits until the promise completes if possible.
|
80 |
*
|
89 |
* @throws \LogicException if the promise has no wait function or if the
|
90 |
* promise does not settle after waiting.
|
91 |
*/
|
92 |
+
public function wait($unwrap = true);
|
93 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* Interface used with classes that return a promise.
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* Interface used with classes that return a promise.
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* A promise that has been rejected.
|
@@ -8,26 +7,33 @@ namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
|
8 |
* Thenning off of this promise will invoke the onRejected callback
|
9 |
* immediately and ignore other callbacks.
|
10 |
*/
|
11 |
-
class RejectedPromise implements
|
12 |
{
|
13 |
private $reason;
|
|
|
14 |
public function __construct($reason)
|
15 |
{
|
16 |
-
if (
|
17 |
-
throw new \InvalidArgumentException(
|
|
|
18 |
}
|
|
|
19 |
$this->reason = $reason;
|
20 |
}
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
23 |
// If there's no onRejected callback then just return self.
|
24 |
if (!$onRejected) {
|
25 |
return $this;
|
26 |
}
|
|
|
27 |
$queue = queue();
|
28 |
$reason = $this->reason;
|
29 |
-
$p = new
|
30 |
-
$queue->add(static function () use($p, $reason, $onRejected) {
|
31 |
if ($p->getState() === self::PENDING) {
|
32 |
try {
|
33 |
// Return a resolved promise if onRejected does not throw.
|
@@ -41,32 +47,39 @@ class RejectedPromise implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\Pro
|
|
41 |
}
|
42 |
}
|
43 |
});
|
|
|
44 |
return $p;
|
45 |
}
|
|
|
46 |
public function otherwise(callable $onRejected)
|
47 |
{
|
48 |
return $this->then(null, $onRejected);
|
49 |
}
|
50 |
-
|
|
|
51 |
{
|
52 |
if ($unwrap) {
|
53 |
throw exception_for($this->reason);
|
54 |
}
|
55 |
}
|
|
|
56 |
public function getState()
|
57 |
{
|
58 |
return self::REJECTED;
|
59 |
}
|
|
|
60 |
public function resolve($value)
|
61 |
{
|
62 |
throw new \LogicException("Cannot resolve a rejected promise");
|
63 |
}
|
|
|
64 |
public function reject($reason)
|
65 |
{
|
66 |
if ($reason !== $this->reason) {
|
67 |
throw new \LogicException("Cannot reject a rejected promise");
|
68 |
}
|
69 |
}
|
|
|
70 |
public function cancel()
|
71 |
{
|
72 |
// pass
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* A promise that has been rejected.
|
7 |
* Thenning off of this promise will invoke the onRejected callback
|
8 |
* immediately and ignore other callbacks.
|
9 |
*/
|
10 |
+
class RejectedPromise implements PromiseInterface
|
11 |
{
|
12 |
private $reason;
|
13 |
+
|
14 |
public function __construct($reason)
|
15 |
{
|
16 |
+
if (method_exists($reason, 'then')) {
|
17 |
+
throw new \InvalidArgumentException(
|
18 |
+
'You cannot create a RejectedPromise with a promise.');
|
19 |
}
|
20 |
+
|
21 |
$this->reason = $reason;
|
22 |
}
|
23 |
+
|
24 |
+
public function then(
|
25 |
+
callable $onFulfilled = null,
|
26 |
+
callable $onRejected = null
|
27 |
+
) {
|
28 |
// If there's no onRejected callback then just return self.
|
29 |
if (!$onRejected) {
|
30 |
return $this;
|
31 |
}
|
32 |
+
|
33 |
$queue = queue();
|
34 |
$reason = $this->reason;
|
35 |
+
$p = new Promise([$queue, 'run']);
|
36 |
+
$queue->add(static function () use ($p, $reason, $onRejected) {
|
37 |
if ($p->getState() === self::PENDING) {
|
38 |
try {
|
39 |
// Return a resolved promise if onRejected does not throw.
|
47 |
}
|
48 |
}
|
49 |
});
|
50 |
+
|
51 |
return $p;
|
52 |
}
|
53 |
+
|
54 |
public function otherwise(callable $onRejected)
|
55 |
{
|
56 |
return $this->then(null, $onRejected);
|
57 |
}
|
58 |
+
|
59 |
+
public function wait($unwrap = true, $defaultDelivery = null)
|
60 |
{
|
61 |
if ($unwrap) {
|
62 |
throw exception_for($this->reason);
|
63 |
}
|
64 |
}
|
65 |
+
|
66 |
public function getState()
|
67 |
{
|
68 |
return self::REJECTED;
|
69 |
}
|
70 |
+
|
71 |
public function resolve($value)
|
72 |
{
|
73 |
throw new \LogicException("Cannot resolve a rejected promise");
|
74 |
}
|
75 |
+
|
76 |
public function reject($reason)
|
77 |
{
|
78 |
if ($reason !== $this->reason) {
|
79 |
throw new \LogicException("Cannot reject a rejected promise");
|
80 |
}
|
81 |
}
|
82 |
+
|
83 |
public function cancel()
|
84 |
{
|
85 |
// pass
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* A special exception that is thrown when waiting on a rejected promise.
|
@@ -11,6 +10,7 @@ class RejectionException extends \RuntimeException
|
|
11 |
{
|
12 |
/** @var mixed Rejection reason. */
|
13 |
private $reason;
|
|
|
14 |
/**
|
15 |
* @param mixed $reason Rejection reason.
|
16 |
* @param string $description Optional description
|
@@ -18,16 +18,23 @@ class RejectionException extends \RuntimeException
|
|
18 |
public function __construct($reason, $description = null)
|
19 |
{
|
20 |
$this->reason = $reason;
|
|
|
21 |
$message = 'The promise was rejected';
|
|
|
22 |
if ($description) {
|
23 |
$message .= ' with reason: ' . $description;
|
24 |
-
} elseif (
|
|
|
|
|
25 |
$message .= ' with reason: ' . $this->reason;
|
26 |
} elseif ($reason instanceof \JsonSerializable) {
|
27 |
-
$message .= ' with reason: '
|
|
|
28 |
}
|
|
|
29 |
parent::__construct($message);
|
30 |
}
|
|
|
31 |
/**
|
32 |
* Returns the rejection reason.
|
33 |
*
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* A special exception that is thrown when waiting on a rejected promise.
|
10 |
{
|
11 |
/** @var mixed Rejection reason. */
|
12 |
private $reason;
|
13 |
+
|
14 |
/**
|
15 |
* @param mixed $reason Rejection reason.
|
16 |
* @param string $description Optional description
|
18 |
public function __construct($reason, $description = null)
|
19 |
{
|
20 |
$this->reason = $reason;
|
21 |
+
|
22 |
$message = 'The promise was rejected';
|
23 |
+
|
24 |
if ($description) {
|
25 |
$message .= ' with reason: ' . $description;
|
26 |
+
} elseif (is_string($reason)
|
27 |
+
|| (is_object($reason) && method_exists($reason, '__toString'))
|
28 |
+
) {
|
29 |
$message .= ' with reason: ' . $this->reason;
|
30 |
} elseif ($reason instanceof \JsonSerializable) {
|
31 |
+
$message .= ' with reason: '
|
32 |
+
. json_encode($this->reason, JSON_PRETTY_PRINT);
|
33 |
}
|
34 |
+
|
35 |
parent::__construct($message);
|
36 |
}
|
37 |
+
|
38 |
/**
|
39 |
* Returns the rejection reason.
|
40 |
*
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* A task queue that executes tasks in a FIFO order.
|
@@ -11,39 +10,44 @@ namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
|
11 |
*
|
12 |
* GuzzleHttp\Promise\queue()->run();
|
13 |
*/
|
14 |
-
class TaskQueue implements
|
15 |
{
|
16 |
-
private $enableShutdown =
|
17 |
private $queue = [];
|
18 |
-
|
|
|
19 |
{
|
20 |
if ($withShutdown) {
|
21 |
-
|
22 |
if ($this->enableShutdown) {
|
23 |
// Only run the tasks if an E_ERROR didn't occur.
|
24 |
-
$err =
|
25 |
-
if (!$err || $err['type'] ^
|
26 |
$this->run();
|
27 |
}
|
28 |
}
|
29 |
});
|
30 |
}
|
31 |
}
|
|
|
32 |
public function isEmpty()
|
33 |
{
|
34 |
return !$this->queue;
|
35 |
}
|
|
|
36 |
public function add(callable $task)
|
37 |
{
|
38 |
$this->queue[] = $task;
|
39 |
}
|
|
|
40 |
public function run()
|
41 |
{
|
42 |
/** @var callable $task */
|
43 |
-
while ($task =
|
44 |
$task();
|
45 |
}
|
46 |
}
|
|
|
47 |
/**
|
48 |
* The task queue will be run and exhausted by default when the process
|
49 |
* exits IFF the exit is not the result of a PHP E_ERROR error.
|
@@ -57,6 +61,6 @@ class TaskQueue implements \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\TaskQueue
|
|
57 |
*/
|
58 |
public function disableShutdown()
|
59 |
{
|
60 |
-
$this->enableShutdown =
|
61 |
}
|
62 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* A task queue that executes tasks in a FIFO order.
|
10 |
*
|
11 |
* GuzzleHttp\Promise\queue()->run();
|
12 |
*/
|
13 |
+
class TaskQueue implements TaskQueueInterface
|
14 |
{
|
15 |
+
private $enableShutdown = true;
|
16 |
private $queue = [];
|
17 |
+
|
18 |
+
public function __construct($withShutdown = true)
|
19 |
{
|
20 |
if ($withShutdown) {
|
21 |
+
register_shutdown_function(function () {
|
22 |
if ($this->enableShutdown) {
|
23 |
// Only run the tasks if an E_ERROR didn't occur.
|
24 |
+
$err = error_get_last();
|
25 |
+
if (!$err || ($err['type'] ^ E_ERROR)) {
|
26 |
$this->run();
|
27 |
}
|
28 |
}
|
29 |
});
|
30 |
}
|
31 |
}
|
32 |
+
|
33 |
public function isEmpty()
|
34 |
{
|
35 |
return !$this->queue;
|
36 |
}
|
37 |
+
|
38 |
public function add(callable $task)
|
39 |
{
|
40 |
$this->queue[] = $task;
|
41 |
}
|
42 |
+
|
43 |
public function run()
|
44 |
{
|
45 |
/** @var callable $task */
|
46 |
+
while ($task = array_shift($this->queue)) {
|
47 |
$task();
|
48 |
}
|
49 |
}
|
50 |
+
|
51 |
/**
|
52 |
* The task queue will be run and exhausted by default when the process
|
53 |
* exits IFF the exit is not the result of a PHP E_ERROR error.
|
61 |
*/
|
62 |
public function disableShutdown()
|
63 |
{
|
64 |
+
$this->enableShutdown = false;
|
65 |
}
|
66 |
}
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
interface TaskQueueInterface
|
6 |
{
|
@@ -10,6 +9,7 @@ interface TaskQueueInterface
|
|
10 |
* @return bool
|
11 |
*/
|
12 |
public function isEmpty();
|
|
|
13 |
/**
|
14 |
* Adds a task to the queue that will be executed the next time run is
|
15 |
* called.
|
@@ -17,6 +17,7 @@ interface TaskQueueInterface
|
|
17 |
* @param callable $task
|
18 |
*/
|
19 |
public function add(callable $task);
|
|
|
20 |
/**
|
21 |
* Execute all of the pending task in the queue.
|
22 |
*/
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
interface TaskQueueInterface
|
5 |
{
|
9 |
* @return bool
|
10 |
*/
|
11 |
public function isEmpty();
|
12 |
+
|
13 |
/**
|
14 |
* Adds a task to the queue that will be executed the next time run is
|
15 |
* called.
|
17 |
* @param callable $task
|
18 |
*/
|
19 |
public function add(callable $task);
|
20 |
+
|
21 |
/**
|
22 |
* Execute all of the pending task in the queue.
|
23 |
*/
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
4 |
|
5 |
/**
|
6 |
* Get the global task queue used for promise resolution.
|
@@ -19,16 +18,19 @@ namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise;
|
|
19 |
*
|
20 |
* @return TaskQueueInterface
|
21 |
*/
|
22 |
-
function queue(
|
23 |
{
|
24 |
static $queue;
|
|
|
25 |
if ($assign) {
|
26 |
$queue = $assign;
|
27 |
} elseif (!$queue) {
|
28 |
-
$queue = new
|
29 |
}
|
|
|
30 |
return $queue;
|
31 |
}
|
|
|
32 |
/**
|
33 |
* Adds a function to run in the task queue when it is next `run()` and returns
|
34 |
* a promise that is fulfilled or rejected with the result.
|
@@ -40,8 +42,8 @@ function queue(\_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\TaskQueueInterface $a
|
|
40 |
function task(callable $task)
|
41 |
{
|
42 |
$queue = queue();
|
43 |
-
$promise = new
|
44 |
-
$queue->add(function () use($task, $promise) {
|
45 |
try {
|
46 |
$promise->resolve($task());
|
47 |
} catch (\Throwable $e) {
|
@@ -50,8 +52,10 @@ function task(callable $task)
|
|
50 |
$promise->reject($e);
|
51 |
}
|
52 |
});
|
|
|
53 |
return $promise;
|
54 |
}
|
|
|
55 |
/**
|
56 |
* Creates a promise for a value if the value is not a promise.
|
57 |
*
|
@@ -61,19 +65,22 @@ function task(callable $task)
|
|
61 |
*/
|
62 |
function promise_for($value)
|
63 |
{
|
64 |
-
if ($value instanceof
|
65 |
return $value;
|
66 |
}
|
|
|
67 |
// Return a Guzzle promise that shadows the given promise.
|
68 |
-
if (
|
69 |
-
$wfn =
|
70 |
-
$cfn =
|
71 |
-
$promise = new
|
72 |
$value->then([$promise, 'resolve'], [$promise, 'reject']);
|
73 |
return $promise;
|
74 |
}
|
75 |
-
|
|
|
76 |
}
|
|
|
77 |
/**
|
78 |
* Creates a rejected promise for a reason if the reason is not a promise. If
|
79 |
* the provided reason is a promise, then it is returned as-is.
|
@@ -84,11 +91,13 @@ function promise_for($value)
|
|
84 |
*/
|
85 |
function rejection_for($reason)
|
86 |
{
|
87 |
-
if ($reason instanceof
|
88 |
return $reason;
|
89 |
}
|
90 |
-
|
|
|
91 |
}
|
|
|
92 |
/**
|
93 |
* Create an exception for a rejected promise value.
|
94 |
*
|
@@ -98,8 +107,11 @@ function rejection_for($reason)
|
|
98 |
*/
|
99 |
function exception_for($reason)
|
100 |
{
|
101 |
-
return $reason instanceof \Exception || $reason instanceof \Throwable
|
|
|
|
|
102 |
}
|
|
|
103 |
/**
|
104 |
* Returns an iterator for the given value.
|
105 |
*
|
@@ -111,12 +123,13 @@ function iter_for($value)
|
|
111 |
{
|
112 |
if ($value instanceof \Iterator) {
|
113 |
return $value;
|
114 |
-
} elseif (
|
115 |
return new \ArrayIterator($value);
|
116 |
} else {
|
117 |
return new \ArrayIterator([$value]);
|
118 |
}
|
119 |
}
|
|
|
120 |
/**
|
121 |
* Synchronously waits on a promise to resolve and returns an inspection state
|
122 |
* array.
|
@@ -131,18 +144,22 @@ function iter_for($value)
|
|
131 |
*
|
132 |
* @return array
|
133 |
*/
|
134 |
-
function inspect(
|
135 |
{
|
136 |
try {
|
137 |
-
return [
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
140 |
} catch (\Throwable $e) {
|
141 |
-
return ['state' =>
|
142 |
} catch (\Exception $e) {
|
143 |
-
return ['state' =>
|
144 |
}
|
145 |
}
|
|
|
146 |
/**
|
147 |
* Waits on all of the provided promises, but does not unwrap rejected promises
|
148 |
* as thrown exception.
|
@@ -160,8 +177,10 @@ function inspect_all($promises)
|
|
160 |
foreach ($promises as $key => $promise) {
|
161 |
$results[$key] = inspect($promise);
|
162 |
}
|
|
|
163 |
return $results;
|
164 |
}
|
|
|
165 |
/**
|
166 |
* Waits on all of the provided promises and returns the fulfilled values.
|
167 |
*
|
@@ -181,8 +200,10 @@ function unwrap($promises)
|
|
181 |
foreach ($promises as $key => $promise) {
|
182 |
$results[$key] = $promise->wait();
|
183 |
}
|
|
|
184 |
return $results;
|
185 |
}
|
|
|
186 |
/**
|
187 |
* Given an array of promises, return a promise that is fulfilled when all the
|
188 |
* items in the array are fulfilled.
|
@@ -198,15 +219,20 @@ function unwrap($promises)
|
|
198 |
function all($promises)
|
199 |
{
|
200 |
$results = [];
|
201 |
-
return
|
202 |
-
$
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
|
|
|
|
|
|
|
|
207 |
return $results;
|
208 |
});
|
209 |
}
|
|
|
210 |
/**
|
211 |
* Initiate a competitive race between multiple promises or values (values will
|
212 |
* become immediately fulfilled promises).
|
@@ -227,24 +253,35 @@ function some($count, $promises)
|
|
227 |
{
|
228 |
$results = [];
|
229 |
$rejections = [];
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
243 |
}
|
244 |
-
|
245 |
-
return \array_values($results);
|
246 |
-
});
|
247 |
}
|
|
|
248 |
/**
|
249 |
* Like some(), with 1 as count. However, if the promise fulfills, the
|
250 |
* fulfillment value is not an array of 1 but the value directly.
|
@@ -255,10 +292,9 @@ function some($count, $promises)
|
|
255 |
*/
|
256 |
function any($promises)
|
257 |
{
|
258 |
-
return some(1, $promises)->then(function ($values) {
|
259 |
-
return $values[0];
|
260 |
-
});
|
261 |
}
|
|
|
262 |
/**
|
263 |
* Returns a promise that is fulfilled when all of the provided promises have
|
264 |
* been fulfilled or rejected.
|
@@ -273,15 +309,21 @@ function any($promises)
|
|
273 |
function settle($promises)
|
274 |
{
|
275 |
$results = [];
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
$
|
280 |
-
|
281 |
-
|
|
|
|
|
|
|
|
|
|
|
282 |
return $results;
|
283 |
});
|
284 |
}
|
|
|
285 |
/**
|
286 |
* Given an iterator that yields promises or values, returns a promise that is
|
287 |
* fulfilled with a null value when the iterator has been consumed or the
|
@@ -301,10 +343,17 @@ function settle($promises)
|
|
301 |
*
|
302 |
* @return PromiseInterface
|
303 |
*/
|
304 |
-
function each(
|
305 |
-
|
306 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
}
|
|
|
308 |
/**
|
309 |
* Like each, but only allows a certain number of outstanding promises at any
|
310 |
* given time.
|
@@ -320,10 +369,19 @@ function each($iterable, callable $onFulfilled = null, callable $onRejected = nu
|
|
320 |
*
|
321 |
* @return PromiseInterface
|
322 |
*/
|
323 |
-
function each_limit(
|
324 |
-
|
325 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
}
|
|
|
327 |
/**
|
328 |
* Like each_limit, but ensures that no promise in the given $iterable argument
|
329 |
* is rejected. If any promise is rejected, then the aggregate promise is
|
@@ -335,12 +393,21 @@ function each_limit($iterable, $concurrency, callable $onFulfilled = null, calla
|
|
335 |
*
|
336 |
* @return PromiseInterface
|
337 |
*/
|
338 |
-
function each_limit_all(
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
343 |
}
|
|
|
344 |
/**
|
345 |
* Returns true if a promise is fulfilled.
|
346 |
*
|
@@ -348,10 +415,11 @@ function each_limit_all($iterable, $concurrency, callable $onFulfilled = null)
|
|
348 |
*
|
349 |
* @return bool
|
350 |
*/
|
351 |
-
function is_fulfilled(
|
352 |
{
|
353 |
-
return $promise->getState() ===
|
354 |
}
|
|
|
355 |
/**
|
356 |
* Returns true if a promise is rejected.
|
357 |
*
|
@@ -359,10 +427,11 @@ function is_fulfilled(\_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterfa
|
|
359 |
*
|
360 |
* @return bool
|
361 |
*/
|
362 |
-
function is_rejected(
|
363 |
{
|
364 |
-
return $promise->getState() ===
|
365 |
}
|
|
|
366 |
/**
|
367 |
* Returns true if a promise is fulfilled or rejected.
|
368 |
*
|
@@ -370,10 +439,11 @@ function is_rejected(\_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterfac
|
|
370 |
*
|
371 |
* @return bool
|
372 |
*/
|
373 |
-
function is_settled(
|
374 |
{
|
375 |
-
return $promise->getState() !==
|
376 |
}
|
|
|
377 |
/**
|
378 |
* @see Coroutine
|
379 |
*
|
@@ -383,5 +453,5 @@ function is_settled(\_PhpScoper5bbb1f4b001f3\GuzzleHttp\Promise\PromiseInterface
|
|
383 |
*/
|
384 |
function coroutine(callable $generatorFn)
|
385 |
{
|
386 |
-
return new
|
387 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Promise;
|
|
|
3 |
|
4 |
/**
|
5 |
* Get the global task queue used for promise resolution.
|
18 |
*
|
19 |
* @return TaskQueueInterface
|
20 |
*/
|
21 |
+
function queue(TaskQueueInterface $assign = null)
|
22 |
{
|
23 |
static $queue;
|
24 |
+
|
25 |
if ($assign) {
|
26 |
$queue = $assign;
|
27 |
} elseif (!$queue) {
|
28 |
+
$queue = new TaskQueue();
|
29 |
}
|
30 |
+
|
31 |
return $queue;
|
32 |
}
|
33 |
+
|
34 |
/**
|
35 |
* Adds a function to run in the task queue when it is next `run()` and returns
|
36 |
* a promise that is fulfilled or rejected with the result.
|
42 |
function task(callable $task)
|
43 |
{
|
44 |
$queue = queue();
|
45 |
+
$promise = new Promise([$queue, 'run']);
|
46 |
+
$queue->add(function () use ($task, $promise) {
|
47 |
try {
|
48 |
$promise->resolve($task());
|
49 |
} catch (\Throwable $e) {
|
52 |
$promise->reject($e);
|
53 |
}
|
54 |
});
|
55 |
+
|
56 |
return $promise;
|
57 |
}
|
58 |
+
|
59 |
/**
|
60 |
* Creates a promise for a value if the value is not a promise.
|
61 |
*
|
65 |
*/
|
66 |
function promise_for($value)
|
67 |
{
|
68 |
+
if ($value instanceof PromiseInterface) {
|
69 |
return $value;
|
70 |
}
|
71 |
+
|
72 |
// Return a Guzzle promise that shadows the given promise.
|
73 |
+
if (method_exists($value, 'then')) {
|
74 |
+
$wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
|
75 |
+
$cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
|
76 |
+
$promise = new Promise($wfn, $cfn);
|
77 |
$value->then([$promise, 'resolve'], [$promise, 'reject']);
|
78 |
return $promise;
|
79 |
}
|
80 |
+
|
81 |
+
return new FulfilledPromise($value);
|
82 |
}
|
83 |
+
|
84 |
/**
|
85 |
* Creates a rejected promise for a reason if the reason is not a promise. If
|
86 |
* the provided reason is a promise, then it is returned as-is.
|
91 |
*/
|
92 |
function rejection_for($reason)
|
93 |
{
|
94 |
+
if ($reason instanceof PromiseInterface) {
|
95 |
return $reason;
|
96 |
}
|
97 |
+
|
98 |
+
return new RejectedPromise($reason);
|
99 |
}
|
100 |
+
|
101 |
/**
|
102 |
* Create an exception for a rejected promise value.
|
103 |
*
|
107 |
*/
|
108 |
function exception_for($reason)
|
109 |
{
|
110 |
+
return $reason instanceof \Exception || $reason instanceof \Throwable
|
111 |
+
? $reason
|
112 |
+
: new RejectionException($reason);
|
113 |
}
|
114 |
+
|
115 |
/**
|
116 |
* Returns an iterator for the given value.
|
117 |
*
|
123 |
{
|
124 |
if ($value instanceof \Iterator) {
|
125 |
return $value;
|
126 |
+
} elseif (is_array($value)) {
|
127 |
return new \ArrayIterator($value);
|
128 |
} else {
|
129 |
return new \ArrayIterator([$value]);
|
130 |
}
|
131 |
}
|
132 |
+
|
133 |
/**
|
134 |
* Synchronously waits on a promise to resolve and returns an inspection state
|
135 |
* array.
|
144 |
*
|
145 |
* @return array
|
146 |
*/
|
147 |
+
function inspect(PromiseInterface $promise)
|
148 |
{
|
149 |
try {
|
150 |
+
return [
|
151 |
+
'state' => PromiseInterface::FULFILLED,
|
152 |
+
'value' => $promise->wait()
|
153 |
+
];
|
154 |
+
} catch (RejectionException $e) {
|
155 |
+
return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
|
156 |
} catch (\Throwable $e) {
|
157 |
+
return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
|
158 |
} catch (\Exception $e) {
|
159 |
+
return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
|
160 |
}
|
161 |
}
|
162 |
+
|
163 |
/**
|
164 |
* Waits on all of the provided promises, but does not unwrap rejected promises
|
165 |
* as thrown exception.
|
177 |
foreach ($promises as $key => $promise) {
|
178 |
$results[$key] = inspect($promise);
|
179 |
}
|
180 |
+
|
181 |
return $results;
|
182 |
}
|
183 |
+
|
184 |
/**
|
185 |
* Waits on all of the provided promises and returns the fulfilled values.
|
186 |
*
|
200 |
foreach ($promises as $key => $promise) {
|
201 |
$results[$key] = $promise->wait();
|
202 |
}
|
203 |
+
|
204 |
return $results;
|
205 |
}
|
206 |
+
|
207 |
/**
|
208 |
* Given an array of promises, return a promise that is fulfilled when all the
|
209 |
* items in the array are fulfilled.
|
219 |
function all($promises)
|
220 |
{
|
221 |
$results = [];
|
222 |
+
return each(
|
223 |
+
$promises,
|
224 |
+
function ($value, $idx) use (&$results) {
|
225 |
+
$results[$idx] = $value;
|
226 |
+
},
|
227 |
+
function ($reason, $idx, Promise $aggregate) {
|
228 |
+
$aggregate->reject($reason);
|
229 |
+
}
|
230 |
+
)->then(function () use (&$results) {
|
231 |
+
ksort($results);
|
232 |
return $results;
|
233 |
});
|
234 |
}
|
235 |
+
|
236 |
/**
|
237 |
* Initiate a competitive race between multiple promises or values (values will
|
238 |
* become immediately fulfilled promises).
|
253 |
{
|
254 |
$results = [];
|
255 |
$rejections = [];
|
256 |
+
|
257 |
+
return each(
|
258 |
+
$promises,
|
259 |
+
function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
|
260 |
+
if ($p->getState() !== PromiseInterface::PENDING) {
|
261 |
+
return;
|
262 |
+
}
|
263 |
+
$results[$idx] = $value;
|
264 |
+
if (count($results) >= $count) {
|
265 |
+
$p->resolve(null);
|
266 |
+
}
|
267 |
+
},
|
268 |
+
function ($reason) use (&$rejections) {
|
269 |
+
$rejections[] = $reason;
|
270 |
}
|
271 |
+
)->then(
|
272 |
+
function () use (&$results, &$rejections, $count) {
|
273 |
+
if (count($results) !== $count) {
|
274 |
+
throw new AggregateException(
|
275 |
+
'Not enough promises to fulfill count',
|
276 |
+
$rejections
|
277 |
+
);
|
278 |
+
}
|
279 |
+
ksort($results);
|
280 |
+
return array_values($results);
|
281 |
}
|
282 |
+
);
|
|
|
|
|
283 |
}
|
284 |
+
|
285 |
/**
|
286 |
* Like some(), with 1 as count. However, if the promise fulfills, the
|
287 |
* fulfillment value is not an array of 1 but the value directly.
|
292 |
*/
|
293 |
function any($promises)
|
294 |
{
|
295 |
+
return some(1, $promises)->then(function ($values) { return $values[0]; });
|
|
|
|
|
296 |
}
|
297 |
+
|
298 |
/**
|
299 |
* Returns a promise that is fulfilled when all of the provided promises have
|
300 |
* been fulfilled or rejected.
|
309 |
function settle($promises)
|
310 |
{
|
311 |
$results = [];
|
312 |
+
|
313 |
+
return each(
|
314 |
+
$promises,
|
315 |
+
function ($value, $idx) use (&$results) {
|
316 |
+
$results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
|
317 |
+
},
|
318 |
+
function ($reason, $idx) use (&$results) {
|
319 |
+
$results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
|
320 |
+
}
|
321 |
+
)->then(function () use (&$results) {
|
322 |
+
ksort($results);
|
323 |
return $results;
|
324 |
});
|
325 |
}
|
326 |
+
|
327 |
/**
|
328 |
* Given an iterator that yields promises or values, returns a promise that is
|
329 |
* fulfilled with a null value when the iterator has been consumed or the
|
343 |
*
|
344 |
* @return PromiseInterface
|
345 |
*/
|
346 |
+
function each(
|
347 |
+
$iterable,
|
348 |
+
callable $onFulfilled = null,
|
349 |
+
callable $onRejected = null
|
350 |
+
) {
|
351 |
+
return (new EachPromise($iterable, [
|
352 |
+
'fulfilled' => $onFulfilled,
|
353 |
+
'rejected' => $onRejected
|
354 |
+
]))->promise();
|
355 |
}
|
356 |
+
|
357 |
/**
|
358 |
* Like each, but only allows a certain number of outstanding promises at any
|
359 |
* given time.
|
369 |
*
|
370 |
* @return PromiseInterface
|
371 |
*/
|
372 |
+
function each_limit(
|
373 |
+
$iterable,
|
374 |
+
$concurrency,
|
375 |
+
callable $onFulfilled = null,
|
376 |
+
callable $onRejected = null
|
377 |
+
) {
|
378 |
+
return (new EachPromise($iterable, [
|
379 |
+
'fulfilled' => $onFulfilled,
|
380 |
+
'rejected' => $onRejected,
|
381 |
+
'concurrency' => $concurrency
|
382 |
+
]))->promise();
|
383 |
}
|
384 |
+
|
385 |
/**
|
386 |
* Like each_limit, but ensures that no promise in the given $iterable argument
|
387 |
* is rejected. If any promise is rejected, then the aggregate promise is
|
393 |
*
|
394 |
* @return PromiseInterface
|
395 |
*/
|
396 |
+
function each_limit_all(
|
397 |
+
$iterable,
|
398 |
+
$concurrency,
|
399 |
+
callable $onFulfilled = null
|
400 |
+
) {
|
401 |
+
return each_limit(
|
402 |
+
$iterable,
|
403 |
+
$concurrency,
|
404 |
+
$onFulfilled,
|
405 |
+
function ($reason, $idx, PromiseInterface $aggregate) {
|
406 |
+
$aggregate->reject($reason);
|
407 |
+
}
|
408 |
+
);
|
409 |
}
|
410 |
+
|
411 |
/**
|
412 |
* Returns true if a promise is fulfilled.
|
413 |
*
|
415 |
*
|
416 |
* @return bool
|
417 |
*/
|
418 |
+
function is_fulfilled(PromiseInterface $promise)
|
419 |
{
|
420 |
+
return $promise->getState() === PromiseInterface::FULFILLED;
|
421 |
}
|
422 |
+
|
423 |
/**
|
424 |
* Returns true if a promise is rejected.
|
425 |
*
|
427 |
*
|
428 |
* @return bool
|
429 |
*/
|
430 |
+
function is_rejected(PromiseInterface $promise)
|
431 |
{
|
432 |
+
return $promise->getState() === PromiseInterface::REJECTED;
|
433 |
}
|
434 |
+
|
435 |
/**
|
436 |
* Returns true if a promise is fulfilled or rejected.
|
437 |
*
|
439 |
*
|
440 |
* @return bool
|
441 |
*/
|
442 |
+
function is_settled(PromiseInterface $promise)
|
443 |
{
|
444 |
+
return $promise->getState() !== PromiseInterface::PENDING;
|
445 |
}
|
446 |
+
|
447 |
/**
|
448 |
* @see Coroutine
|
449 |
*
|
453 |
*/
|
454 |
function coroutine(callable $generatorFn)
|
455 |
{
|
456 |
+
return new Coroutine($generatorFn);
|
457 |
}
|
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
// Don't redefine the functions if included multiple times.
|
6 |
-
if (
|
7 |
require __DIR__ . '/functions.php';
|
8 |
}
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
// Don't redefine the functions if included multiple times.
|
4 |
+
if (!function_exists('GuzzleHttp\Promise\promise_for')) {
|
5 |
require __DIR__ . '/functions.php';
|
6 |
}
|
@@ -1,49 +1,39 @@
|
|
1 |
{
|
2 |
-
"name": "guzzlehttp
|
3 |
"type": "library",
|
4 |
"description": "PSR-7 message implementation that also provides common utility methods",
|
5 |
-
"keywords": [
|
6 |
-
"request",
|
7 |
-
"response",
|
8 |
-
"message",
|
9 |
-
"stream",
|
10 |
-
"http",
|
11 |
-
"uri",
|
12 |
-
"url"
|
13 |
-
],
|
14 |
"license": "MIT",
|
15 |
"authors": [
|
16 |
{
|
17 |
"name": "Michael Dowling",
|
18 |
"email": "mtdowling@gmail.com",
|
19 |
-
"homepage": "https
|
20 |
},
|
21 |
{
|
22 |
"name": "Tobias Schultze",
|
23 |
-
"homepage": "https
|
24 |
}
|
25 |
],
|
26 |
"require": {
|
27 |
"php": ">=5.4.0",
|
28 |
-
"psr
|
29 |
},
|
30 |
"require-dev": {
|
31 |
-
"phpunit
|
32 |
},
|
33 |
"provide": {
|
34 |
-
"psr
|
35 |
},
|
36 |
"autoload": {
|
37 |
"psr-4": {
|
38 |
-
"
|
39 |
},
|
40 |
-
"files": [
|
41 |
-
"src\/functions_include.php"
|
42 |
-
]
|
43 |
},
|
44 |
"extra": {
|
45 |
"branch-alias": {
|
46 |
"dev-master": "1.4-dev"
|
47 |
}
|
48 |
}
|
49 |
-
}
|
1 |
{
|
2 |
+
"name": "guzzlehttp/psr7",
|
3 |
"type": "library",
|
4 |
"description": "PSR-7 message implementation that also provides common utility methods",
|
5 |
+
"keywords": ["request", "response", "message", "stream", "http", "uri", "url"],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
8 |
{
|
9 |
"name": "Michael Dowling",
|
10 |
"email": "mtdowling@gmail.com",
|
11 |
+
"homepage": "https://github.com/mtdowling"
|
12 |
},
|
13 |
{
|
14 |
"name": "Tobias Schultze",
|
15 |
+
"homepage": "https://github.com/Tobion"
|
16 |
}
|
17 |
],
|
18 |
"require": {
|
19 |
"php": ">=5.4.0",
|
20 |
+
"psr/http-message": "~1.0"
|
21 |
},
|
22 |
"require-dev": {
|
23 |
+
"phpunit/phpunit": "~4.0"
|
24 |
},
|
25 |
"provide": {
|
26 |
+
"psr/http-message-implementation": "1.0"
|
27 |
},
|
28 |
"autoload": {
|
29 |
"psr-4": {
|
30 |
+
"GuzzleHttp\\Psr7\\": "src/"
|
31 |
},
|
32 |
+
"files": ["src/functions_include.php"]
|
|
|
|
|
33 |
},
|
34 |
"extra": {
|
35 |
"branch-alias": {
|
36 |
"dev-master": "1.4-dev"
|
37 |
}
|
38 |
}
|
39 |
+
}
|
@@ -1,21 +1,23 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Reads from multiple streams, one after the other.
|
8 |
*
|
9 |
* This is a read-only stream decorator.
|
10 |
*/
|
11 |
-
class AppendStream implements
|
12 |
{
|
13 |
/** @var StreamInterface[] Streams being decorated */
|
14 |
private $streams = [];
|
15 |
-
|
|
|
16 |
private $current = 0;
|
17 |
private $pos = 0;
|
18 |
-
private $detached =
|
|
|
19 |
/**
|
20 |
* @param StreamInterface[] $streams Streams to decorate. Each stream must
|
21 |
* be readable.
|
@@ -26,6 +28,7 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
26 |
$this->addStream($stream);
|
27 |
}
|
28 |
}
|
|
|
29 |
public function __toString()
|
30 |
{
|
31 |
try {
|
@@ -35,6 +38,7 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
35 |
return '';
|
36 |
}
|
37 |
}
|
|
|
38 |
/**
|
39 |
* Add a stream to the AppendStream
|
40 |
*
|
@@ -42,21 +46,25 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
42 |
*
|
43 |
* @throws \InvalidArgumentException if the stream is not readable
|
44 |
*/
|
45 |
-
public function addStream(
|
46 |
{
|
47 |
if (!$stream->isReadable()) {
|
48 |
throw new \InvalidArgumentException('Each stream must be readable');
|
49 |
}
|
|
|
50 |
// The stream is only seekable if all streams are seekable
|
51 |
if (!$stream->isSeekable()) {
|
52 |
-
$this->seekable =
|
53 |
}
|
|
|
54 |
$this->streams[] = $stream;
|
55 |
}
|
|
|
56 |
public function getContents()
|
57 |
{
|
58 |
return copy_to_string($this);
|
59 |
}
|
|
|
60 |
/**
|
61 |
* Closes each attached stream.
|
62 |
*
|
@@ -65,11 +73,14 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
65 |
public function close()
|
66 |
{
|
67 |
$this->pos = $this->current = 0;
|
|
|
68 |
foreach ($this->streams as $stream) {
|
69 |
$stream->close();
|
70 |
}
|
|
|
71 |
$this->streams = [];
|
72 |
}
|
|
|
73 |
/**
|
74 |
* Detaches each attached stream
|
75 |
*
|
@@ -78,12 +89,14 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
78 |
public function detach()
|
79 |
{
|
80 |
$this->close();
|
81 |
-
$this->detached =
|
82 |
}
|
|
|
83 |
public function tell()
|
84 |
{
|
85 |
return $this->pos;
|
86 |
}
|
|
|
87 |
/**
|
88 |
* Tries to calculate the size by adding the size of each stream.
|
89 |
*
|
@@ -95,6 +108,7 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
95 |
public function getSize()
|
96 |
{
|
97 |
$size = 0;
|
|
|
98 |
foreach ($this->streams as $stream) {
|
99 |
$s = $stream->getSize();
|
100 |
if ($s === null) {
|
@@ -102,45 +116,56 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
102 |
}
|
103 |
$size += $s;
|
104 |
}
|
|
|
105 |
return $size;
|
106 |
}
|
|
|
107 |
public function eof()
|
108 |
{
|
109 |
-
return !$this->streams ||
|
|
|
|
|
110 |
}
|
|
|
111 |
public function rewind()
|
112 |
{
|
113 |
$this->seek(0);
|
114 |
}
|
|
|
115 |
/**
|
116 |
* Attempts to seek to the given position. Only supports SEEK_SET.
|
117 |
*
|
118 |
* {@inheritdoc}
|
119 |
*/
|
120 |
-
public function seek($offset, $whence =
|
121 |
{
|
122 |
if (!$this->seekable) {
|
123 |
throw new \RuntimeException('This AppendStream is not seekable');
|
124 |
-
} elseif ($whence !==
|
125 |
throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
|
126 |
}
|
|
|
127 |
$this->pos = $this->current = 0;
|
|
|
128 |
// Rewind each stream
|
129 |
foreach ($this->streams as $i => $stream) {
|
130 |
try {
|
131 |
$stream->rewind();
|
132 |
} catch (\Exception $e) {
|
133 |
-
throw new \RuntimeException('Unable to seek stream '
|
|
|
134 |
}
|
135 |
}
|
|
|
136 |
// Seek to the actual position by reading from each stream
|
137 |
while ($this->pos < $offset && !$this->eof()) {
|
138 |
-
$result = $this->read(
|
139 |
if ($result === '') {
|
140 |
break;
|
141 |
}
|
142 |
}
|
143 |
}
|
|
|
144 |
/**
|
145 |
* Reads from all of the appended streams until the length is met or EOF.
|
146 |
*
|
@@ -149,46 +174,58 @@ class AppendStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
149 |
public function read($length)
|
150 |
{
|
151 |
$buffer = '';
|
152 |
-
$total =
|
153 |
$remaining = $length;
|
154 |
-
$progressToNext =
|
|
|
155 |
while ($remaining > 0) {
|
|
|
156 |
// Progress to the next stream if needed.
|
157 |
if ($progressToNext || $this->streams[$this->current]->eof()) {
|
158 |
-
$progressToNext =
|
159 |
if ($this->current === $total) {
|
160 |
break;
|
161 |
}
|
162 |
$this->current++;
|
163 |
}
|
|
|
164 |
$result = $this->streams[$this->current]->read($remaining);
|
|
|
165 |
// Using a loose comparison here to match on '', false, and null
|
166 |
if ($result == null) {
|
167 |
-
$progressToNext =
|
168 |
continue;
|
169 |
}
|
|
|
170 |
$buffer .= $result;
|
171 |
-
$remaining = $length -
|
172 |
}
|
173 |
-
|
|
|
|
|
174 |
return $buffer;
|
175 |
}
|
|
|
176 |
public function isReadable()
|
177 |
{
|
178 |
-
return
|
179 |
}
|
|
|
180 |
public function isWritable()
|
181 |
{
|
182 |
-
return
|
183 |
}
|
|
|
184 |
public function isSeekable()
|
185 |
{
|
186 |
return $this->seekable;
|
187 |
}
|
|
|
188 |
public function write($string)
|
189 |
{
|
190 |
throw new \RuntimeException('Cannot write to an AppendStream');
|
191 |
}
|
|
|
192 |
public function getMetadata($key = null)
|
193 |
{
|
194 |
return $key ? null : [];
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Reads from multiple streams, one after the other.
|
8 |
*
|
9 |
* This is a read-only stream decorator.
|
10 |
*/
|
11 |
+
class AppendStream implements StreamInterface
|
12 |
{
|
13 |
/** @var StreamInterface[] Streams being decorated */
|
14 |
private $streams = [];
|
15 |
+
|
16 |
+
private $seekable = true;
|
17 |
private $current = 0;
|
18 |
private $pos = 0;
|
19 |
+
private $detached = false;
|
20 |
+
|
21 |
/**
|
22 |
* @param StreamInterface[] $streams Streams to decorate. Each stream must
|
23 |
* be readable.
|
28 |
$this->addStream($stream);
|
29 |
}
|
30 |
}
|
31 |
+
|
32 |
public function __toString()
|
33 |
{
|
34 |
try {
|
38 |
return '';
|
39 |
}
|
40 |
}
|
41 |
+
|
42 |
/**
|
43 |
* Add a stream to the AppendStream
|
44 |
*
|
46 |
*
|
47 |
* @throws \InvalidArgumentException if the stream is not readable
|
48 |
*/
|
49 |
+
public function addStream(StreamInterface $stream)
|
50 |
{
|
51 |
if (!$stream->isReadable()) {
|
52 |
throw new \InvalidArgumentException('Each stream must be readable');
|
53 |
}
|
54 |
+
|
55 |
// The stream is only seekable if all streams are seekable
|
56 |
if (!$stream->isSeekable()) {
|
57 |
+
$this->seekable = false;
|
58 |
}
|
59 |
+
|
60 |
$this->streams[] = $stream;
|
61 |
}
|
62 |
+
|
63 |
public function getContents()
|
64 |
{
|
65 |
return copy_to_string($this);
|
66 |
}
|
67 |
+
|
68 |
/**
|
69 |
* Closes each attached stream.
|
70 |
*
|
73 |
public function close()
|
74 |
{
|
75 |
$this->pos = $this->current = 0;
|
76 |
+
|
77 |
foreach ($this->streams as $stream) {
|
78 |
$stream->close();
|
79 |
}
|
80 |
+
|
81 |
$this->streams = [];
|
82 |
}
|
83 |
+
|
84 |
/**
|
85 |
* Detaches each attached stream
|
86 |
*
|
89 |
public function detach()
|
90 |
{
|
91 |
$this->close();
|
92 |
+
$this->detached = true;
|
93 |
}
|
94 |
+
|
95 |
public function tell()
|
96 |
{
|
97 |
return $this->pos;
|
98 |
}
|
99 |
+
|
100 |
/**
|
101 |
* Tries to calculate the size by adding the size of each stream.
|
102 |
*
|
108 |
public function getSize()
|
109 |
{
|
110 |
$size = 0;
|
111 |
+
|
112 |
foreach ($this->streams as $stream) {
|
113 |
$s = $stream->getSize();
|
114 |
if ($s === null) {
|
116 |
}
|
117 |
$size += $s;
|
118 |
}
|
119 |
+
|
120 |
return $size;
|
121 |
}
|
122 |
+
|
123 |
public function eof()
|
124 |
{
|
125 |
+
return !$this->streams ||
|
126 |
+
($this->current >= count($this->streams) - 1 &&
|
127 |
+
$this->streams[$this->current]->eof());
|
128 |
}
|
129 |
+
|
130 |
public function rewind()
|
131 |
{
|
132 |
$this->seek(0);
|
133 |
}
|
134 |
+
|
135 |
/**
|
136 |
* Attempts to seek to the given position. Only supports SEEK_SET.
|
137 |
*
|
138 |
* {@inheritdoc}
|
139 |
*/
|
140 |
+
public function seek($offset, $whence = SEEK_SET)
|
141 |
{
|
142 |
if (!$this->seekable) {
|
143 |
throw new \RuntimeException('This AppendStream is not seekable');
|
144 |
+
} elseif ($whence !== SEEK_SET) {
|
145 |
throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
|
146 |
}
|
147 |
+
|
148 |
$this->pos = $this->current = 0;
|
149 |
+
|
150 |
// Rewind each stream
|
151 |
foreach ($this->streams as $i => $stream) {
|
152 |
try {
|
153 |
$stream->rewind();
|
154 |
} catch (\Exception $e) {
|
155 |
+
throw new \RuntimeException('Unable to seek stream '
|
156 |
+
. $i . ' of the AppendStream', 0, $e);
|
157 |
}
|
158 |
}
|
159 |
+
|
160 |
// Seek to the actual position by reading from each stream
|
161 |
while ($this->pos < $offset && !$this->eof()) {
|
162 |
+
$result = $this->read(min(8096, $offset - $this->pos));
|
163 |
if ($result === '') {
|
164 |
break;
|
165 |
}
|
166 |
}
|
167 |
}
|
168 |
+
|
169 |
/**
|
170 |
* Reads from all of the appended streams until the length is met or EOF.
|
171 |
*
|
174 |
public function read($length)
|
175 |
{
|
176 |
$buffer = '';
|
177 |
+
$total = count($this->streams) - 1;
|
178 |
$remaining = $length;
|
179 |
+
$progressToNext = false;
|
180 |
+
|
181 |
while ($remaining > 0) {
|
182 |
+
|
183 |
// Progress to the next stream if needed.
|
184 |
if ($progressToNext || $this->streams[$this->current]->eof()) {
|
185 |
+
$progressToNext = false;
|
186 |
if ($this->current === $total) {
|
187 |
break;
|
188 |
}
|
189 |
$this->current++;
|
190 |
}
|
191 |
+
|
192 |
$result = $this->streams[$this->current]->read($remaining);
|
193 |
+
|
194 |
// Using a loose comparison here to match on '', false, and null
|
195 |
if ($result == null) {
|
196 |
+
$progressToNext = true;
|
197 |
continue;
|
198 |
}
|
199 |
+
|
200 |
$buffer .= $result;
|
201 |
+
$remaining = $length - strlen($buffer);
|
202 |
}
|
203 |
+
|
204 |
+
$this->pos += strlen($buffer);
|
205 |
+
|
206 |
return $buffer;
|
207 |
}
|
208 |
+
|
209 |
public function isReadable()
|
210 |
{
|
211 |
+
return true;
|
212 |
}
|
213 |
+
|
214 |
public function isWritable()
|
215 |
{
|
216 |
+
return false;
|
217 |
}
|
218 |
+
|
219 |
public function isSeekable()
|
220 |
{
|
221 |
return $this->seekable;
|
222 |
}
|
223 |
+
|
224 |
public function write($string)
|
225 |
{
|
226 |
throw new \RuntimeException('Cannot write to an AppendStream');
|
227 |
}
|
228 |
+
|
229 |
public function getMetadata($key = null)
|
230 |
{
|
231 |
return $key ? null : [];
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Provides a buffer stream that can be written to to fill a buffer, and read
|
8 |
* from to remove bytes from the buffer.
|
@@ -11,10 +11,11 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
|
11 |
* what the configured high water mark of the stream is, or the maximum
|
12 |
* preferred size of the buffer.
|
13 |
*/
|
14 |
-
class BufferStream implements
|
15 |
{
|
16 |
private $hwm;
|
17 |
private $buffer = '';
|
|
|
18 |
/**
|
19 |
* @param int $hwm High water mark, representing the preferred maximum
|
20 |
* buffer size. If the size of the buffer exceeds the high
|
@@ -26,90 +27,111 @@ class BufferStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamIn
|
|
26 |
{
|
27 |
$this->hwm = $hwm;
|
28 |
}
|
|
|
29 |
public function __toString()
|
30 |
{
|
31 |
return $this->getContents();
|
32 |
}
|
|
|
33 |
public function getContents()
|
34 |
{
|
35 |
$buffer = $this->buffer;
|
36 |
$this->buffer = '';
|
|
|
37 |
return $buffer;
|
38 |
}
|
|
|
39 |
public function close()
|
40 |
{
|
41 |
$this->buffer = '';
|
42 |
}
|
|
|
43 |
public function detach()
|
44 |
{
|
45 |
$this->close();
|
46 |
}
|
|
|
47 |
public function getSize()
|
48 |
{
|
49 |
-
return
|
50 |
}
|
|
|
51 |
public function isReadable()
|
52 |
{
|
53 |
-
return
|
54 |
}
|
|
|
55 |
public function isWritable()
|
56 |
{
|
57 |
-
return
|
58 |
}
|
|
|
59 |
public function isSeekable()
|
60 |
{
|
61 |
-
return
|
62 |
}
|
|
|
63 |
public function rewind()
|
64 |
{
|
65 |
$this->seek(0);
|
66 |
}
|
67 |
-
|
|
|
68 |
{
|
69 |
throw new \RuntimeException('Cannot seek a BufferStream');
|
70 |
}
|
|
|
71 |
public function eof()
|
72 |
{
|
73 |
-
return
|
74 |
}
|
|
|
75 |
public function tell()
|
76 |
{
|
77 |
throw new \RuntimeException('Cannot determine the position of a BufferStream');
|
78 |
}
|
|
|
79 |
/**
|
80 |
* Reads data from the buffer.
|
81 |
*/
|
82 |
public function read($length)
|
83 |
{
|
84 |
-
$currentLength =
|
|
|
85 |
if ($length >= $currentLength) {
|
86 |
// No need to slice the buffer because we don't have enough data.
|
87 |
$result = $this->buffer;
|
88 |
$this->buffer = '';
|
89 |
} else {
|
90 |
// Slice up the result to provide a subset of the buffer.
|
91 |
-
$result =
|
92 |
-
$this->buffer =
|
93 |
}
|
|
|
94 |
return $result;
|
95 |
}
|
|
|
96 |
/**
|
97 |
* Writes data to the buffer.
|
98 |
*/
|
99 |
public function write($string)
|
100 |
{
|
101 |
$this->buffer .= $string;
|
|
|
102 |
// TODO: What should happen here?
|
103 |
-
if (
|
104 |
-
return
|
105 |
}
|
106 |
-
|
|
|
107 |
}
|
|
|
108 |
public function getMetadata($key = null)
|
109 |
{
|
110 |
if ($key == 'hwm') {
|
111 |
return $this->hwm;
|
112 |
}
|
|
|
113 |
return $key ? null : [];
|
114 |
}
|
115 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Provides a buffer stream that can be written to to fill a buffer, and read
|
8 |
* from to remove bytes from the buffer.
|
11 |
* what the configured high water mark of the stream is, or the maximum
|
12 |
* preferred size of the buffer.
|
13 |
*/
|
14 |
+
class BufferStream implements StreamInterface
|
15 |
{
|
16 |
private $hwm;
|
17 |
private $buffer = '';
|
18 |
+
|
19 |
/**
|
20 |
* @param int $hwm High water mark, representing the preferred maximum
|
21 |
* buffer size. If the size of the buffer exceeds the high
|
27 |
{
|
28 |
$this->hwm = $hwm;
|
29 |
}
|
30 |
+
|
31 |
public function __toString()
|
32 |
{
|
33 |
return $this->getContents();
|
34 |
}
|
35 |
+
|
36 |
public function getContents()
|
37 |
{
|
38 |
$buffer = $this->buffer;
|
39 |
$this->buffer = '';
|
40 |
+
|
41 |
return $buffer;
|
42 |
}
|
43 |
+
|
44 |
public function close()
|
45 |
{
|
46 |
$this->buffer = '';
|
47 |
}
|
48 |
+
|
49 |
public function detach()
|
50 |
{
|
51 |
$this->close();
|
52 |
}
|
53 |
+
|
54 |
public function getSize()
|
55 |
{
|
56 |
+
return strlen($this->buffer);
|
57 |
}
|
58 |
+
|
59 |
public function isReadable()
|
60 |
{
|
61 |
+
return true;
|
62 |
}
|
63 |
+
|
64 |
public function isWritable()
|
65 |
{
|
66 |
+
return true;
|
67 |
}
|
68 |
+
|
69 |
public function isSeekable()
|
70 |
{
|
71 |
+
return false;
|
72 |
}
|
73 |
+
|
74 |
public function rewind()
|
75 |
{
|
76 |
$this->seek(0);
|
77 |
}
|
78 |
+
|
79 |
+
public function seek($offset, $whence = SEEK_SET)
|
80 |
{
|
81 |
throw new \RuntimeException('Cannot seek a BufferStream');
|
82 |
}
|
83 |
+
|
84 |
public function eof()
|
85 |
{
|
86 |
+
return strlen($this->buffer) === 0;
|
87 |
}
|
88 |
+
|
89 |
public function tell()
|
90 |
{
|
91 |
throw new \RuntimeException('Cannot determine the position of a BufferStream');
|
92 |
}
|
93 |
+
|
94 |
/**
|
95 |
* Reads data from the buffer.
|
96 |
*/
|
97 |
public function read($length)
|
98 |
{
|
99 |
+
$currentLength = strlen($this->buffer);
|
100 |
+
|
101 |
if ($length >= $currentLength) {
|
102 |
// No need to slice the buffer because we don't have enough data.
|
103 |
$result = $this->buffer;
|
104 |
$this->buffer = '';
|
105 |
} else {
|
106 |
// Slice up the result to provide a subset of the buffer.
|
107 |
+
$result = substr($this->buffer, 0, $length);
|
108 |
+
$this->buffer = substr($this->buffer, $length);
|
109 |
}
|
110 |
+
|
111 |
return $result;
|
112 |
}
|
113 |
+
|
114 |
/**
|
115 |
* Writes data to the buffer.
|
116 |
*/
|
117 |
public function write($string)
|
118 |
{
|
119 |
$this->buffer .= $string;
|
120 |
+
|
121 |
// TODO: What should happen here?
|
122 |
+
if (strlen($this->buffer) >= $this->hwm) {
|
123 |
+
return false;
|
124 |
}
|
125 |
+
|
126 |
+
return strlen($string);
|
127 |
}
|
128 |
+
|
129 |
public function getMetadata($key = null)
|
130 |
{
|
131 |
if ($key == 'hwm') {
|
132 |
return $this->hwm;
|
133 |
}
|
134 |
+
|
135 |
return $key ? null : [];
|
136 |
}
|
137 |
}
|
@@ -1,45 +1,53 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Stream decorator that can cache previously read bytes from a sequentially
|
8 |
* read stream.
|
9 |
*/
|
10 |
-
class CachingStream implements
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
|
|
13 |
/** @var StreamInterface Stream being wrapped */
|
14 |
private $remoteStream;
|
|
|
15 |
/** @var int Number of bytes to skip reading due to a write on the buffer */
|
16 |
private $skipReadBytes = 0;
|
|
|
17 |
/**
|
18 |
* We will treat the buffer object as the body of the stream
|
19 |
*
|
20 |
* @param StreamInterface $stream Stream to cache
|
21 |
* @param StreamInterface $target Optionally specify where data is cached
|
22 |
*/
|
23 |
-
public function __construct(
|
24 |
-
|
|
|
|
|
25 |
$this->remoteStream = $stream;
|
26 |
-
$this->stream = $target ?: new
|
27 |
}
|
|
|
28 |
public function getSize()
|
29 |
{
|
30 |
-
return
|
31 |
}
|
|
|
32 |
public function rewind()
|
33 |
{
|
34 |
$this->seek(0);
|
35 |
}
|
36 |
-
|
|
|
37 |
{
|
38 |
-
if ($whence ==
|
39 |
$byte = $offset;
|
40 |
-
} elseif ($whence ==
|
41 |
$byte = $offset + $this->tell();
|
42 |
-
} elseif ($whence ==
|
43 |
$size = $this->remoteStream->getSize();
|
44 |
if ($size === null) {
|
45 |
$size = $this->cacheEntireStream();
|
@@ -48,7 +56,9 @@ class CachingStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamI
|
|
48 |
} else {
|
49 |
throw new \InvalidArgumentException('Invalid whence');
|
50 |
}
|
|
|
51 |
$diff = $byte - $this->stream->getSize();
|
|
|
52 |
if ($diff > 0) {
|
53 |
// Read the remoteStream until we have read in at least the amount
|
54 |
// of bytes requested, or we reach the end of the file.
|
@@ -61,44 +71,55 @@ class CachingStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamI
|
|
61 |
$this->stream->seek($byte);
|
62 |
}
|
63 |
}
|
|
|
64 |
public function read($length)
|
65 |
{
|
66 |
// Perform a regular read on any previously read data from the buffer
|
67 |
$data = $this->stream->read($length);
|
68 |
-
$remaining = $length -
|
|
|
69 |
// More data was requested so read from the remote stream
|
70 |
if ($remaining) {
|
71 |
// If data was written to the buffer in a position that would have
|
72 |
// been filled from the remote stream, then we must skip bytes on
|
73 |
// the remote stream to emulate overwriting bytes from that
|
74 |
// position. This mimics the behavior of other PHP stream wrappers.
|
75 |
-
$remoteData = $this->remoteStream->read(
|
|
|
|
|
|
|
76 |
if ($this->skipReadBytes) {
|
77 |
-
$len =
|
78 |
-
$remoteData =
|
79 |
-
$this->skipReadBytes =
|
80 |
}
|
|
|
81 |
$data .= $remoteData;
|
82 |
$this->stream->write($remoteData);
|
83 |
}
|
|
|
84 |
return $data;
|
85 |
}
|
|
|
86 |
public function write($string)
|
87 |
{
|
88 |
// When appending to the end of the currently read stream, you'll want
|
89 |
// to skip bytes from being read from the remote stream to emulate
|
90 |
// other stream wrappers. Basically replacing bytes of data of a fixed
|
91 |
// length.
|
92 |
-
$overflow =
|
93 |
if ($overflow > 0) {
|
94 |
$this->skipReadBytes += $overflow;
|
95 |
}
|
|
|
96 |
return $this->stream->write($string);
|
97 |
}
|
|
|
98 |
public function eof()
|
99 |
{
|
100 |
return $this->stream->eof() && $this->remoteStream->eof();
|
101 |
}
|
|
|
102 |
/**
|
103 |
* Close both the remote stream and buffer stream
|
104 |
*/
|
@@ -106,10 +127,12 @@ class CachingStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamI
|
|
106 |
{
|
107 |
$this->remoteStream->close() && $this->stream->close();
|
108 |
}
|
|
|
109 |
private function cacheEntireStream()
|
110 |
{
|
111 |
-
$target = new
|
112 |
copy_to_stream($this, $target);
|
|
|
113 |
return $this->tell();
|
114 |
}
|
115 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Stream decorator that can cache previously read bytes from a sequentially
|
8 |
* read stream.
|
9 |
*/
|
10 |
+
class CachingStream implements StreamInterface
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
13 |
+
|
14 |
/** @var StreamInterface Stream being wrapped */
|
15 |
private $remoteStream;
|
16 |
+
|
17 |
/** @var int Number of bytes to skip reading due to a write on the buffer */
|
18 |
private $skipReadBytes = 0;
|
19 |
+
|
20 |
/**
|
21 |
* We will treat the buffer object as the body of the stream
|
22 |
*
|
23 |
* @param StreamInterface $stream Stream to cache
|
24 |
* @param StreamInterface $target Optionally specify where data is cached
|
25 |
*/
|
26 |
+
public function __construct(
|
27 |
+
StreamInterface $stream,
|
28 |
+
StreamInterface $target = null
|
29 |
+
) {
|
30 |
$this->remoteStream = $stream;
|
31 |
+
$this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
|
32 |
}
|
33 |
+
|
34 |
public function getSize()
|
35 |
{
|
36 |
+
return max($this->stream->getSize(), $this->remoteStream->getSize());
|
37 |
}
|
38 |
+
|
39 |
public function rewind()
|
40 |
{
|
41 |
$this->seek(0);
|
42 |
}
|
43 |
+
|
44 |
+
public function seek($offset, $whence = SEEK_SET)
|
45 |
{
|
46 |
+
if ($whence == SEEK_SET) {
|
47 |
$byte = $offset;
|
48 |
+
} elseif ($whence == SEEK_CUR) {
|
49 |
$byte = $offset + $this->tell();
|
50 |
+
} elseif ($whence == SEEK_END) {
|
51 |
$size = $this->remoteStream->getSize();
|
52 |
if ($size === null) {
|
53 |
$size = $this->cacheEntireStream();
|
56 |
} else {
|
57 |
throw new \InvalidArgumentException('Invalid whence');
|
58 |
}
|
59 |
+
|
60 |
$diff = $byte - $this->stream->getSize();
|
61 |
+
|
62 |
if ($diff > 0) {
|
63 |
// Read the remoteStream until we have read in at least the amount
|
64 |
// of bytes requested, or we reach the end of the file.
|
71 |
$this->stream->seek($byte);
|
72 |
}
|
73 |
}
|
74 |
+
|
75 |
public function read($length)
|
76 |
{
|
77 |
// Perform a regular read on any previously read data from the buffer
|
78 |
$data = $this->stream->read($length);
|
79 |
+
$remaining = $length - strlen($data);
|
80 |
+
|
81 |
// More data was requested so read from the remote stream
|
82 |
if ($remaining) {
|
83 |
// If data was written to the buffer in a position that would have
|
84 |
// been filled from the remote stream, then we must skip bytes on
|
85 |
// the remote stream to emulate overwriting bytes from that
|
86 |
// position. This mimics the behavior of other PHP stream wrappers.
|
87 |
+
$remoteData = $this->remoteStream->read(
|
88 |
+
$remaining + $this->skipReadBytes
|
89 |
+
);
|
90 |
+
|
91 |
if ($this->skipReadBytes) {
|
92 |
+
$len = strlen($remoteData);
|
93 |
+
$remoteData = substr($remoteData, $this->skipReadBytes);
|
94 |
+
$this->skipReadBytes = max(0, $this->skipReadBytes - $len);
|
95 |
}
|
96 |
+
|
97 |
$data .= $remoteData;
|
98 |
$this->stream->write($remoteData);
|
99 |
}
|
100 |
+
|
101 |
return $data;
|
102 |
}
|
103 |
+
|
104 |
public function write($string)
|
105 |
{
|
106 |
// When appending to the end of the currently read stream, you'll want
|
107 |
// to skip bytes from being read from the remote stream to emulate
|
108 |
// other stream wrappers. Basically replacing bytes of data of a fixed
|
109 |
// length.
|
110 |
+
$overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
|
111 |
if ($overflow > 0) {
|
112 |
$this->skipReadBytes += $overflow;
|
113 |
}
|
114 |
+
|
115 |
return $this->stream->write($string);
|
116 |
}
|
117 |
+
|
118 |
public function eof()
|
119 |
{
|
120 |
return $this->stream->eof() && $this->remoteStream->eof();
|
121 |
}
|
122 |
+
|
123 |
/**
|
124 |
* Close both the remote stream and buffer stream
|
125 |
*/
|
127 |
{
|
128 |
$this->remoteStream->close() && $this->stream->close();
|
129 |
}
|
130 |
+
|
131 |
private function cacheEntireStream()
|
132 |
{
|
133 |
+
$target = new FnStream(['write' => 'strlen']);
|
134 |
copy_to_stream($this, $target);
|
135 |
+
|
136 |
return $this->tell();
|
137 |
}
|
138 |
}
|
@@ -1,36 +1,42 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Stream decorator that begins dropping data once the size of the underlying
|
8 |
* stream becomes too full.
|
9 |
*/
|
10 |
-
class DroppingStream implements
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
|
|
13 |
private $maxLength;
|
|
|
14 |
/**
|
15 |
* @param StreamInterface $stream Underlying stream to decorate.
|
16 |
* @param int $maxLength Maximum size before dropping data.
|
17 |
*/
|
18 |
-
public function __construct(
|
19 |
{
|
20 |
$this->stream = $stream;
|
21 |
$this->maxLength = $maxLength;
|
22 |
}
|
|
|
23 |
public function write($string)
|
24 |
{
|
25 |
$diff = $this->maxLength - $this->stream->getSize();
|
|
|
26 |
// Begin returning 0 when the underlying stream is too large.
|
27 |
if ($diff <= 0) {
|
28 |
return 0;
|
29 |
}
|
|
|
30 |
// Write the stream or a subset of the stream if needed.
|
31 |
-
if (
|
32 |
return $this->stream->write($string);
|
33 |
}
|
34 |
-
|
|
|
35 |
}
|
36 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Stream decorator that begins dropping data once the size of the underlying
|
8 |
* stream becomes too full.
|
9 |
*/
|
10 |
+
class DroppingStream implements StreamInterface
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
13 |
+
|
14 |
private $maxLength;
|
15 |
+
|
16 |
/**
|
17 |
* @param StreamInterface $stream Underlying stream to decorate.
|
18 |
* @param int $maxLength Maximum size before dropping data.
|
19 |
*/
|
20 |
+
public function __construct(StreamInterface $stream, $maxLength)
|
21 |
{
|
22 |
$this->stream = $stream;
|
23 |
$this->maxLength = $maxLength;
|
24 |
}
|
25 |
+
|
26 |
public function write($string)
|
27 |
{
|
28 |
$diff = $this->maxLength - $this->stream->getSize();
|
29 |
+
|
30 |
// Begin returning 0 when the underlying stream is too large.
|
31 |
if ($diff <= 0) {
|
32 |
return 0;
|
33 |
}
|
34 |
+
|
35 |
// Write the stream or a subset of the stream if needed.
|
36 |
+
if (strlen($string) < $diff) {
|
37 |
return $this->stream->write($string);
|
38 |
}
|
39 |
+
|
40 |
+
return $this->stream->write(substr($string, 0, $diff));
|
41 |
}
|
42 |
}
|
@@ -1,48 +1,57 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Compose stream implementations based on a hash of functions.
|
8 |
*
|
9 |
* Allows for easy testing and extension of a provided stream without needing
|
10 |
* to create a concrete class for a simple extension point.
|
11 |
*/
|
12 |
-
class FnStream implements
|
13 |
{
|
14 |
/** @var array */
|
15 |
private $methods;
|
|
|
16 |
/** @var array Methods that must be implemented in the given array */
|
17 |
-
private static $slots = ['__toString', 'close', 'detach', 'rewind',
|
|
|
|
|
|
|
18 |
/**
|
19 |
* @param array $methods Hash of method name to a callable.
|
20 |
*/
|
21 |
public function __construct(array $methods)
|
22 |
{
|
23 |
$this->methods = $methods;
|
|
|
24 |
// Create the functions on the class
|
25 |
foreach ($methods as $name => $fn) {
|
26 |
$this->{'_fn_' . $name} = $fn;
|
27 |
}
|
28 |
}
|
|
|
29 |
/**
|
30 |
* Lazily determine which methods are not implemented.
|
31 |
* @throws \BadMethodCallException
|
32 |
*/
|
33 |
public function __get($name)
|
34 |
{
|
35 |
-
throw new \BadMethodCallException(
|
|
|
36 |
}
|
|
|
37 |
/**
|
38 |
* The close method is called on the underlying stream only if possible.
|
39 |
*/
|
40 |
public function __destruct()
|
41 |
{
|
42 |
if (isset($this->_fn_close)) {
|
43 |
-
|
44 |
}
|
45 |
}
|
|
|
46 |
/**
|
47 |
* Adds custom functionality to an underlying stream by intercepting
|
48 |
* specific method calls.
|
@@ -52,73 +61,89 @@ class FnStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterf
|
|
52 |
*
|
53 |
* @return FnStream
|
54 |
*/
|
55 |
-
public static function decorate(
|
56 |
{
|
57 |
// If any of the required methods were not provided, then simply
|
58 |
// proxy to the decorated stream.
|
59 |
-
foreach (
|
60 |
$methods[$diff] = [$stream, $diff];
|
61 |
}
|
|
|
62 |
return new self($methods);
|
63 |
}
|
|
|
64 |
public function __toString()
|
65 |
{
|
66 |
-
return
|
67 |
}
|
|
|
68 |
public function close()
|
69 |
{
|
70 |
-
return
|
71 |
}
|
|
|
72 |
public function detach()
|
73 |
{
|
74 |
-
return
|
75 |
}
|
|
|
76 |
public function getSize()
|
77 |
{
|
78 |
-
return
|
79 |
}
|
|
|
80 |
public function tell()
|
81 |
{
|
82 |
-
return
|
83 |
}
|
|
|
84 |
public function eof()
|
85 |
{
|
86 |
-
return
|
87 |
}
|
|
|
88 |
public function isSeekable()
|
89 |
{
|
90 |
-
return
|
91 |
}
|
|
|
92 |
public function rewind()
|
93 |
{
|
94 |
-
|
95 |
}
|
96 |
-
|
|
|
97 |
{
|
98 |
-
|
99 |
}
|
|
|
100 |
public function isWritable()
|
101 |
{
|
102 |
-
return
|
103 |
}
|
|
|
104 |
public function write($string)
|
105 |
{
|
106 |
-
return
|
107 |
}
|
|
|
108 |
public function isReadable()
|
109 |
{
|
110 |
-
return
|
111 |
}
|
|
|
112 |
public function read($length)
|
113 |
{
|
114 |
-
return
|
115 |
}
|
|
|
116 |
public function getContents()
|
117 |
{
|
118 |
-
return
|
119 |
}
|
|
|
120 |
public function getMetadata($key = null)
|
121 |
{
|
122 |
-
return
|
123 |
}
|
124 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Compose stream implementations based on a hash of functions.
|
8 |
*
|
9 |
* Allows for easy testing and extension of a provided stream without needing
|
10 |
* to create a concrete class for a simple extension point.
|
11 |
*/
|
12 |
+
class FnStream implements StreamInterface
|
13 |
{
|
14 |
/** @var array */
|
15 |
private $methods;
|
16 |
+
|
17 |
/** @var array Methods that must be implemented in the given array */
|
18 |
+
private static $slots = ['__toString', 'close', 'detach', 'rewind',
|
19 |
+
'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
|
20 |
+
'isReadable', 'read', 'getContents', 'getMetadata'];
|
21 |
+
|
22 |
/**
|
23 |
* @param array $methods Hash of method name to a callable.
|
24 |
*/
|
25 |
public function __construct(array $methods)
|
26 |
{
|
27 |
$this->methods = $methods;
|
28 |
+
|
29 |
// Create the functions on the class
|
30 |
foreach ($methods as $name => $fn) {
|
31 |
$this->{'_fn_' . $name} = $fn;
|
32 |
}
|
33 |
}
|
34 |
+
|
35 |
/**
|
36 |
* Lazily determine which methods are not implemented.
|
37 |
* @throws \BadMethodCallException
|
38 |
*/
|
39 |
public function __get($name)
|
40 |
{
|
41 |
+
throw new \BadMethodCallException(str_replace('_fn_', '', $name)
|
42 |
+
. '() is not implemented in the FnStream');
|
43 |
}
|
44 |
+
|
45 |
/**
|
46 |
* The close method is called on the underlying stream only if possible.
|
47 |
*/
|
48 |
public function __destruct()
|
49 |
{
|
50 |
if (isset($this->_fn_close)) {
|
51 |
+
call_user_func($this->_fn_close);
|
52 |
}
|
53 |
}
|
54 |
+
|
55 |
/**
|
56 |
* Adds custom functionality to an underlying stream by intercepting
|
57 |
* specific method calls.
|
61 |
*
|
62 |
* @return FnStream
|
63 |
*/
|
64 |
+
public static function decorate(StreamInterface $stream, array $methods)
|
65 |
{
|
66 |
// If any of the required methods were not provided, then simply
|
67 |
// proxy to the decorated stream.
|
68 |
+
foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
|
69 |
$methods[$diff] = [$stream, $diff];
|
70 |
}
|
71 |
+
|
72 |
return new self($methods);
|
73 |
}
|
74 |
+
|
75 |
public function __toString()
|
76 |
{
|
77 |
+
return call_user_func($this->_fn___toString);
|
78 |
}
|
79 |
+
|
80 |
public function close()
|
81 |
{
|
82 |
+
return call_user_func($this->_fn_close);
|
83 |
}
|
84 |
+
|
85 |
public function detach()
|
86 |
{
|
87 |
+
return call_user_func($this->_fn_detach);
|
88 |
}
|
89 |
+
|
90 |
public function getSize()
|
91 |
{
|
92 |
+
return call_user_func($this->_fn_getSize);
|
93 |
}
|
94 |
+
|
95 |
public function tell()
|
96 |
{
|
97 |
+
return call_user_func($this->_fn_tell);
|
98 |
}
|
99 |
+
|
100 |
public function eof()
|
101 |
{
|
102 |
+
return call_user_func($this->_fn_eof);
|
103 |
}
|
104 |
+
|
105 |
public function isSeekable()
|
106 |
{
|
107 |
+
return call_user_func($this->_fn_isSeekable);
|
108 |
}
|
109 |
+
|
110 |
public function rewind()
|
111 |
{
|
112 |
+
call_user_func($this->_fn_rewind);
|
113 |
}
|
114 |
+
|
115 |
+
public function seek($offset, $whence = SEEK_SET)
|
116 |
{
|
117 |
+
call_user_func($this->_fn_seek, $offset, $whence);
|
118 |
}
|
119 |
+
|
120 |
public function isWritable()
|
121 |
{
|
122 |
+
return call_user_func($this->_fn_isWritable);
|
123 |
}
|
124 |
+
|
125 |
public function write($string)
|
126 |
{
|
127 |
+
return call_user_func($this->_fn_write, $string);
|
128 |
}
|
129 |
+
|
130 |
public function isReadable()
|
131 |
{
|
132 |
+
return call_user_func($this->_fn_isReadable);
|
133 |
}
|
134 |
+
|
135 |
public function read($length)
|
136 |
{
|
137 |
+
return call_user_func($this->_fn_read, $length);
|
138 |
}
|
139 |
+
|
140 |
public function getContents()
|
141 |
{
|
142 |
+
return call_user_func($this->_fn_getContents);
|
143 |
}
|
144 |
+
|
145 |
public function getMetadata($key = null)
|
146 |
{
|
147 |
+
return call_user_func($this->_fn_getMetadata, $key);
|
148 |
}
|
149 |
}
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
|
8 |
*
|
@@ -14,35 +14,39 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
|
14 |
* @link http://tools.ietf.org/html/rfc1952
|
15 |
* @link http://php.net/manual/en/filters.compression.php
|
16 |
*/
|
17 |
-
class InflateStream implements
|
18 |
{
|
19 |
use StreamDecoratorTrait;
|
20 |
-
|
|
|
21 |
{
|
22 |
// read the first 10 bytes, ie. gzip header
|
23 |
$header = $stream->read(10);
|
24 |
$filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header);
|
25 |
// Skip the header, that is 10 + length of filename + 1 (nil) bytes
|
26 |
-
$stream = new
|
27 |
-
$resource =
|
28 |
-
|
29 |
-
$this->stream = new
|
30 |
}
|
|
|
31 |
/**
|
32 |
* @param StreamInterface $stream
|
33 |
* @param $header
|
34 |
* @return int
|
35 |
*/
|
36 |
-
private function getLengthOfPossibleFilenameHeader(
|
37 |
{
|
38 |
$filename_header_length = 0;
|
39 |
-
|
|
|
40 |
// we have a filename, read until nil
|
41 |
$filename_header_length = 1;
|
42 |
-
while ($stream->read(1) !==
|
43 |
$filename_header_length++;
|
44 |
}
|
45 |
}
|
|
|
46 |
return $filename_header_length;
|
47 |
}
|
48 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
|
8 |
*
|
14 |
* @link http://tools.ietf.org/html/rfc1952
|
15 |
* @link http://php.net/manual/en/filters.compression.php
|
16 |
*/
|
17 |
+
class InflateStream implements StreamInterface
|
18 |
{
|
19 |
use StreamDecoratorTrait;
|
20 |
+
|
21 |
+
public function __construct(StreamInterface $stream)
|
22 |
{
|
23 |
// read the first 10 bytes, ie. gzip header
|
24 |
$header = $stream->read(10);
|
25 |
$filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header);
|
26 |
// Skip the header, that is 10 + length of filename + 1 (nil) bytes
|
27 |
+
$stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength);
|
28 |
+
$resource = StreamWrapper::getResource($stream);
|
29 |
+
stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
|
30 |
+
$this->stream = new Stream($resource);
|
31 |
}
|
32 |
+
|
33 |
/**
|
34 |
* @param StreamInterface $stream
|
35 |
* @param $header
|
36 |
* @return int
|
37 |
*/
|
38 |
+
private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header)
|
39 |
{
|
40 |
$filename_header_length = 0;
|
41 |
+
|
42 |
+
if (substr(bin2hex($header), 6, 2) === '08') {
|
43 |
// we have a filename, read until nil
|
44 |
$filename_header_length = 1;
|
45 |
+
while ($stream->read(1) !== chr(0)) {
|
46 |
$filename_header_length++;
|
47 |
}
|
48 |
}
|
49 |
+
|
50 |
return $filename_header_length;
|
51 |
}
|
52 |
}
|
@@ -1,19 +1,22 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Lazily reads or writes to a file that is opened only after an IO operation
|
8 |
* take place on the stream.
|
9 |
*/
|
10 |
-
class LazyOpenStream implements
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
|
|
13 |
/** @var string File to open */
|
14 |
private $filename;
|
|
|
15 |
/** @var string $mode */
|
16 |
private $mode;
|
|
|
17 |
/**
|
18 |
* @param string $filename File to lazily open
|
19 |
* @param string $mode fopen mode to use when opening the stream
|
@@ -23,6 +26,7 @@ class LazyOpenStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Stream
|
|
23 |
$this->filename = $filename;
|
24 |
$this->mode = $mode;
|
25 |
}
|
|
|
26 |
/**
|
27 |
* Creates the underlying stream lazily when required.
|
28 |
*
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Lazily reads or writes to a file that is opened only after an IO operation
|
8 |
* take place on the stream.
|
9 |
*/
|
10 |
+
class LazyOpenStream implements StreamInterface
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
13 |
+
|
14 |
/** @var string File to open */
|
15 |
private $filename;
|
16 |
+
|
17 |
/** @var string $mode */
|
18 |
private $mode;
|
19 |
+
|
20 |
/**
|
21 |
* @param string $filename File to lazily open
|
22 |
* @param string $mode fopen mode to use when opening the stream
|
26 |
$this->filename = $filename;
|
27 |
$this->mode = $mode;
|
28 |
}
|
29 |
+
|
30 |
/**
|
31 |
* Creates the underlying stream lazily when required.
|
32 |
*
|
@@ -1,18 +1,22 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
2 |
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Decorator used to return only a subset of a stream
|
8 |
*/
|
9 |
-
class LimitStream implements
|
10 |
{
|
11 |
use StreamDecoratorTrait;
|
|
|
12 |
/** @var int Offset to start reading from */
|
13 |
private $offset;
|
|
|
14 |
/** @var int Limit the number of bytes that can be read */
|
15 |
private $limit;
|
|
|
16 |
/**
|
17 |
* @param StreamInterface $stream Stream to wrap
|
18 |
* @param int $limit Total number of bytes to allow to be read
|
@@ -20,24 +24,31 @@ class LimitStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInt
|
|
20 |
* @param int $offset Position to seek to before reading (only
|
21 |
* works on seekable streams).
|
22 |
*/
|
23 |
-
public function __construct(
|
24 |
-
|
|
|
|
|
|
|
25 |
$this->stream = $stream;
|
26 |
$this->setLimit($limit);
|
27 |
$this->setOffset($offset);
|
28 |
}
|
|
|
29 |
public function eof()
|
30 |
{
|
31 |
// Always return true if the underlying stream is EOF
|
32 |
if ($this->stream->eof()) {
|
33 |
-
return
|
34 |
}
|
|
|
35 |
// No limit and the underlying stream is not at EOF
|
36 |
if ($this->limit == -1) {
|
37 |
-
return
|
38 |
}
|
|
|
39 |
return $this->stream->tell() >= $this->offset + $this->limit;
|
40 |
}
|
|
|
41 |
/**
|
42 |
* Returns the size of the limited subset of data
|
43 |
* {@inheritdoc}
|
@@ -49,26 +60,35 @@ class LimitStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInt
|
|
49 |
} elseif ($this->limit == -1) {
|
50 |
return $length - $this->offset;
|
51 |
} else {
|
52 |
-
return
|
53 |
}
|
54 |
}
|
|
|
55 |
/**
|
56 |
* Allow for a bounded seek on the read limited stream
|
57 |
* {@inheritdoc}
|
58 |
*/
|
59 |
-
public function seek($offset, $whence =
|
60 |
{
|
61 |
-
if ($whence !==
|
62 |
-
throw new \RuntimeException(
|
|
|
|
|
|
|
|
|
63 |
}
|
|
|
64 |
$offset += $this->offset;
|
|
|
65 |
if ($this->limit !== -1) {
|
66 |
if ($offset > $this->offset + $this->limit) {
|
67 |
$offset = $this->offset + $this->limit;
|
68 |
}
|
69 |
}
|
|
|
70 |
$this->stream->seek($offset);
|
71 |
}
|
|
|
72 |
/**
|
73 |
* Give a relative tell()
|
74 |
* {@inheritdoc}
|
@@ -77,6 +97,7 @@ class LimitStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInt
|
|
77 |
{
|
78 |
return $this->stream->tell() - $this->offset;
|
79 |
}
|
|
|
80 |
/**
|
81 |
* Set the offset to start limiting from
|
82 |
*
|
@@ -87,18 +108,21 @@ class LimitStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInt
|
|
87 |
public function setOffset($offset)
|
88 |
{
|
89 |
$current = $this->stream->tell();
|
|
|
90 |
if ($current !== $offset) {
|
91 |
// If the stream cannot seek to the offset position, then read to it
|
92 |
if ($this->stream->isSeekable()) {
|
93 |
$this->stream->seek($offset);
|
94 |
} elseif ($current > $offset) {
|
95 |
-
throw new \RuntimeException("Could not seek to stream offset
|
96 |
} else {
|
97 |
$this->stream->read($offset - $current);
|
98 |
}
|
99 |
}
|
|
|
100 |
$this->offset = $offset;
|
101 |
}
|
|
|
102 |
/**
|
103 |
* Set the limit of bytes that the decorator allows to be read from the
|
104 |
* stream.
|
@@ -110,19 +134,22 @@ class LimitStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInt
|
|
110 |
{
|
111 |
$this->limit = $limit;
|
112 |
}
|
|
|
113 |
public function read($length)
|
114 |
{
|
115 |
if ($this->limit == -1) {
|
116 |
return $this->stream->read($length);
|
117 |
}
|
|
|
118 |
// Check if the current position is less than the total allowed
|
119 |
// bytes + original offset
|
120 |
-
$remaining = $this->offset + $this->limit - $this->stream->tell();
|
121 |
if ($remaining > 0) {
|
122 |
// Only return the amount of requested data, ensuring that the byte
|
123 |
// limit is not exceeded
|
124 |
-
return $this->stream->read(
|
125 |
}
|
|
|
126 |
return '';
|
127 |
}
|
128 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
+
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
|
|
|
7 |
/**
|
8 |
* Decorator used to return only a subset of a stream
|
9 |
*/
|
10 |
+
class LimitStream implements StreamInterface
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
13 |
+
|
14 |
/** @var int Offset to start reading from */
|
15 |
private $offset;
|
16 |
+
|
17 |
/** @var int Limit the number of bytes that can be read */
|
18 |
private $limit;
|
19 |
+
|
20 |
/**
|
21 |
* @param StreamInterface $stream Stream to wrap
|
22 |
* @param int $limit Total number of bytes to allow to be read
|
24 |
* @param int $offset Position to seek to before reading (only
|
25 |
* works on seekable streams).
|
26 |
*/
|
27 |
+
public function __construct(
|
28 |
+
StreamInterface $stream,
|
29 |
+
$limit = -1,
|
30 |
+
$offset = 0
|
31 |
+
) {
|
32 |
$this->stream = $stream;
|
33 |
$this->setLimit($limit);
|
34 |
$this->setOffset($offset);
|
35 |
}
|
36 |
+
|
37 |
public function eof()
|
38 |
{
|
39 |
// Always return true if the underlying stream is EOF
|
40 |
if ($this->stream->eof()) {
|
41 |
+
return true;
|
42 |
}
|
43 |
+
|
44 |
// No limit and the underlying stream is not at EOF
|
45 |
if ($this->limit == -1) {
|
46 |
+
return false;
|
47 |
}
|
48 |
+
|
49 |
return $this->stream->tell() >= $this->offset + $this->limit;
|
50 |
}
|
51 |
+
|
52 |
/**
|
53 |
* Returns the size of the limited subset of data
|
54 |
* {@inheritdoc}
|
60 |
} elseif ($this->limit == -1) {
|
61 |
return $length - $this->offset;
|
62 |
} else {
|
63 |
+
return min($this->limit, $length - $this->offset);
|
64 |
}
|
65 |
}
|
66 |
+
|
67 |
/**
|
68 |
* Allow for a bounded seek on the read limited stream
|
69 |
* {@inheritdoc}
|
70 |
*/
|
71 |
+
public function seek($offset, $whence = SEEK_SET)
|
72 |
{
|
73 |
+
if ($whence !== SEEK_SET || $offset < 0) {
|
74 |
+
throw new \RuntimeException(sprintf(
|
75 |
+
'Cannot seek to offset % with whence %s',
|
76 |
+
$offset,
|
77 |
+
$whence
|
78 |
+
));
|
79 |
}
|
80 |
+
|
81 |
$offset += $this->offset;
|
82 |
+
|
83 |
if ($this->limit !== -1) {
|
84 |
if ($offset > $this->offset + $this->limit) {
|
85 |
$offset = $this->offset + $this->limit;
|
86 |
}
|
87 |
}
|
88 |
+
|
89 |
$this->stream->seek($offset);
|
90 |
}
|
91 |
+
|
92 |
/**
|
93 |
* Give a relative tell()
|
94 |
* {@inheritdoc}
|
97 |
{
|
98 |
return $this->stream->tell() - $this->offset;
|
99 |
}
|
100 |
+
|
101 |
/**
|
102 |
* Set the offset to start limiting from
|
103 |
*
|
108 |
public function setOffset($offset)
|
109 |
{
|
110 |
$current = $this->stream->tell();
|
111 |
+
|
112 |
if ($current !== $offset) {
|
113 |
// If the stream cannot seek to the offset position, then read to it
|
114 |
if ($this->stream->isSeekable()) {
|
115 |
$this->stream->seek($offset);
|
116 |
} elseif ($current > $offset) {
|
117 |
+
throw new \RuntimeException("Could not seek to stream offset $offset");
|
118 |
} else {
|
119 |
$this->stream->read($offset - $current);
|
120 |
}
|
121 |
}
|
122 |
+
|
123 |
$this->offset = $offset;
|
124 |
}
|
125 |
+
|
126 |
/**
|
127 |
* Set the limit of bytes that the decorator allows to be read from the
|
128 |
* stream.
|
134 |
{
|
135 |
$this->limit = $limit;
|
136 |
}
|
137 |
+
|
138 |
public function read($length)
|
139 |
{
|
140 |
if ($this->limit == -1) {
|
141 |
return $this->stream->read($length);
|
142 |
}
|
143 |
+
|
144 |
// Check if the current position is less than the total allowed
|
145 |
// bytes + original offset
|
146 |
+
$remaining = ($this->offset + $this->limit) - $this->stream->tell();
|
147 |
if ($remaining > 0) {
|
148 |
// Only return the amount of requested data, ensuring that the byte
|
149 |
// limit is not exceeded
|
150 |
+
return $this->stream->read(min($remaining, $length));
|
151 |
}
|
152 |
+
|
153 |
return '';
|
154 |
}
|
155 |
}
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Trait implementing functionality common to requests and responses.
|
8 |
*/
|
@@ -10,123 +10,156 @@ trait MessageTrait
|
|
10 |
{
|
11 |
/** @var array Map of all registered headers, as original name => array of values */
|
12 |
private $headers = [];
|
|
|
13 |
/** @var array Map of lowercase header name => original name at registration */
|
14 |
-
private $headerNames
|
|
|
15 |
/** @var string */
|
16 |
private $protocol = '1.1';
|
|
|
17 |
/** @var StreamInterface */
|
18 |
private $stream;
|
|
|
19 |
public function getProtocolVersion()
|
20 |
{
|
21 |
return $this->protocol;
|
22 |
}
|
|
|
23 |
public function withProtocolVersion($version)
|
24 |
{
|
25 |
if ($this->protocol === $version) {
|
26 |
return $this;
|
27 |
}
|
|
|
28 |
$new = clone $this;
|
29 |
$new->protocol = $version;
|
30 |
return $new;
|
31 |
}
|
|
|
32 |
public function getHeaders()
|
33 |
{
|
34 |
return $this->headers;
|
35 |
}
|
|
|
36 |
public function hasHeader($header)
|
37 |
{
|
38 |
-
return isset($this->headerNames[
|
39 |
}
|
|
|
40 |
public function getHeader($header)
|
41 |
{
|
42 |
-
$header =
|
|
|
43 |
if (!isset($this->headerNames[$header])) {
|
44 |
return [];
|
45 |
}
|
|
|
46 |
$header = $this->headerNames[$header];
|
|
|
47 |
return $this->headers[$header];
|
48 |
}
|
|
|
49 |
public function getHeaderLine($header)
|
50 |
{
|
51 |
-
return
|
52 |
}
|
|
|
53 |
public function withHeader($header, $value)
|
54 |
{
|
55 |
-
if (
|
56 |
$value = [$value];
|
57 |
}
|
|
|
58 |
$value = $this->trimHeaderValues($value);
|
59 |
-
$normalized =
|
|
|
60 |
$new = clone $this;
|
61 |
if (isset($new->headerNames[$normalized])) {
|
62 |
unset($new->headers[$new->headerNames[$normalized]]);
|
63 |
}
|
64 |
$new->headerNames[$normalized] = $header;
|
65 |
$new->headers[$header] = $value;
|
|
|
66 |
return $new;
|
67 |
}
|
|
|
68 |
public function withAddedHeader($header, $value)
|
69 |
{
|
70 |
-
if (
|
71 |
$value = [$value];
|
72 |
}
|
|
|
73 |
$value = $this->trimHeaderValues($value);
|
74 |
-
$normalized =
|
|
|
75 |
$new = clone $this;
|
76 |
if (isset($new->headerNames[$normalized])) {
|
77 |
$header = $this->headerNames[$normalized];
|
78 |
-
$new->headers[$header] =
|
79 |
} else {
|
80 |
$new->headerNames[$normalized] = $header;
|
81 |
$new->headers[$header] = $value;
|
82 |
}
|
|
|
83 |
return $new;
|
84 |
}
|
|
|
85 |
public function withoutHeader($header)
|
86 |
{
|
87 |
-
$normalized =
|
|
|
88 |
if (!isset($this->headerNames[$normalized])) {
|
89 |
return $this;
|
90 |
}
|
|
|
91 |
$header = $this->headerNames[$normalized];
|
|
|
92 |
$new = clone $this;
|
93 |
unset($new->headers[$header], $new->headerNames[$normalized]);
|
|
|
94 |
return $new;
|
95 |
}
|
|
|
96 |
public function getBody()
|
97 |
{
|
98 |
if (!$this->stream) {
|
99 |
$this->stream = stream_for('');
|
100 |
}
|
|
|
101 |
return $this->stream;
|
102 |
}
|
103 |
-
|
|
|
104 |
{
|
105 |
if ($body === $this->stream) {
|
106 |
return $this;
|
107 |
}
|
|
|
108 |
$new = clone $this;
|
109 |
$new->stream = $body;
|
110 |
return $new;
|
111 |
}
|
|
|
112 |
private function setHeaders(array $headers)
|
113 |
{
|
114 |
$this->headerNames = $this->headers = [];
|
115 |
foreach ($headers as $header => $value) {
|
116 |
-
if (
|
117 |
$value = [$value];
|
118 |
}
|
|
|
119 |
$value = $this->trimHeaderValues($value);
|
120 |
-
$normalized =
|
121 |
if (isset($this->headerNames[$normalized])) {
|
122 |
$header = $this->headerNames[$normalized];
|
123 |
-
$this->headers[$header] =
|
124 |
} else {
|
125 |
$this->headerNames[$normalized] = $header;
|
126 |
$this->headers[$header] = $value;
|
127 |
}
|
128 |
}
|
129 |
}
|
|
|
130 |
/**
|
131 |
* Trims whitespace from the header values.
|
132 |
*
|
@@ -143,8 +176,8 @@ trait MessageTrait
|
|
143 |
*/
|
144 |
private function trimHeaderValues(array $values)
|
145 |
{
|
146 |
-
return
|
147 |
-
return
|
148 |
}, $values);
|
149 |
}
|
150 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Trait implementing functionality common to requests and responses.
|
8 |
*/
|
10 |
{
|
11 |
/** @var array Map of all registered headers, as original name => array of values */
|
12 |
private $headers = [];
|
13 |
+
|
14 |
/** @var array Map of lowercase header name => original name at registration */
|
15 |
+
private $headerNames = [];
|
16 |
+
|
17 |
/** @var string */
|
18 |
private $protocol = '1.1';
|
19 |
+
|
20 |
/** @var StreamInterface */
|
21 |
private $stream;
|
22 |
+
|
23 |
public function getProtocolVersion()
|
24 |
{
|
25 |
return $this->protocol;
|
26 |
}
|
27 |
+
|
28 |
public function withProtocolVersion($version)
|
29 |
{
|
30 |
if ($this->protocol === $version) {
|
31 |
return $this;
|
32 |
}
|
33 |
+
|
34 |
$new = clone $this;
|
35 |
$new->protocol = $version;
|
36 |
return $new;
|
37 |
}
|
38 |
+
|
39 |
public function getHeaders()
|
40 |
{
|
41 |
return $this->headers;
|
42 |
}
|
43 |
+
|
44 |
public function hasHeader($header)
|
45 |
{
|
46 |
+
return isset($this->headerNames[strtolower($header)]);
|
47 |
}
|
48 |
+
|
49 |
public function getHeader($header)
|
50 |
{
|
51 |
+
$header = strtolower($header);
|
52 |
+
|
53 |
if (!isset($this->headerNames[$header])) {
|
54 |
return [];
|
55 |
}
|
56 |
+
|
57 |
$header = $this->headerNames[$header];
|
58 |
+
|
59 |
return $this->headers[$header];
|
60 |
}
|
61 |
+
|
62 |
public function getHeaderLine($header)
|
63 |
{
|
64 |
+
return implode(', ', $this->getHeader($header));
|
65 |
}
|
66 |
+
|
67 |
public function withHeader($header, $value)
|
68 |
{
|
69 |
+
if (!is_array($value)) {
|
70 |
$value = [$value];
|
71 |
}
|
72 |
+
|
73 |
$value = $this->trimHeaderValues($value);
|
74 |
+
$normalized = strtolower($header);
|
75 |
+
|
76 |
$new = clone $this;
|
77 |
if (isset($new->headerNames[$normalized])) {
|
78 |
unset($new->headers[$new->headerNames[$normalized]]);
|
79 |
}
|
80 |
$new->headerNames[$normalized] = $header;
|
81 |
$new->headers[$header] = $value;
|
82 |
+
|
83 |
return $new;
|
84 |
}
|
85 |
+
|
86 |
public function withAddedHeader($header, $value)
|
87 |
{
|
88 |
+
if (!is_array($value)) {
|
89 |
$value = [$value];
|
90 |
}
|
91 |
+
|
92 |
$value = $this->trimHeaderValues($value);
|
93 |
+
$normalized = strtolower($header);
|
94 |
+
|
95 |
$new = clone $this;
|
96 |
if (isset($new->headerNames[$normalized])) {
|
97 |
$header = $this->headerNames[$normalized];
|
98 |
+
$new->headers[$header] = array_merge($this->headers[$header], $value);
|
99 |
} else {
|
100 |
$new->headerNames[$normalized] = $header;
|
101 |
$new->headers[$header] = $value;
|
102 |
}
|
103 |
+
|
104 |
return $new;
|
105 |
}
|
106 |
+
|
107 |
public function withoutHeader($header)
|
108 |
{
|
109 |
+
$normalized = strtolower($header);
|
110 |
+
|
111 |
if (!isset($this->headerNames[$normalized])) {
|
112 |
return $this;
|
113 |
}
|
114 |
+
|
115 |
$header = $this->headerNames[$normalized];
|
116 |
+
|
117 |
$new = clone $this;
|
118 |
unset($new->headers[$header], $new->headerNames[$normalized]);
|
119 |
+
|
120 |
return $new;
|
121 |
}
|
122 |
+
|
123 |
public function getBody()
|
124 |
{
|
125 |
if (!$this->stream) {
|
126 |
$this->stream = stream_for('');
|
127 |
}
|
128 |
+
|
129 |
return $this->stream;
|
130 |
}
|
131 |
+
|
132 |
+
public function withBody(StreamInterface $body)
|
133 |
{
|
134 |
if ($body === $this->stream) {
|
135 |
return $this;
|
136 |
}
|
137 |
+
|
138 |
$new = clone $this;
|
139 |
$new->stream = $body;
|
140 |
return $new;
|
141 |
}
|
142 |
+
|
143 |
private function setHeaders(array $headers)
|
144 |
{
|
145 |
$this->headerNames = $this->headers = [];
|
146 |
foreach ($headers as $header => $value) {
|
147 |
+
if (!is_array($value)) {
|
148 |
$value = [$value];
|
149 |
}
|
150 |
+
|
151 |
$value = $this->trimHeaderValues($value);
|
152 |
+
$normalized = strtolower($header);
|
153 |
if (isset($this->headerNames[$normalized])) {
|
154 |
$header = $this->headerNames[$normalized];
|
155 |
+
$this->headers[$header] = array_merge($this->headers[$header], $value);
|
156 |
} else {
|
157 |
$this->headerNames[$normalized] = $header;
|
158 |
$this->headers[$header] = $value;
|
159 |
}
|
160 |
}
|
161 |
}
|
162 |
+
|
163 |
/**
|
164 |
* Trims whitespace from the header values.
|
165 |
*
|
176 |
*/
|
177 |
private function trimHeaderValues(array $values)
|
178 |
{
|
179 |
+
return array_map(function ($value) {
|
180 |
+
return trim($value, " \t");
|
181 |
}, $values);
|
182 |
}
|
183 |
}
|
@@ -1,16 +1,18 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Stream that when read returns bytes for a streaming multipart or
|
8 |
* multipart/form-data stream.
|
9 |
*/
|
10 |
-
class MultipartStream implements
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
|
|
13 |
private $boundary;
|
|
|
14 |
/**
|
15 |
* @param array $elements Array of associative arrays, each containing a
|
16 |
* required "name" key mapping to the form field,
|
@@ -25,9 +27,10 @@ class MultipartStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Strea
|
|
25 |
*/
|
26 |
public function __construct(array $elements = [], $boundary = null)
|
27 |
{
|
28 |
-
$this->boundary = $boundary ?:
|
29 |
$this->stream = $this->createStream($elements);
|
30 |
}
|
|
|
31 |
/**
|
32 |
* Get the boundary
|
33 |
*
|
@@ -37,10 +40,12 @@ class MultipartStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Strea
|
|
37 |
{
|
38 |
return $this->boundary;
|
39 |
}
|
|
|
40 |
public function isWritable()
|
41 |
{
|
42 |
-
return
|
43 |
}
|
|
|
44 |
/**
|
45 |
* Get the headers needed before transferring the content of a POST file
|
46 |
*/
|
@@ -50,50 +55,71 @@ class MultipartStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Strea
|
|
50 |
foreach ($headers as $key => $value) {
|
51 |
$str .= "{$key}: {$value}\r\n";
|
52 |
}
|
53 |
-
|
|
|
54 |
}
|
|
|
55 |
/**
|
56 |
* Create the aggregate stream that will be used to upload the POST data
|
57 |
*/
|
58 |
protected function createStream(array $elements)
|
59 |
{
|
60 |
-
$stream = new
|
|
|
61 |
foreach ($elements as $element) {
|
62 |
$this->addElement($stream, $element);
|
63 |
}
|
|
|
64 |
// Add the trailing boundary with CRLF
|
65 |
$stream->addStream(stream_for("--{$this->boundary}--\r\n"));
|
|
|
66 |
return $stream;
|
67 |
}
|
68 |
-
|
|
|
69 |
{
|
70 |
foreach (['contents', 'name'] as $key) {
|
71 |
-
if (
|
72 |
throw new \InvalidArgumentException("A '{$key}' key is required");
|
73 |
}
|
74 |
}
|
|
|
75 |
$element['contents'] = stream_for($element['contents']);
|
|
|
76 |
if (empty($element['filename'])) {
|
77 |
$uri = $element['contents']->getMetadata('uri');
|
78 |
-
if (
|
79 |
$element['filename'] = $uri;
|
80 |
}
|
81 |
}
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
$stream->addStream(stream_for($this->getHeaders($headers)));
|
84 |
$stream->addStream($body);
|
85 |
$stream->addStream(stream_for("\r\n"));
|
86 |
}
|
|
|
87 |
/**
|
88 |
* @return array
|
89 |
*/
|
90 |
-
private function createElement($name,
|
91 |
{
|
92 |
// Set a default content-disposition header if one was no provided
|
93 |
$disposition = $this->getHeader($headers, 'content-disposition');
|
94 |
if (!$disposition) {
|
95 |
-
$headers['Content-Disposition'] = $filename === '0' || $filename
|
|
|
|
|
|
|
|
|
96 |
}
|
|
|
97 |
// Set a default content-length header if one was no provided
|
98 |
$length = $this->getHeader($headers, 'content-length');
|
99 |
if (!$length) {
|
@@ -101,6 +127,7 @@ class MultipartStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Strea
|
|
101 |
$headers['Content-Length'] = (string) $length;
|
102 |
}
|
103 |
}
|
|
|
104 |
// Set a default Content-Type if one was not supplied
|
105 |
$type = $this->getHeader($headers, 'content-type');
|
106 |
if (!$type && ($filename === '0' || $filename)) {
|
@@ -108,16 +135,19 @@ class MultipartStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Strea
|
|
108 |
$headers['Content-Type'] = $type;
|
109 |
}
|
110 |
}
|
|
|
111 |
return [$stream, $headers];
|
112 |
}
|
|
|
113 |
private function getHeader(array $headers, $key)
|
114 |
{
|
115 |
-
$lowercaseHeader =
|
116 |
foreach ($headers as $k => $v) {
|
117 |
-
if (
|
118 |
return $v;
|
119 |
}
|
120 |
}
|
|
|
121 |
return null;
|
122 |
}
|
123 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Stream that when read returns bytes for a streaming multipart or
|
8 |
* multipart/form-data stream.
|
9 |
*/
|
10 |
+
class MultipartStream implements StreamInterface
|
11 |
{
|
12 |
use StreamDecoratorTrait;
|
13 |
+
|
14 |
private $boundary;
|
15 |
+
|
16 |
/**
|
17 |
* @param array $elements Array of associative arrays, each containing a
|
18 |
* required "name" key mapping to the form field,
|
27 |
*/
|
28 |
public function __construct(array $elements = [], $boundary = null)
|
29 |
{
|
30 |
+
$this->boundary = $boundary ?: sha1(uniqid('', true));
|
31 |
$this->stream = $this->createStream($elements);
|
32 |
}
|
33 |
+
|
34 |
/**
|
35 |
* Get the boundary
|
36 |
*
|
40 |
{
|
41 |
return $this->boundary;
|
42 |
}
|
43 |
+
|
44 |
public function isWritable()
|
45 |
{
|
46 |
+
return false;
|
47 |
}
|
48 |
+
|
49 |
/**
|
50 |
* Get the headers needed before transferring the content of a POST file
|
51 |
*/
|
55 |
foreach ($headers as $key => $value) {
|
56 |
$str .= "{$key}: {$value}\r\n";
|
57 |
}
|
58 |
+
|
59 |
+
return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n";
|
60 |
}
|
61 |
+
|
62 |
/**
|
63 |
* Create the aggregate stream that will be used to upload the POST data
|
64 |
*/
|
65 |
protected function createStream(array $elements)
|
66 |
{
|
67 |
+
$stream = new AppendStream();
|
68 |
+
|
69 |
foreach ($elements as $element) {
|
70 |
$this->addElement($stream, $element);
|
71 |
}
|
72 |
+
|
73 |
// Add the trailing boundary with CRLF
|
74 |
$stream->addStream(stream_for("--{$this->boundary}--\r\n"));
|
75 |
+
|
76 |
return $stream;
|
77 |
}
|
78 |
+
|
79 |
+
private function addElement(AppendStream $stream, array $element)
|
80 |
{
|
81 |
foreach (['contents', 'name'] as $key) {
|
82 |
+
if (!array_key_exists($key, $element)) {
|
83 |
throw new \InvalidArgumentException("A '{$key}' key is required");
|
84 |
}
|
85 |
}
|
86 |
+
|
87 |
$element['contents'] = stream_for($element['contents']);
|
88 |
+
|
89 |
if (empty($element['filename'])) {
|
90 |
$uri = $element['contents']->getMetadata('uri');
|
91 |
+
if (substr($uri, 0, 6) !== 'php://') {
|
92 |
$element['filename'] = $uri;
|
93 |
}
|
94 |
}
|
95 |
+
|
96 |
+
list($body, $headers) = $this->createElement(
|
97 |
+
$element['name'],
|
98 |
+
$element['contents'],
|
99 |
+
isset($element['filename']) ? $element['filename'] : null,
|
100 |
+
isset($element['headers']) ? $element['headers'] : []
|
101 |
+
);
|
102 |
+
|
103 |
$stream->addStream(stream_for($this->getHeaders($headers)));
|
104 |
$stream->addStream($body);
|
105 |
$stream->addStream(stream_for("\r\n"));
|
106 |
}
|
107 |
+
|
108 |
/**
|
109 |
* @return array
|
110 |
*/
|
111 |
+
private function createElement($name, StreamInterface $stream, $filename, array $headers)
|
112 |
{
|
113 |
// Set a default content-disposition header if one was no provided
|
114 |
$disposition = $this->getHeader($headers, 'content-disposition');
|
115 |
if (!$disposition) {
|
116 |
+
$headers['Content-Disposition'] = ($filename === '0' || $filename)
|
117 |
+
? sprintf('form-data; name="%s"; filename="%s"',
|
118 |
+
$name,
|
119 |
+
basename($filename))
|
120 |
+
: "form-data; name=\"{$name}\"";
|
121 |
}
|
122 |
+
|
123 |
// Set a default content-length header if one was no provided
|
124 |
$length = $this->getHeader($headers, 'content-length');
|
125 |
if (!$length) {
|
127 |
$headers['Content-Length'] = (string) $length;
|
128 |
}
|
129 |
}
|
130 |
+
|
131 |
// Set a default Content-Type if one was not supplied
|
132 |
$type = $this->getHeader($headers, 'content-type');
|
133 |
if (!$type && ($filename === '0' || $filename)) {
|
135 |
$headers['Content-Type'] = $type;
|
136 |
}
|
137 |
}
|
138 |
+
|
139 |
return [$stream, $headers];
|
140 |
}
|
141 |
+
|
142 |
private function getHeader(array $headers, $key)
|
143 |
{
|
144 |
+
$lowercaseHeader = strtolower($key);
|
145 |
foreach ($headers as $k => $v) {
|
146 |
+
if (strtolower($k) === $lowercaseHeader) {
|
147 |
return $v;
|
148 |
}
|
149 |
}
|
150 |
+
|
151 |
return null;
|
152 |
}
|
153 |
}
|
@@ -1,20 +1,22 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Stream decorator that prevents a stream from being seeked
|
8 |
*/
|
9 |
-
class NoSeekStream implements
|
10 |
{
|
11 |
use StreamDecoratorTrait;
|
12 |
-
|
|
|
13 |
{
|
14 |
throw new \RuntimeException('Cannot seek a NoSeekStream');
|
15 |
}
|
|
|
16 |
public function isSeekable()
|
17 |
{
|
18 |
-
return
|
19 |
}
|
20 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Stream decorator that prevents a stream from being seeked
|
8 |
*/
|
9 |
+
class NoSeekStream implements StreamInterface
|
10 |
{
|
11 |
use StreamDecoratorTrait;
|
12 |
+
|
13 |
+
public function seek($offset, $whence = SEEK_SET)
|
14 |
{
|
15 |
throw new \RuntimeException('Cannot seek a NoSeekStream');
|
16 |
}
|
17 |
+
|
18 |
public function isSeekable()
|
19 |
{
|
20 |
+
return false;
|
21 |
}
|
22 |
}
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Provides a read only stream that pumps data from a PHP callable.
|
8 |
*
|
@@ -13,18 +13,23 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
|
13 |
* the read() function of the PumpStream. The provided callable MUST return
|
14 |
* false when there is no more data to read.
|
15 |
*/
|
16 |
-
class PumpStream implements
|
17 |
{
|
18 |
/** @var callable */
|
19 |
private $source;
|
|
|
20 |
/** @var int */
|
21 |
private $size;
|
|
|
22 |
/** @var int */
|
23 |
private $tellPos = 0;
|
|
|
24 |
/** @var array */
|
25 |
private $metadata;
|
|
|
26 |
/** @var BufferStream */
|
27 |
private $buffer;
|
|
|
28 |
/**
|
29 |
* @param callable $source Source of the stream data. The callable MAY
|
30 |
* accept an integer argument used to control the
|
@@ -40,8 +45,9 @@ class PumpStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInte
|
|
40 |
$this->source = $source;
|
41 |
$this->size = isset($options['size']) ? $options['size'] : null;
|
42 |
$this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
|
43 |
-
$this->buffer = new
|
44 |
}
|
|
|
45 |
public function __toString()
|
46 |
{
|
47 |
try {
|
@@ -50,90 +56,109 @@ class PumpStream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInte
|
|
50 |
return '';
|
51 |
}
|
52 |
}
|
|
|
53 |
public function close()
|
54 |
{
|
55 |
$this->detach();
|
56 |
}
|
|
|
57 |
public function detach()
|
58 |
{
|
59 |
-
$this->tellPos =
|
60 |
$this->source = null;
|
61 |
}
|
|
|
62 |
public function getSize()
|
63 |
{
|
64 |
return $this->size;
|
65 |
}
|
|
|
66 |
public function tell()
|
67 |
{
|
68 |
return $this->tellPos;
|
69 |
}
|
|
|
70 |
public function eof()
|
71 |
{
|
72 |
return !$this->source;
|
73 |
}
|
|
|
74 |
public function isSeekable()
|
75 |
{
|
76 |
-
return
|
77 |
}
|
|
|
78 |
public function rewind()
|
79 |
{
|
80 |
$this->seek(0);
|
81 |
}
|
82 |
-
|
|
|
83 |
{
|
84 |
throw new \RuntimeException('Cannot seek a PumpStream');
|
85 |
}
|
|
|
86 |
public function isWritable()
|
87 |
{
|
88 |
-
return
|
89 |
}
|
|
|
90 |
public function write($string)
|
91 |
{
|
92 |
throw new \RuntimeException('Cannot write to a PumpStream');
|
93 |
}
|
|
|
94 |
public function isReadable()
|
95 |
{
|
96 |
-
return
|
97 |
}
|
|
|
98 |
public function read($length)
|
99 |
{
|
100 |
$data = $this->buffer->read($length);
|
101 |
-
$readLen =
|
102 |
$this->tellPos += $readLen;
|
103 |
$remaining = $length - $readLen;
|
|
|
104 |
if ($remaining) {
|
105 |
$this->pump($remaining);
|
106 |
$data .= $this->buffer->read($remaining);
|
107 |
-
$this->tellPos +=
|
108 |
}
|
|
|
109 |
return $data;
|
110 |
}
|
|
|
111 |
public function getContents()
|
112 |
{
|
113 |
$result = '';
|
114 |
while (!$this->eof()) {
|
115 |
$result .= $this->read(1000000);
|
116 |
}
|
|
|
117 |
return $result;
|
118 |
}
|
|
|
119 |
public function getMetadata($key = null)
|
120 |
{
|
121 |
if (!$key) {
|
122 |
return $this->metadata;
|
123 |
}
|
|
|
124 |
return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
|
125 |
}
|
|
|
126 |
private function pump($length)
|
127 |
{
|
128 |
if ($this->source) {
|
129 |
do {
|
130 |
-
$data =
|
131 |
-
if ($data ===
|
132 |
$this->source = null;
|
133 |
return;
|
134 |
}
|
135 |
$this->buffer->write($data);
|
136 |
-
$length -=
|
137 |
} while ($length > 0);
|
138 |
}
|
139 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Provides a read only stream that pumps data from a PHP callable.
|
8 |
*
|
13 |
* the read() function of the PumpStream. The provided callable MUST return
|
14 |
* false when there is no more data to read.
|
15 |
*/
|
16 |
+
class PumpStream implements StreamInterface
|
17 |
{
|
18 |
/** @var callable */
|
19 |
private $source;
|
20 |
+
|
21 |
/** @var int */
|
22 |
private $size;
|
23 |
+
|
24 |
/** @var int */
|
25 |
private $tellPos = 0;
|
26 |
+
|
27 |
/** @var array */
|
28 |
private $metadata;
|
29 |
+
|
30 |
/** @var BufferStream */
|
31 |
private $buffer;
|
32 |
+
|
33 |
/**
|
34 |
* @param callable $source Source of the stream data. The callable MAY
|
35 |
* accept an integer argument used to control the
|
45 |
$this->source = $source;
|
46 |
$this->size = isset($options['size']) ? $options['size'] : null;
|
47 |
$this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
|
48 |
+
$this->buffer = new BufferStream();
|
49 |
}
|
50 |
+
|
51 |
public function __toString()
|
52 |
{
|
53 |
try {
|
56 |
return '';
|
57 |
}
|
58 |
}
|
59 |
+
|
60 |
public function close()
|
61 |
{
|
62 |
$this->detach();
|
63 |
}
|
64 |
+
|
65 |
public function detach()
|
66 |
{
|
67 |
+
$this->tellPos = false;
|
68 |
$this->source = null;
|
69 |
}
|
70 |
+
|
71 |
public function getSize()
|
72 |
{
|
73 |
return $this->size;
|
74 |
}
|
75 |
+
|
76 |
public function tell()
|
77 |
{
|
78 |
return $this->tellPos;
|
79 |
}
|
80 |
+
|
81 |
public function eof()
|
82 |
{
|
83 |
return !$this->source;
|
84 |
}
|
85 |
+
|
86 |
public function isSeekable()
|
87 |
{
|
88 |
+
return false;
|
89 |
}
|
90 |
+
|
91 |
public function rewind()
|
92 |
{
|
93 |
$this->seek(0);
|
94 |
}
|
95 |
+
|
96 |
+
public function seek($offset, $whence = SEEK_SET)
|
97 |
{
|
98 |
throw new \RuntimeException('Cannot seek a PumpStream');
|
99 |
}
|
100 |
+
|
101 |
public function isWritable()
|
102 |
{
|
103 |
+
return false;
|
104 |
}
|
105 |
+
|
106 |
public function write($string)
|
107 |
{
|
108 |
throw new \RuntimeException('Cannot write to a PumpStream');
|
109 |
}
|
110 |
+
|
111 |
public function isReadable()
|
112 |
{
|
113 |
+
return true;
|
114 |
}
|
115 |
+
|
116 |
public function read($length)
|
117 |
{
|
118 |
$data = $this->buffer->read($length);
|
119 |
+
$readLen = strlen($data);
|
120 |
$this->tellPos += $readLen;
|
121 |
$remaining = $length - $readLen;
|
122 |
+
|
123 |
if ($remaining) {
|
124 |
$this->pump($remaining);
|
125 |
$data .= $this->buffer->read($remaining);
|
126 |
+
$this->tellPos += strlen($data) - $readLen;
|
127 |
}
|
128 |
+
|
129 |
return $data;
|
130 |
}
|
131 |
+
|
132 |
public function getContents()
|
133 |
{
|
134 |
$result = '';
|
135 |
while (!$this->eof()) {
|
136 |
$result .= $this->read(1000000);
|
137 |
}
|
138 |
+
|
139 |
return $result;
|
140 |
}
|
141 |
+
|
142 |
public function getMetadata($key = null)
|
143 |
{
|
144 |
if (!$key) {
|
145 |
return $this->metadata;
|
146 |
}
|
147 |
+
|
148 |
return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
|
149 |
}
|
150 |
+
|
151 |
private function pump($length)
|
152 |
{
|
153 |
if ($this->source) {
|
154 |
do {
|
155 |
+
$data = call_user_func($this->source, $length);
|
156 |
+
if ($data === false || $data === null) {
|
157 |
$this->source = null;
|
158 |
return;
|
159 |
}
|
160 |
$this->buffer->write($data);
|
161 |
+
$length -= strlen($data);
|
162 |
} while ($length > 0);
|
163 |
}
|
164 |
}
|
@@ -1,23 +1,27 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
4 |
|
5 |
use InvalidArgumentException;
|
6 |
-
use
|
7 |
-
use
|
8 |
-
use
|
|
|
9 |
/**
|
10 |
* PSR-7 request implementation.
|
11 |
*/
|
12 |
-
class Request implements
|
13 |
{
|
14 |
use MessageTrait;
|
|
|
15 |
/** @var string */
|
16 |
private $method;
|
|
|
17 |
/** @var null|string */
|
18 |
private $requestTarget;
|
|
|
19 |
/** @var UriInterface */
|
20 |
private $uri;
|
|
|
21 |
/**
|
22 |
* @param string $method HTTP method
|
23 |
* @param string|UriInterface $uri URI
|
@@ -25,27 +29,37 @@ class Request implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterf
|
|
25 |
* @param string|null|resource|StreamInterface $body Request body
|
26 |
* @param string $version Protocol version
|
27 |
*/
|
28 |
-
public function __construct(
|
29 |
-
|
30 |
-
|
31 |
-
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
33 |
-
|
|
|
34 |
$this->uri = $uri;
|
35 |
$this->setHeaders($headers);
|
36 |
$this->protocol = $version;
|
|
|
37 |
if (!$this->hasHeader('Host')) {
|
38 |
$this->updateHostFromUri();
|
39 |
}
|
|
|
40 |
if ($body !== '' && $body !== null) {
|
41 |
$this->stream = stream_for($body);
|
42 |
}
|
43 |
}
|
|
|
44 |
public function getRequestTarget()
|
45 |
{
|
46 |
if ($this->requestTarget !== null) {
|
47 |
return $this->requestTarget;
|
48 |
}
|
|
|
49 |
$target = $this->uri->getPath();
|
50 |
if ($target == '') {
|
51 |
$target = '/';
|
@@ -53,52 +67,68 @@ class Request implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterf
|
|
53 |
if ($this->uri->getQuery() != '') {
|
54 |
$target .= '?' . $this->uri->getQuery();
|
55 |
}
|
|
|
56 |
return $target;
|
57 |
}
|
|
|
58 |
public function withRequestTarget($requestTarget)
|
59 |
{
|
60 |
-
if (
|
61 |
-
throw new
|
|
|
|
|
62 |
}
|
|
|
63 |
$new = clone $this;
|
64 |
$new->requestTarget = $requestTarget;
|
65 |
return $new;
|
66 |
}
|
|
|
67 |
public function getMethod()
|
68 |
{
|
69 |
return $this->method;
|
70 |
}
|
|
|
71 |
public function withMethod($method)
|
72 |
{
|
73 |
$new = clone $this;
|
74 |
-
$new->method =
|
75 |
return $new;
|
76 |
}
|
|
|
77 |
public function getUri()
|
78 |
{
|
79 |
return $this->uri;
|
80 |
}
|
81 |
-
|
|
|
82 |
{
|
83 |
if ($uri === $this->uri) {
|
84 |
return $this;
|
85 |
}
|
|
|
86 |
$new = clone $this;
|
87 |
$new->uri = $uri;
|
|
|
88 |
if (!$preserveHost) {
|
89 |
$new->updateHostFromUri();
|
90 |
}
|
|
|
91 |
return $new;
|
92 |
}
|
|
|
93 |
private function updateHostFromUri()
|
94 |
{
|
95 |
$host = $this->uri->getHost();
|
|
|
96 |
if ($host == '') {
|
97 |
return;
|
98 |
}
|
|
|
99 |
if (($port = $this->uri->getPort()) !== null) {
|
100 |
$host .= ':' . $port;
|
101 |
}
|
|
|
102 |
if (isset($this->headerNames['host'])) {
|
103 |
$header = $this->headerNames['host'];
|
104 |
} else {
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
|
|
3 |
|
4 |
use InvalidArgumentException;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\StreamInterface;
|
7 |
+
use Psr\Http\Message\UriInterface;
|
8 |
+
|
9 |
/**
|
10 |
* PSR-7 request implementation.
|
11 |
*/
|
12 |
+
class Request implements RequestInterface
|
13 |
{
|
14 |
use MessageTrait;
|
15 |
+
|
16 |
/** @var string */
|
17 |
private $method;
|
18 |
+
|
19 |
/** @var null|string */
|
20 |
private $requestTarget;
|
21 |
+
|
22 |
/** @var UriInterface */
|
23 |
private $uri;
|
24 |
+
|
25 |
/**
|
26 |
* @param string $method HTTP method
|
27 |
* @param string|UriInterface $uri URI
|
29 |
* @param string|null|resource|StreamInterface $body Request body
|
30 |
* @param string $version Protocol version
|
31 |
*/
|
32 |
+
public function __construct(
|
33 |
+
$method,
|
34 |
+
$uri,
|
35 |
+
array $headers = [],
|
36 |
+
$body = null,
|
37 |
+
$version = '1.1'
|
38 |
+
) {
|
39 |
+
if (!($uri instanceof UriInterface)) {
|
40 |
+
$uri = new Uri($uri);
|
41 |
}
|
42 |
+
|
43 |
+
$this->method = strtoupper($method);
|
44 |
$this->uri = $uri;
|
45 |
$this->setHeaders($headers);
|
46 |
$this->protocol = $version;
|
47 |
+
|
48 |
if (!$this->hasHeader('Host')) {
|
49 |
$this->updateHostFromUri();
|
50 |
}
|
51 |
+
|
52 |
if ($body !== '' && $body !== null) {
|
53 |
$this->stream = stream_for($body);
|
54 |
}
|
55 |
}
|
56 |
+
|
57 |
public function getRequestTarget()
|
58 |
{
|
59 |
if ($this->requestTarget !== null) {
|
60 |
return $this->requestTarget;
|
61 |
}
|
62 |
+
|
63 |
$target = $this->uri->getPath();
|
64 |
if ($target == '') {
|
65 |
$target = '/';
|
67 |
if ($this->uri->getQuery() != '') {
|
68 |
$target .= '?' . $this->uri->getQuery();
|
69 |
}
|
70 |
+
|
71 |
return $target;
|
72 |
}
|
73 |
+
|
74 |
public function withRequestTarget($requestTarget)
|
75 |
{
|
76 |
+
if (preg_match('#\s#', $requestTarget)) {
|
77 |
+
throw new InvalidArgumentException(
|
78 |
+
'Invalid request target provided; cannot contain whitespace'
|
79 |
+
);
|
80 |
}
|
81 |
+
|
82 |
$new = clone $this;
|
83 |
$new->requestTarget = $requestTarget;
|
84 |
return $new;
|
85 |
}
|
86 |
+
|
87 |
public function getMethod()
|
88 |
{
|
89 |
return $this->method;
|
90 |
}
|
91 |
+
|
92 |
public function withMethod($method)
|
93 |
{
|
94 |
$new = clone $this;
|
95 |
+
$new->method = strtoupper($method);
|
96 |
return $new;
|
97 |
}
|
98 |
+
|
99 |
public function getUri()
|
100 |
{
|
101 |
return $this->uri;
|
102 |
}
|
103 |
+
|
104 |
+
public function withUri(UriInterface $uri, $preserveHost = false)
|
105 |
{
|
106 |
if ($uri === $this->uri) {
|
107 |
return $this;
|
108 |
}
|
109 |
+
|
110 |
$new = clone $this;
|
111 |
$new->uri = $uri;
|
112 |
+
|
113 |
if (!$preserveHost) {
|
114 |
$new->updateHostFromUri();
|
115 |
}
|
116 |
+
|
117 |
return $new;
|
118 |
}
|
119 |
+
|
120 |
private function updateHostFromUri()
|
121 |
{
|
122 |
$host = $this->uri->getHost();
|
123 |
+
|
124 |
if ($host == '') {
|
125 |
return;
|
126 |
}
|
127 |
+
|
128 |
if (($port = $this->uri->getPort()) !== null) {
|
129 |
$host .= ':' . $port;
|
130 |
}
|
131 |
+
|
132 |
if (isset($this->headerNames['host'])) {
|
133 |
$header = $this->headerNames['host'];
|
134 |
} else {
|
@@ -1,21 +1,84 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
7 |
/**
|
8 |
* PSR-7 response implementation.
|
9 |
*/
|
10 |
-
class Response implements
|
11 |
{
|
12 |
use MessageTrait;
|
|
|
13 |
/** @var array Map of standard HTTP status code/reason phrases */
|
14 |
-
private static $phrases = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
/** @var string */
|
16 |
private $reasonPhrase = '';
|
|
|
17 |
/** @var int */
|
18 |
private $statusCode = 200;
|
|
|
19 |
/**
|
20 |
* @param int $status Status code
|
21 |
* @param array $headers Response headers
|
@@ -23,28 +86,39 @@ class Response implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInte
|
|
23 |
* @param string $version Protocol version
|
24 |
* @param string|null $reason Reason phrase (when empty a default will be used based on the status code)
|
25 |
*/
|
26 |
-
public function __construct(
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
28 |
$this->statusCode = (int) $status;
|
|
|
29 |
if ($body !== '' && $body !== null) {
|
30 |
$this->stream = stream_for($body);
|
31 |
}
|
|
|
32 |
$this->setHeaders($headers);
|
33 |
if ($reason == '' && isset(self::$phrases[$this->statusCode])) {
|
34 |
$this->reasonPhrase = self::$phrases[$this->statusCode];
|
35 |
} else {
|
36 |
$this->reasonPhrase = (string) $reason;
|
37 |
}
|
|
|
38 |
$this->protocol = $version;
|
39 |
}
|
|
|
40 |
public function getStatusCode()
|
41 |
{
|
42 |
return $this->statusCode;
|
43 |
}
|
|
|
44 |
public function getReasonPhrase()
|
45 |
{
|
46 |
return $this->reasonPhrase;
|
47 |
}
|
|
|
48 |
public function withStatus($code, $reasonPhrase = '')
|
49 |
{
|
50 |
$new = clone $this;
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\ResponseInterface;
|
5 |
+
use Psr\Http\Message\StreamInterface;
|
6 |
|
|
|
|
|
7 |
/**
|
8 |
* PSR-7 response implementation.
|
9 |
*/
|
10 |
+
class Response implements ResponseInterface
|
11 |
{
|
12 |
use MessageTrait;
|
13 |
+
|
14 |
/** @var array Map of standard HTTP status code/reason phrases */
|
15 |
+
private static $phrases = [
|
16 |
+
100 => 'Continue',
|
17 |
+
101 => 'Switching Protocols',
|
18 |
+
102 => 'Processing',
|
19 |
+
200 => 'OK',
|
20 |
+
201 => 'Created',
|
21 |
+
202 => 'Accepted',
|
22 |
+
203 => 'Non-Authoritative Information',
|
23 |
+
204 => 'No Content',
|
24 |
+
205 => 'Reset Content',
|
25 |
+
206 => 'Partial Content',
|
26 |
+
207 => 'Multi-status',
|
27 |
+
208 => 'Already Reported',
|
28 |
+
300 => 'Multiple Choices',
|
29 |
+
301 => 'Moved Permanently',
|
30 |
+
302 => 'Found',
|
31 |
+
303 => 'See Other',
|
32 |
+
304 => 'Not Modified',
|
33 |
+
305 => 'Use Proxy',
|
34 |
+
306 => 'Switch Proxy',
|
35 |
+
307 => 'Temporary Redirect',
|
36 |
+
400 => 'Bad Request',
|
37 |
+
401 => 'Unauthorized',
|
38 |
+
402 => 'Payment Required',
|
39 |
+
403 => 'Forbidden',
|
40 |
+
404 => 'Not Found',
|
41 |
+
405 => 'Method Not Allowed',
|
42 |
+
406 => 'Not Acceptable',
|
43 |
+
407 => 'Proxy Authentication Required',
|
44 |
+
408 => 'Request Time-out',
|
45 |
+
409 => 'Conflict',
|
46 |
+
410 => 'Gone',
|
47 |
+
411 => 'Length Required',
|
48 |
+
412 => 'Precondition Failed',
|
49 |
+
413 => 'Request Entity Too Large',
|
50 |
+
414 => 'Request-URI Too Large',
|
51 |
+
415 => 'Unsupported Media Type',
|
52 |
+
416 => 'Requested range not satisfiable',
|
53 |
+
417 => 'Expectation Failed',
|
54 |
+
418 => 'I\'m a teapot',
|
55 |
+
422 => 'Unprocessable Entity',
|
56 |
+
423 => 'Locked',
|
57 |
+
424 => 'Failed Dependency',
|
58 |
+
425 => 'Unordered Collection',
|
59 |
+
426 => 'Upgrade Required',
|
60 |
+
428 => 'Precondition Required',
|
61 |
+
429 => 'Too Many Requests',
|
62 |
+
431 => 'Request Header Fields Too Large',
|
63 |
+
451 => 'Unavailable For Legal Reasons',
|
64 |
+
500 => 'Internal Server Error',
|
65 |
+
501 => 'Not Implemented',
|
66 |
+
502 => 'Bad Gateway',
|
67 |
+
503 => 'Service Unavailable',
|
68 |
+
504 => 'Gateway Time-out',
|
69 |
+
505 => 'HTTP Version not supported',
|
70 |
+
506 => 'Variant Also Negotiates',
|
71 |
+
507 => 'Insufficient Storage',
|
72 |
+
508 => 'Loop Detected',
|
73 |
+
511 => 'Network Authentication Required',
|
74 |
+
];
|
75 |
+
|
76 |
/** @var string */
|
77 |
private $reasonPhrase = '';
|
78 |
+
|
79 |
/** @var int */
|
80 |
private $statusCode = 200;
|
81 |
+
|
82 |
/**
|
83 |
* @param int $status Status code
|
84 |
* @param array $headers Response headers
|
86 |
* @param string $version Protocol version
|
87 |
* @param string|null $reason Reason phrase (when empty a default will be used based on the status code)
|
88 |
*/
|
89 |
+
public function __construct(
|
90 |
+
$status = 200,
|
91 |
+
array $headers = [],
|
92 |
+
$body = null,
|
93 |
+
$version = '1.1',
|
94 |
+
$reason = null
|
95 |
+
) {
|
96 |
$this->statusCode = (int) $status;
|
97 |
+
|
98 |
if ($body !== '' && $body !== null) {
|
99 |
$this->stream = stream_for($body);
|
100 |
}
|
101 |
+
|
102 |
$this->setHeaders($headers);
|
103 |
if ($reason == '' && isset(self::$phrases[$this->statusCode])) {
|
104 |
$this->reasonPhrase = self::$phrases[$this->statusCode];
|
105 |
} else {
|
106 |
$this->reasonPhrase = (string) $reason;
|
107 |
}
|
108 |
+
|
109 |
$this->protocol = $version;
|
110 |
}
|
111 |
+
|
112 |
public function getStatusCode()
|
113 |
{
|
114 |
return $this->statusCode;
|
115 |
}
|
116 |
+
|
117 |
public function getReasonPhrase()
|
118 |
{
|
119 |
return $this->reasonPhrase;
|
120 |
}
|
121 |
+
|
122 |
public function withStatus($code, $reasonPhrase = '')
|
123 |
{
|
124 |
$new = clone $this;
|
@@ -1,12 +1,13 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace
|
4 |
|
5 |
use InvalidArgumentException;
|
6 |
-
use
|
7 |
-
use
|
8 |
-
use
|
9 |
-
use
|
|
|
10 |
/**
|
11 |
* Server-side HTTP request
|
12 |
*
|
@@ -21,32 +22,38 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UploadedFileInterface;
|
|
21 |
* implemented such that they retain the internal state of the current
|
22 |
* message and return a new instance that contains the changed state.
|
23 |
*/
|
24 |
-
class ServerRequest extends
|
25 |
{
|
26 |
/**
|
27 |
* @var array
|
28 |
*/
|
29 |
private $attributes = [];
|
|
|
30 |
/**
|
31 |
* @var array
|
32 |
*/
|
33 |
private $cookieParams = [];
|
|
|
34 |
/**
|
35 |
* @var null|array|object
|
36 |
*/
|
37 |
private $parsedBody;
|
|
|
38 |
/**
|
39 |
* @var array
|
40 |
*/
|
41 |
private $queryParams = [];
|
|
|
42 |
/**
|
43 |
* @var array
|
44 |
*/
|
45 |
private $serverParams;
|
|
|
46 |
/**
|
47 |
* @var array
|
48 |
*/
|
49 |
private $uploadedFiles = [];
|
|
|
50 |
/**
|
51 |
* @param string $method HTTP method
|
52 |
* @param string|UriInterface $uri URI
|
@@ -55,11 +62,19 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
55 |
* @param string $version Protocol version
|
56 |
* @param array $serverParams Typically the $_SERVER superglobal
|
57 |
*/
|
58 |
-
public function __construct(
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
$this->serverParams = $serverParams;
|
|
|
61 |
parent::__construct($method, $uri, $headers, $body, $version);
|
62 |
}
|
|
|
63 |
/**
|
64 |
* Return an UploadedFile instance array.
|
65 |
*
|
@@ -70,20 +85,23 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
70 |
public static function normalizeFiles(array $files)
|
71 |
{
|
72 |
$normalized = [];
|
|
|
73 |
foreach ($files as $key => $value) {
|
74 |
-
if ($value instanceof
|
75 |
$normalized[$key] = $value;
|
76 |
-
} elseif (
|
77 |
$normalized[$key] = self::createUploadedFileFromSpec($value);
|
78 |
-
} elseif (
|
79 |
$normalized[$key] = self::normalizeFiles($value);
|
80 |
continue;
|
81 |
} else {
|
82 |
-
throw new
|
83 |
}
|
84 |
}
|
|
|
85 |
return $normalized;
|
86 |
}
|
|
|
87 |
/**
|
88 |
* Create and return an UploadedFile instance from a $_FILES specification.
|
89 |
*
|
@@ -95,11 +113,19 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
95 |
*/
|
96 |
private static function createUploadedFileFromSpec(array $value)
|
97 |
{
|
98 |
-
if (
|
99 |
return self::normalizeNestedFileSpec($value);
|
100 |
}
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
|
|
103 |
/**
|
104 |
* Normalize an array of file specifications.
|
105 |
*
|
@@ -112,12 +138,21 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
112 |
private static function normalizeNestedFileSpec(array $files = [])
|
113 |
{
|
114 |
$normalizedFiles = [];
|
115 |
-
|
116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
$normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
|
118 |
}
|
|
|
119 |
return $normalizedFiles;
|
120 |
}
|
|
|
121 |
/**
|
122 |
* Return a ServerRequest populated with superglobals:
|
123 |
* $_GET
|
@@ -131,28 +166,36 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
131 |
public static function fromGlobals()
|
132 |
{
|
133 |
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
|
134 |
-
$headers =
|
135 |
$uri = self::getUriFromGlobals();
|
136 |
-
$body = new
|
137 |
-
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ?
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
|
|
141 |
/**
|
142 |
* Get a Uri populated with values from $_SERVER.
|
143 |
*
|
144 |
* @return UriInterface
|
145 |
*/
|
146 |
-
public static function getUriFromGlobals()
|
147 |
-
|
148 |
-
|
149 |
$uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
|
150 |
-
|
|
|
151 |
if (isset($_SERVER['HTTP_HOST'])) {
|
152 |
-
$hostHeaderParts =
|
153 |
$uri = $uri->withHost($hostHeaderParts[0]);
|
154 |
if (isset($hostHeaderParts[1])) {
|
155 |
-
$hasPort =
|
156 |
$uri = $uri->withPort($hostHeaderParts[1]);
|
157 |
}
|
158 |
} elseif (isset($_SERVER['SERVER_NAME'])) {
|
@@ -160,23 +203,29 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
160 |
} elseif (isset($_SERVER['SERVER_ADDR'])) {
|
161 |
$uri = $uri->withHost($_SERVER['SERVER_ADDR']);
|
162 |
}
|
|
|
163 |
if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
|
164 |
$uri = $uri->withPort($_SERVER['SERVER_PORT']);
|
165 |
}
|
166 |
-
|
|
|
167 |
if (isset($_SERVER['REQUEST_URI'])) {
|
168 |
-
$requestUriParts =
|
169 |
$uri = $uri->withPath($requestUriParts[0]);
|
170 |
if (isset($requestUriParts[1])) {
|
171 |
-
$hasQuery =
|
172 |
$uri = $uri->withQuery($requestUriParts[1]);
|
173 |
}
|
174 |
}
|
|
|
175 |
if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
|
176 |
$uri = $uri->withQuery($_SERVER['QUERY_STRING']);
|
177 |
}
|
|
|
178 |
return $uri;
|
179 |
}
|
|
|
|
|
180 |
/**
|
181 |
* {@inheritdoc}
|
182 |
*/
|
@@ -184,6 +233,7 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
184 |
{
|
185 |
return $this->serverParams;
|
186 |
}
|
|
|
187 |
/**
|
188 |
* {@inheritdoc}
|
189 |
*/
|
@@ -191,6 +241,7 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
191 |
{
|
192 |
return $this->uploadedFiles;
|
193 |
}
|
|
|
194 |
/**
|
195 |
* {@inheritdoc}
|
196 |
*/
|
@@ -198,8 +249,10 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
198 |
{
|
199 |
$new = clone $this;
|
200 |
$new->uploadedFiles = $uploadedFiles;
|
|
|
201 |
return $new;
|
202 |
}
|
|
|
203 |
/**
|
204 |
* {@inheritdoc}
|
205 |
*/
|
@@ -207,6 +260,7 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
207 |
{
|
208 |
return $this->cookieParams;
|
209 |
}
|
|
|
210 |
/**
|
211 |
* {@inheritdoc}
|
212 |
*/
|
@@ -214,8 +268,10 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
214 |
{
|
215 |
$new = clone $this;
|
216 |
$new->cookieParams = $cookies;
|
|
|
217 |
return $new;
|
218 |
}
|
|
|
219 |
/**
|
220 |
* {@inheritdoc}
|
221 |
*/
|
@@ -223,6 +279,7 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
223 |
{
|
224 |
return $this->queryParams;
|
225 |
}
|
|
|
226 |
/**
|
227 |
* {@inheritdoc}
|
228 |
*/
|
@@ -230,8 +287,10 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
230 |
{
|
231 |
$new = clone $this;
|
232 |
$new->queryParams = $query;
|
|
|
233 |
return $new;
|
234 |
}
|
|
|
235 |
/**
|
236 |
* {@inheritdoc}
|
237 |
*/
|
@@ -239,6 +298,7 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
239 |
{
|
240 |
return $this->parsedBody;
|
241 |
}
|
|
|
242 |
/**
|
243 |
* {@inheritdoc}
|
244 |
*/
|
@@ -246,8 +306,10 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
246 |
{
|
247 |
$new = clone $this;
|
248 |
$new->parsedBody = $data;
|
|
|
249 |
return $new;
|
250 |
}
|
|
|
251 |
/**
|
252 |
* {@inheritdoc}
|
253 |
*/
|
@@ -255,16 +317,19 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
255 |
{
|
256 |
return $this->attributes;
|
257 |
}
|
|
|
258 |
/**
|
259 |
* {@inheritdoc}
|
260 |
*/
|
261 |
public function getAttribute($attribute, $default = null)
|
262 |
{
|
263 |
-
if (
|
264 |
return $default;
|
265 |
}
|
|
|
266 |
return $this->attributes[$attribute];
|
267 |
}
|
|
|
268 |
/**
|
269 |
* {@inheritdoc}
|
270 |
*/
|
@@ -272,18 +337,22 @@ class ServerRequest extends \_PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7\Request imp
|
|
272 |
{
|
273 |
$new = clone $this;
|
274 |
$new->attributes[$attribute] = $value;
|
|
|
275 |
return $new;
|
276 |
}
|
|
|
277 |
/**
|
278 |
* {@inheritdoc}
|
279 |
*/
|
280 |
public function withoutAttribute($attribute)
|
281 |
{
|
282 |
-
if (
|
283 |
return $this;
|
284 |
}
|
|
|
285 |
$new = clone $this;
|
286 |
unset($new->attributes[$attribute]);
|
|
|
287 |
return $new;
|
288 |
}
|
289 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace GuzzleHttp\Psr7;
|
4 |
|
5 |
use InvalidArgumentException;
|
6 |
+
use Psr\Http\Message\ServerRequestInterface;
|
7 |
+
use Psr\Http\Message\UriInterface;
|
8 |
+
use Psr\Http\Message\StreamInterface;
|
9 |
+
use Psr\Http\Message\UploadedFileInterface;
|
10 |
+
|
11 |
/**
|
12 |
* Server-side HTTP request
|
13 |
*
|
22 |
* implemented such that they retain the internal state of the current
|
23 |
* message and return a new instance that contains the changed state.
|
24 |
*/
|
25 |
+
class ServerRequest extends Request implements ServerRequestInterface
|
26 |
{
|
27 |
/**
|
28 |
* @var array
|
29 |
*/
|
30 |
private $attributes = [];
|
31 |
+
|
32 |
/**
|
33 |
* @var array
|
34 |
*/
|
35 |
private $cookieParams = [];
|
36 |
+
|
37 |
/**
|
38 |
* @var null|array|object
|
39 |
*/
|
40 |
private $parsedBody;
|
41 |
+
|
42 |
/**
|
43 |
* @var array
|
44 |
*/
|
45 |
private $queryParams = [];
|
46 |
+
|
47 |
/**
|
48 |
* @var array
|
49 |
*/
|
50 |
private $serverParams;
|
51 |
+
|
52 |
/**
|
53 |
* @var array
|
54 |
*/
|
55 |
private $uploadedFiles = [];
|
56 |
+
|
57 |
/**
|
58 |
* @param string $method HTTP method
|
59 |
* @param string|UriInterface $uri URI
|
62 |
* @param string $version Protocol version
|
63 |
* @param array $serverParams Typically the $_SERVER superglobal
|
64 |
*/
|
65 |
+
public function __construct(
|
66 |
+
$method,
|
67 |
+
$uri,
|
68 |
+
array $headers = [],
|
69 |
+
$body = null,
|
70 |
+
$version = '1.1',
|
71 |
+
array $serverParams = []
|
72 |
+
) {
|
73 |
$this->serverParams = $serverParams;
|
74 |
+
|
75 |
parent::__construct($method, $uri, $headers, $body, $version);
|
76 |
}
|
77 |
+
|
78 |
/**
|
79 |
* Return an UploadedFile instance array.
|
80 |
*
|
85 |
public static function normalizeFiles(array $files)
|
86 |
{
|
87 |
$normalized = [];
|
88 |
+
|
89 |
foreach ($files as $key => $value) {
|
90 |
+
if ($value instanceof UploadedFileInterface) {
|
91 |
$normalized[$key] = $value;
|
92 |
+
} elseif (is_array($value) && isset($value['tmp_name'])) {
|
93 |
$normalized[$key] = self::createUploadedFileFromSpec($value);
|
94 |
+
} elseif (is_array($value)) {
|
95 |
$normalized[$key] = self::normalizeFiles($value);
|
96 |
continue;
|
97 |
} else {
|
98 |
+
throw new InvalidArgumentException('Invalid value in files specification');
|
99 |
}
|
100 |
}
|
101 |
+
|
102 |
return $normalized;
|
103 |
}
|
104 |
+
|
105 |
/**
|
106 |
* Create and return an UploadedFile instance from a $_FILES specification.
|
107 |
*
|
113 |
*/
|
114 |
private static function createUploadedFileFromSpec(array $value)
|
115 |
{
|
116 |
+
if (is_array($value['tmp_name'])) {
|
117 |
return self::normalizeNestedFileSpec($value);
|
118 |
}
|
119 |
+
|
120 |
+
return new UploadedFile(
|
121 |
+
$value['tmp_name'],
|
122 |
+
(int) $value['size'],
|
123 |
+
(int) $value['error'],
|
124 |
+
$value['name'],
|
125 |
+
$value['type']
|
126 |
+
);
|
127 |
}
|
128 |
+
|
129 |
/**
|
130 |
* Normalize an array of file specifications.
|
131 |
*
|
138 |
private static function normalizeNestedFileSpec(array $files = [])
|
139 |
{
|
140 |
$normalizedFiles = [];
|
141 |
+
|
142 |
+
foreach (array_keys($files['tmp_name']) as $key) {
|
143 |
+
$spec = [
|
144 |
+
'tmp_name' => $files['tmp_name'][$key],
|
145 |
+
'size' => $files['size'][$key],
|
146 |
+
'error' => $files['error'][$key],
|
147 |
+
'name' => $files['name'][$key],
|
148 |
+
'type' => $files['type'][$key],
|
149 |
+
];
|
150 |
$normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
|
151 |
}
|
152 |
+
|
153 |
return $normalizedFiles;
|
154 |
}
|
155 |
+
|
156 |
/**
|
157 |
* Return a ServerRequest populated with superglobals:
|
158 |
* $_GET
|
166 |
public static function fromGlobals()
|
167 |
{
|
168 |
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
|
169 |
+
$headers = function_exists('getallheaders') ? getallheaders() : [];
|
170 |
$uri = self::getUriFromGlobals();
|
171 |
+
$body = new LazyOpenStream('php://input', 'r+');
|
172 |
+
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
|
173 |
+
|
174 |
+
$serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
|
175 |
+
|
176 |
+
return $serverRequest
|
177 |
+
->withCookieParams($_COOKIE)
|
178 |
+
->withQueryParams($_GET)
|
179 |
+
->withParsedBody($_POST)
|
180 |
+
->withUploadedFiles(self::normalizeFiles($_FILES));
|
181 |
}
|
182 |
+
|
183 |
/**
|
184 |
* Get a Uri populated with values from $_SERVER.
|
185 |
*
|
186 |
* @return UriInterface
|
187 |
*/
|
188 |
+
public static function getUriFromGlobals() {
|
189 |
+
$uri = new Uri('');
|
190 |
+
|
191 |
$uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
|
192 |
+
|
193 |
+
$hasPort = false;
|
194 |
if (isset($_SERVER['HTTP_HOST'])) {
|
195 |
+
$hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']);
|
196 |
$uri = $uri->withHost($hostHeaderParts[0]);
|
197 |
if (isset($hostHeaderParts[1])) {
|
198 |
+
$hasPort = true;
|
199 |
$uri = $uri->withPort($hostHeaderParts[1]);
|
200 |
}
|
201 |
} elseif (isset($_SERVER['SERVER_NAME'])) {
|
203 |
} elseif (isset($_SERVER['SERVER_ADDR'])) {
|
204 |
$uri = $uri->withHost($_SERVER['SERVER_ADDR']);
|
205 |
}
|
206 |
+
|
207 |
if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
|
208 |
$uri = $uri->withPort($_SERVER['SERVER_PORT']);
|
209 |
}
|
210 |
+
|
211 |
+
$hasQuery = false;
|
212 |
if (isset($_SERVER['REQUEST_URI'])) {
|
213 |
+
$requestUriParts = explode('?', $_SERVER['REQUEST_URI']);
|
214 |
$uri = $uri->withPath($requestUriParts[0]);
|
215 |
if (isset($requestUriParts[1])) {
|
216 |
+
$hasQuery = true;
|
217 |
$uri = $uri->withQuery($requestUriParts[1]);
|
218 |
}
|
219 |
}
|
220 |
+
|
221 |
if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
|
222 |
$uri = $uri->withQuery($_SERVER['QUERY_STRING']);
|
223 |
}
|
224 |
+
|
225 |
return $uri;
|
226 |
}
|
227 |
+
|
228 |
+
|
229 |
/**
|
230 |
* {@inheritdoc}
|
231 |
*/
|
233 |
{
|
234 |
return $this->serverParams;
|
235 |
}
|
236 |
+
|
237 |
/**
|
238 |
* {@inheritdoc}
|
239 |
*/
|
241 |
{
|
242 |
return $this->uploadedFiles;
|
243 |
}
|
244 |
+
|
245 |
/**
|
246 |
* {@inheritdoc}
|
247 |
*/
|
249 |
{
|
250 |
$new = clone $this;
|
251 |
$new->uploadedFiles = $uploadedFiles;
|
252 |
+
|
253 |
return $new;
|
254 |
}
|
255 |
+
|
256 |
/**
|
257 |
* {@inheritdoc}
|
258 |
*/
|
260 |
{
|
261 |
return $this->cookieParams;
|
262 |
}
|
263 |
+
|
264 |
/**
|
265 |
* {@inheritdoc}
|
266 |
*/
|
268 |
{
|
269 |
$new = clone $this;
|
270 |
$new->cookieParams = $cookies;
|
271 |
+
|
272 |
return $new;
|
273 |
}
|
274 |
+
|
275 |
/**
|
276 |
* {@inheritdoc}
|
277 |
*/
|
279 |
{
|
280 |
return $this->queryParams;
|
281 |
}
|
282 |
+
|
283 |
/**
|
284 |
* {@inheritdoc}
|
285 |
*/
|
287 |
{
|
288 |
$new = clone $this;
|
289 |
$new->queryParams = $query;
|
290 |
+
|
291 |
return $new;
|
292 |
}
|
293 |
+
|
294 |
/**
|
295 |
* {@inheritdoc}
|
296 |
*/
|
298 |
{
|
299 |
return $this->parsedBody;
|
300 |
}
|
301 |
+
|
302 |
/**
|
303 |
* {@inheritdoc}
|
304 |
*/
|
306 |
{
|
307 |
$new = clone $this;
|
308 |
$new->parsedBody = $data;
|
309 |
+
|
310 |
return $new;
|
311 |
}
|
312 |
+
|
313 |
/**
|
314 |
* {@inheritdoc}
|
315 |
*/
|
317 |
{
|
318 |
return $this->attributes;
|
319 |
}
|
320 |
+
|
321 |
/**
|
322 |
* {@inheritdoc}
|
323 |
*/
|
324 |
public function getAttribute($attribute, $default = null)
|
325 |
{
|
326 |
+
if (false === array_key_exists($attribute, $this->attributes)) {
|
327 |
return $default;
|
328 |
}
|
329 |
+
|
330 |
return $this->attributes[$attribute];
|
331 |
}
|
332 |
+
|
333 |
/**
|
334 |
* {@inheritdoc}
|
335 |
*/
|
337 |
{
|
338 |
$new = clone $this;
|
339 |
$new->attributes[$attribute] = $value;
|
340 |
+
|
341 |
return $new;
|
342 |
}
|
343 |
+
|
344 |
/**
|
345 |
* {@inheritdoc}
|
346 |
*/
|
347 |
public function withoutAttribute($attribute)
|
348 |
{
|
349 |
+
if (false === array_key_exists($attribute, $this->attributes)) {
|
350 |
return $this;
|
351 |
}
|
352 |
+
|
353 |
$new = clone $this;
|
354 |
unset($new->attributes[$attribute]);
|
355 |
+
|
356 |
return $new;
|
357 |
}
|
358 |
}
|
@@ -1,14 +1,14 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* PHP stream implementation.
|
8 |
*
|
9 |
* @var $stream
|
10 |
*/
|
11 |
-
class Stream implements
|
12 |
{
|
13 |
private $stream;
|
14 |
private $size;
|
@@ -17,8 +17,23 @@ class Stream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
17 |
private $writable;
|
18 |
private $uri;
|
19 |
private $customMetadata;
|
|
|
20 |
/** @var array Hash of readable and writable stream types */
|
21 |
-
private static $readWriteHash = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
/**
|
23 |
* This constructor accepts an associative array of options.
|
24 |
*
|
@@ -35,27 +50,35 @@ class Stream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
35 |
*/
|
36 |
public function __construct($stream, $options = [])
|
37 |
{
|
38 |
-
if (
|
39 |
throw new \InvalidArgumentException('Stream must be a resource');
|
40 |
}
|
|
|
41 |
if (isset($options['size'])) {
|
42 |
$this->size = $options['size'];
|
43 |
}
|
44 |
-
|
|
|
|
|
|
|
|
|
45 |
$this->stream = $stream;
|
46 |
-
$meta =
|
47 |
$this->seekable = $meta['seekable'];
|
48 |
$this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
|
49 |
$this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
|
50 |
$this->uri = $this->getMetadata('uri');
|
51 |
}
|
|
|
52 |
public function __get($name)
|
53 |
{
|
54 |
if ($name == 'stream') {
|
55 |
throw new \RuntimeException('The stream is detached');
|
56 |
}
|
|
|
57 |
throw new \BadMethodCallException('No value for ' . $name);
|
58 |
}
|
|
|
59 |
/**
|
60 |
* Closes the stream when the destructed
|
61 |
*/
|
@@ -63,98 +86,122 @@ class Stream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
63 |
{
|
64 |
$this->close();
|
65 |
}
|
|
|
66 |
public function __toString()
|
67 |
{
|
68 |
try {
|
69 |
$this->seek(0);
|
70 |
-
return (string)
|
71 |
} catch (\Exception $e) {
|
72 |
return '';
|
73 |
}
|
74 |
}
|
|
|
75 |
public function getContents()
|
76 |
{
|
77 |
-
$contents =
|
78 |
-
|
|
|
79 |
throw new \RuntimeException('Unable to read stream contents');
|
80 |
}
|
|
|
81 |
return $contents;
|
82 |
}
|
|
|
83 |
public function close()
|
84 |
{
|
85 |
if (isset($this->stream)) {
|
86 |
-
if (
|
87 |
-
|
88 |
}
|
89 |
$this->detach();
|
90 |
}
|
91 |
}
|
|
|
92 |
public function detach()
|
93 |
{
|
94 |
if (!isset($this->stream)) {
|
95 |
return null;
|
96 |
}
|
|
|
97 |
$result = $this->stream;
|
98 |
unset($this->stream);
|
99 |
$this->size = $this->uri = null;
|
100 |
-
$this->readable = $this->writable = $this->seekable =
|
|
|
101 |
return $result;
|
102 |
}
|
|
|
103 |
public function getSize()
|
104 |
{
|
105 |
if ($this->size !== null) {
|
106 |
return $this->size;
|
107 |
}
|
|
|
108 |
if (!isset($this->stream)) {
|
109 |
return null;
|
110 |
}
|
|
|
111 |
// Clear the stat cache if the stream has a URI
|
112 |
if ($this->uri) {
|
113 |
-
|
114 |
}
|
115 |
-
|
|
|
116 |
if (isset($stats['size'])) {
|
117 |
$this->size = $stats['size'];
|
118 |
return $this->size;
|
119 |
}
|
|
|
120 |
return null;
|
121 |
}
|
|
|
122 |
public function isReadable()
|
123 |
{
|
124 |
return $this->readable;
|
125 |
}
|
|
|
126 |
public function isWritable()
|
127 |
{
|
128 |
return $this->writable;
|
129 |
}
|
|
|
130 |
public function isSeekable()
|
131 |
{
|
132 |
return $this->seekable;
|
133 |
}
|
|
|
134 |
public function eof()
|
135 |
{
|
136 |
-
return !$this->stream ||
|
137 |
}
|
|
|
138 |
public function tell()
|
139 |
{
|
140 |
-
$result =
|
141 |
-
|
|
|
142 |
throw new \RuntimeException('Unable to determine stream position');
|
143 |
}
|
|
|
144 |
return $result;
|
145 |
}
|
|
|
146 |
public function rewind()
|
147 |
{
|
148 |
$this->seek(0);
|
149 |
}
|
150 |
-
|
|
|
151 |
{
|
152 |
if (!$this->seekable) {
|
153 |
throw new \RuntimeException('Stream is not seekable');
|
154 |
-
} elseif (
|
155 |
-
throw new \RuntimeException('Unable to seek to stream position '
|
|
|
156 |
}
|
157 |
}
|
|
|
158 |
public function read($length)
|
159 |
{
|
160 |
if (!$this->readable) {
|
@@ -163,38 +210,48 @@ class Stream implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
163 |
if ($length < 0) {
|
164 |
throw new \RuntimeException('Length parameter cannot be negative');
|
165 |
}
|
|
|
166 |
if (0 === $length) {
|
167 |
return '';
|
168 |
}
|
169 |
-
|
170 |
-
|
|
|
171 |
throw new \RuntimeException('Unable to read from stream');
|
172 |
}
|
|
|
173 |
return $string;
|
174 |
}
|
|
|
175 |
public function write($string)
|
176 |
{
|
177 |
if (!$this->writable) {
|
178 |
throw new \RuntimeException('Cannot write to a non-writable stream');
|
179 |
}
|
|
|
180 |
// We can't know the size after writing anything
|
181 |
$this->size = null;
|
182 |
-
$result =
|
183 |
-
|
|
|
184 |
throw new \RuntimeException('Unable to write to stream');
|
185 |
}
|
|
|
186 |
return $result;
|
187 |
}
|
|
|
188 |
public function getMetadata($key = null)
|
189 |
{
|
190 |
if (!isset($this->stream)) {
|
191 |
return $key ? null : [];
|
192 |
} elseif (!$key) {
|
193 |
-
return $this->customMetadata +
|
194 |
} elseif (isset($this->customMetadata[$key])) {
|
195 |
return $this->customMetadata[$key];
|
196 |
}
|
197 |
-
|
|
|
|
|
198 |
return isset($meta[$key]) ? $meta[$key] : null;
|
199 |
}
|
200 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* PHP stream implementation.
|
8 |
*
|
9 |
* @var $stream
|
10 |
*/
|
11 |
+
class Stream implements StreamInterface
|
12 |
{
|
13 |
private $stream;
|
14 |
private $size;
|
17 |
private $writable;
|
18 |
private $uri;
|
19 |
private $customMetadata;
|
20 |
+
|
21 |
/** @var array Hash of readable and writable stream types */
|
22 |
+
private static $readWriteHash = [
|
23 |
+
'read' => [
|
24 |
+
'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
|
25 |
+
'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
|
26 |
+
'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
|
27 |
+
'x+t' => true, 'c+t' => true, 'a+' => true
|
28 |
+
],
|
29 |
+
'write' => [
|
30 |
+
'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
|
31 |
+
'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
|
32 |
+
'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
|
33 |
+
'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
|
34 |
+
]
|
35 |
+
];
|
36 |
+
|
37 |
/**
|
38 |
* This constructor accepts an associative array of options.
|
39 |
*
|
50 |
*/
|
51 |
public function __construct($stream, $options = [])
|
52 |
{
|
53 |
+
if (!is_resource($stream)) {
|
54 |
throw new \InvalidArgumentException('Stream must be a resource');
|
55 |
}
|
56 |
+
|
57 |
if (isset($options['size'])) {
|
58 |
$this->size = $options['size'];
|
59 |
}
|
60 |
+
|
61 |
+
$this->customMetadata = isset($options['metadata'])
|
62 |
+
? $options['metadata']
|
63 |
+
: [];
|
64 |
+
|
65 |
$this->stream = $stream;
|
66 |
+
$meta = stream_get_meta_data($this->stream);
|
67 |
$this->seekable = $meta['seekable'];
|
68 |
$this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
|
69 |
$this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
|
70 |
$this->uri = $this->getMetadata('uri');
|
71 |
}
|
72 |
+
|
73 |
public function __get($name)
|
74 |
{
|
75 |
if ($name == 'stream') {
|
76 |
throw new \RuntimeException('The stream is detached');
|
77 |
}
|
78 |
+
|
79 |
throw new \BadMethodCallException('No value for ' . $name);
|
80 |
}
|
81 |
+
|
82 |
/**
|
83 |
* Closes the stream when the destructed
|
84 |
*/
|
86 |
{
|
87 |
$this->close();
|
88 |
}
|
89 |
+
|
90 |
public function __toString()
|
91 |
{
|
92 |
try {
|
93 |
$this->seek(0);
|
94 |
+
return (string) stream_get_contents($this->stream);
|
95 |
} catch (\Exception $e) {
|
96 |
return '';
|
97 |
}
|
98 |
}
|
99 |
+
|
100 |
public function getContents()
|
101 |
{
|
102 |
+
$contents = stream_get_contents($this->stream);
|
103 |
+
|
104 |
+
if ($contents === false) {
|
105 |
throw new \RuntimeException('Unable to read stream contents');
|
106 |
}
|
107 |
+
|
108 |
return $contents;
|
109 |
}
|
110 |
+
|
111 |
public function close()
|
112 |
{
|
113 |
if (isset($this->stream)) {
|
114 |
+
if (is_resource($this->stream)) {
|
115 |
+
fclose($this->stream);
|
116 |
}
|
117 |
$this->detach();
|
118 |
}
|
119 |
}
|
120 |
+
|
121 |
public function detach()
|
122 |
{
|
123 |
if (!isset($this->stream)) {
|
124 |
return null;
|
125 |
}
|
126 |
+
|
127 |
$result = $this->stream;
|
128 |
unset($this->stream);
|
129 |
$this->size = $this->uri = null;
|
130 |
+
$this->readable = $this->writable = $this->seekable = false;
|
131 |
+
|
132 |
return $result;
|
133 |
}
|
134 |
+
|
135 |
public function getSize()
|
136 |
{
|
137 |
if ($this->size !== null) {
|
138 |
return $this->size;
|
139 |
}
|
140 |
+
|
141 |
if (!isset($this->stream)) {
|
142 |
return null;
|
143 |
}
|
144 |
+
|
145 |
// Clear the stat cache if the stream has a URI
|
146 |
if ($this->uri) {
|
147 |
+
clearstatcache(true, $this->uri);
|
148 |
}
|
149 |
+
|
150 |
+
$stats = fstat($this->stream);
|
151 |
if (isset($stats['size'])) {
|
152 |
$this->size = $stats['size'];
|
153 |
return $this->size;
|
154 |
}
|
155 |
+
|
156 |
return null;
|
157 |
}
|
158 |
+
|
159 |
public function isReadable()
|
160 |
{
|
161 |
return $this->readable;
|
162 |
}
|
163 |
+
|
164 |
public function isWritable()
|
165 |
{
|
166 |
return $this->writable;
|
167 |
}
|
168 |
+
|
169 |
public function isSeekable()
|
170 |
{
|
171 |
return $this->seekable;
|
172 |
}
|
173 |
+
|
174 |
public function eof()
|
175 |
{
|
176 |
+
return !$this->stream || feof($this->stream);
|
177 |
}
|
178 |
+
|
179 |
public function tell()
|
180 |
{
|
181 |
+
$result = ftell($this->stream);
|
182 |
+
|
183 |
+
if ($result === false) {
|
184 |
throw new \RuntimeException('Unable to determine stream position');
|
185 |
}
|
186 |
+
|
187 |
return $result;
|
188 |
}
|
189 |
+
|
190 |
public function rewind()
|
191 |
{
|
192 |
$this->seek(0);
|
193 |
}
|
194 |
+
|
195 |
+
public function seek($offset, $whence = SEEK_SET)
|
196 |
{
|
197 |
if (!$this->seekable) {
|
198 |
throw new \RuntimeException('Stream is not seekable');
|
199 |
+
} elseif (fseek($this->stream, $offset, $whence) === -1) {
|
200 |
+
throw new \RuntimeException('Unable to seek to stream position '
|
201 |
+
. $offset . ' with whence ' . var_export($whence, true));
|
202 |
}
|
203 |
}
|
204 |
+
|
205 |
public function read($length)
|
206 |
{
|
207 |
if (!$this->readable) {
|
210 |
if ($length < 0) {
|
211 |
throw new \RuntimeException('Length parameter cannot be negative');
|
212 |
}
|
213 |
+
|
214 |
if (0 === $length) {
|
215 |
return '';
|
216 |
}
|
217 |
+
|
218 |
+
$string = fread($this->stream, $length);
|
219 |
+
if (false === $string) {
|
220 |
throw new \RuntimeException('Unable to read from stream');
|
221 |
}
|
222 |
+
|
223 |
return $string;
|
224 |
}
|
225 |
+
|
226 |
public function write($string)
|
227 |
{
|
228 |
if (!$this->writable) {
|
229 |
throw new \RuntimeException('Cannot write to a non-writable stream');
|
230 |
}
|
231 |
+
|
232 |
// We can't know the size after writing anything
|
233 |
$this->size = null;
|
234 |
+
$result = fwrite($this->stream, $string);
|
235 |
+
|
236 |
+
if ($result === false) {
|
237 |
throw new \RuntimeException('Unable to write to stream');
|
238 |
}
|
239 |
+
|
240 |
return $result;
|
241 |
}
|
242 |
+
|
243 |
public function getMetadata($key = null)
|
244 |
{
|
245 |
if (!isset($this->stream)) {
|
246 |
return $key ? null : [];
|
247 |
} elseif (!$key) {
|
248 |
+
return $this->customMetadata + stream_get_meta_data($this->stream);
|
249 |
} elseif (isset($this->customMetadata[$key])) {
|
250 |
return $this->customMetadata[$key];
|
251 |
}
|
252 |
+
|
253 |
+
$meta = stream_get_meta_data($this->stream);
|
254 |
+
|
255 |
return isset($meta[$key]) ? $meta[$key] : null;
|
256 |
}
|
257 |
}
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Stream decorator trait
|
8 |
* @property StreamInterface stream
|
@@ -12,10 +12,11 @@ trait StreamDecoratorTrait
|
|
12 |
/**
|
13 |
* @param StreamInterface $stream Stream to decorate
|
14 |
*/
|
15 |
-
public function __construct(
|
16 |
{
|
17 |
$this->stream = $stream;
|
18 |
}
|
|
|
19 |
/**
|
20 |
* Magic method used to create a new stream if streams are not added in
|
21 |
* the constructor of a decorator (e.g., LazyOpenStream).
|
@@ -30,8 +31,10 @@ trait StreamDecoratorTrait
|
|
30 |
$this->stream = $this->createStream();
|
31 |
return $this->stream;
|
32 |
}
|
33 |
-
|
|
|
34 |
}
|
|
|
35 |
public function __toString()
|
36 |
{
|
37 |
try {
|
@@ -41,14 +44,17 @@ trait StreamDecoratorTrait
|
|
41 |
return $this->getContents();
|
42 |
} catch (\Exception $e) {
|
43 |
// Really, PHP? https://bugs.php.net/bug.php?id=53648
|
44 |
-
|
|
|
45 |
return '';
|
46 |
}
|
47 |
}
|
|
|
48 |
public function getContents()
|
49 |
{
|
50 |
return copy_to_string($this);
|
51 |
}
|
|
|
52 |
/**
|
53 |
* Allow decorators to implement custom methods
|
54 |
*
|
@@ -59,62 +65,77 @@ trait StreamDecoratorTrait
|
|
59 |
*/
|
60 |
public function __call($method, array $args)
|
61 |
{
|
62 |
-
$result =
|
|
|
63 |
// Always return the wrapped object if the result is a return $this
|
64 |
return $result === $this->stream ? $this : $result;
|
65 |
}
|
|
|
66 |
public function close()
|
67 |
{
|
68 |
$this->stream->close();
|
69 |
}
|
|
|
70 |
public function getMetadata($key = null)
|
71 |
{
|
72 |
return $this->stream->getMetadata($key);
|
73 |
}
|
|
|
74 |
public function detach()
|
75 |
{
|
76 |
return $this->stream->detach();
|
77 |
}
|
|
|
78 |
public function getSize()
|
79 |
{
|
80 |
return $this->stream->getSize();
|
81 |
}
|
|
|
82 |
public function eof()
|
83 |
{
|
84 |
return $this->stream->eof();
|
85 |
}
|
|
|
86 |
public function tell()
|
87 |
{
|
88 |
return $this->stream->tell();
|
89 |
}
|
|
|
90 |
public function isReadable()
|
91 |
{
|
92 |
return $this->stream->isReadable();
|
93 |
}
|
|
|
94 |
public function isWritable()
|
95 |
{
|
96 |
return $this->stream->isWritable();
|
97 |
}
|
|
|
98 |
public function isSeekable()
|
99 |
{
|
100 |
return $this->stream->isSeekable();
|
101 |
}
|
|
|
102 |
public function rewind()
|
103 |
{
|
104 |
$this->seek(0);
|
105 |
}
|
106 |
-
|
|
|
107 |
{
|
108 |
$this->stream->seek($offset, $whence);
|
109 |
}
|
|
|
110 |
public function read($length)
|
111 |
{
|
112 |
return $this->stream->read($length);
|
113 |
}
|
|
|
114 |
public function write($string)
|
115 |
{
|
116 |
return $this->stream->write($string);
|
117 |
}
|
|
|
118 |
/**
|
119 |
* Implement in subclasses to dynamically create streams when requested.
|
120 |
*
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Stream decorator trait
|
8 |
* @property StreamInterface stream
|
12 |
/**
|
13 |
* @param StreamInterface $stream Stream to decorate
|
14 |
*/
|
15 |
+
public function __construct(StreamInterface $stream)
|
16 |
{
|
17 |
$this->stream = $stream;
|
18 |
}
|
19 |
+
|
20 |
/**
|
21 |
* Magic method used to create a new stream if streams are not added in
|
22 |
* the constructor of a decorator (e.g., LazyOpenStream).
|
31 |
$this->stream = $this->createStream();
|
32 |
return $this->stream;
|
33 |
}
|
34 |
+
|
35 |
+
throw new \UnexpectedValueException("$name not found on class");
|
36 |
}
|
37 |
+
|
38 |
public function __toString()
|
39 |
{
|
40 |
try {
|
44 |
return $this->getContents();
|
45 |
} catch (\Exception $e) {
|
46 |
// Really, PHP? https://bugs.php.net/bug.php?id=53648
|
47 |
+
trigger_error('StreamDecorator::__toString exception: '
|
48 |
+
. (string) $e, E_USER_ERROR);
|
49 |
return '';
|
50 |
}
|
51 |
}
|
52 |
+
|
53 |
public function getContents()
|
54 |
{
|
55 |
return copy_to_string($this);
|
56 |
}
|
57 |
+
|
58 |
/**
|
59 |
* Allow decorators to implement custom methods
|
60 |
*
|
65 |
*/
|
66 |
public function __call($method, array $args)
|
67 |
{
|
68 |
+
$result = call_user_func_array([$this->stream, $method], $args);
|
69 |
+
|
70 |
// Always return the wrapped object if the result is a return $this
|
71 |
return $result === $this->stream ? $this : $result;
|
72 |
}
|
73 |
+
|
74 |
public function close()
|
75 |
{
|
76 |
$this->stream->close();
|
77 |
}
|
78 |
+
|
79 |
public function getMetadata($key = null)
|
80 |
{
|
81 |
return $this->stream->getMetadata($key);
|
82 |
}
|
83 |
+
|
84 |
public function detach()
|
85 |
{
|
86 |
return $this->stream->detach();
|
87 |
}
|
88 |
+
|
89 |
public function getSize()
|
90 |
{
|
91 |
return $this->stream->getSize();
|
92 |
}
|
93 |
+
|
94 |
public function eof()
|
95 |
{
|
96 |
return $this->stream->eof();
|
97 |
}
|
98 |
+
|
99 |
public function tell()
|
100 |
{
|
101 |
return $this->stream->tell();
|
102 |
}
|
103 |
+
|
104 |
public function isReadable()
|
105 |
{
|
106 |
return $this->stream->isReadable();
|
107 |
}
|
108 |
+
|
109 |
public function isWritable()
|
110 |
{
|
111 |
return $this->stream->isWritable();
|
112 |
}
|
113 |
+
|
114 |
public function isSeekable()
|
115 |
{
|
116 |
return $this->stream->isSeekable();
|
117 |
}
|
118 |
+
|
119 |
public function rewind()
|
120 |
{
|
121 |
$this->seek(0);
|
122 |
}
|
123 |
+
|
124 |
+
public function seek($offset, $whence = SEEK_SET)
|
125 |
{
|
126 |
$this->stream->seek($offset, $whence);
|
127 |
}
|
128 |
+
|
129 |
public function read($length)
|
130 |
{
|
131 |
return $this->stream->read($length);
|
132 |
}
|
133 |
+
|
134 |
public function write($string)
|
135 |
{
|
136 |
return $this->stream->write($string);
|
137 |
}
|
138 |
+
|
139 |
/**
|
140 |
* Implement in subclasses to dynamically create streams when requested.
|
141 |
*
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
6 |
/**
|
7 |
* Converts Guzzle streams into PHP stream resources.
|
8 |
*/
|
@@ -10,10 +10,13 @@ class StreamWrapper
|
|
10 |
{
|
11 |
/** @var resource */
|
12 |
public $context;
|
|
|
13 |
/** @var StreamInterface */
|
14 |
private $stream;
|
|
|
15 |
/** @var string r, r+, or w */
|
16 |
private $mode;
|
|
|
17 |
/**
|
18 |
* Returns a resource representing the stream.
|
19 |
*
|
@@ -22,61 +25,97 @@ class StreamWrapper
|
|
22 |
* @return resource
|
23 |
* @throws \InvalidArgumentException if stream is not readable or writable
|
24 |
*/
|
25 |
-
public static function getResource(
|
26 |
{
|
27 |
self::register();
|
|
|
28 |
if ($stream->isReadable()) {
|
29 |
$mode = $stream->isWritable() ? 'r+' : 'r';
|
30 |
} elseif ($stream->isWritable()) {
|
31 |
$mode = 'w';
|
32 |
} else {
|
33 |
-
throw new \InvalidArgumentException('The stream must be readable, '
|
|
|
34 |
}
|
35 |
-
|
|
|
|
|
|
|
36 |
}
|
|
|
37 |
/**
|
38 |
* Registers the stream wrapper if needed
|
39 |
*/
|
40 |
public static function register()
|
41 |
{
|
42 |
-
if (
|
43 |
-
|
44 |
}
|
45 |
}
|
|
|
46 |
public function stream_open($path, $mode, $options, &$opened_path)
|
47 |
{
|
48 |
-
$options =
|
|
|
49 |
if (!isset($options['guzzle']['stream'])) {
|
50 |
-
return
|
51 |
}
|
|
|
52 |
$this->mode = $mode;
|
53 |
$this->stream = $options['guzzle']['stream'];
|
54 |
-
|
|
|
55 |
}
|
|
|
56 |
public function stream_read($count)
|
57 |
{
|
58 |
return $this->stream->read($count);
|
59 |
}
|
|
|
60 |
public function stream_write($data)
|
61 |
{
|
62 |
return (int) $this->stream->write($data);
|
63 |
}
|
|
|
64 |
public function stream_tell()
|
65 |
{
|
66 |
return $this->stream->tell();
|
67 |
}
|
|
|
68 |
public function stream_eof()
|
69 |
{
|
70 |
return $this->stream->eof();
|
71 |
}
|
|
|
72 |
public function stream_seek($offset, $whence)
|
73 |
{
|
74 |
$this->stream->seek($offset, $whence);
|
75 |
-
|
|
|
76 |
}
|
|
|
77 |
public function stream_stat()
|
78 |
{
|
79 |
-
static $modeMap = [
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Converts Guzzle streams into PHP stream resources.
|
8 |
*/
|
10 |
{
|
11 |
/** @var resource */
|
12 |
public $context;
|
13 |
+
|
14 |
/** @var StreamInterface */
|
15 |
private $stream;
|
16 |
+
|
17 |
/** @var string r, r+, or w */
|
18 |
private $mode;
|
19 |
+
|
20 |
/**
|
21 |
* Returns a resource representing the stream.
|
22 |
*
|
25 |
* @return resource
|
26 |
* @throws \InvalidArgumentException if stream is not readable or writable
|
27 |
*/
|
28 |
+
public static function getResource(StreamInterface $stream)
|
29 |
{
|
30 |
self::register();
|
31 |
+
|
32 |
if ($stream->isReadable()) {
|
33 |
$mode = $stream->isWritable() ? 'r+' : 'r';
|
34 |
} elseif ($stream->isWritable()) {
|
35 |
$mode = 'w';
|
36 |
} else {
|
37 |
+
throw new \InvalidArgumentException('The stream must be readable, '
|
38 |
+
. 'writable, or both.');
|
39 |
}
|
40 |
+
|
41 |
+
return fopen('guzzle://stream', $mode, null, stream_context_create([
|
42 |
+
'guzzle' => ['stream' => $stream]
|
43 |
+
]));
|
44 |
}
|
45 |
+
|
46 |
/**
|
47 |
* Registers the stream wrapper if needed
|
48 |
*/
|
49 |
public static function register()
|
50 |
{
|
51 |
+
if (!in_array('guzzle', stream_get_wrappers())) {
|
52 |
+
stream_wrapper_register('guzzle', __CLASS__);
|
53 |
}
|
54 |
}
|
55 |
+
|
56 |
public function stream_open($path, $mode, $options, &$opened_path)
|
57 |
{
|
58 |
+
$options = stream_context_get_options($this->context);
|
59 |
+
|
60 |
if (!isset($options['guzzle']['stream'])) {
|
61 |
+
return false;
|
62 |
}
|
63 |
+
|
64 |
$this->mode = $mode;
|
65 |
$this->stream = $options['guzzle']['stream'];
|
66 |
+
|
67 |
+
return true;
|
68 |
}
|
69 |
+
|
70 |
public function stream_read($count)
|
71 |
{
|
72 |
return $this->stream->read($count);
|
73 |
}
|
74 |
+
|
75 |
public function stream_write($data)
|
76 |
{
|
77 |
return (int) $this->stream->write($data);
|
78 |
}
|
79 |
+
|
80 |
public function stream_tell()
|
81 |
{
|
82 |
return $this->stream->tell();
|
83 |
}
|
84 |
+
|
85 |
public function stream_eof()
|
86 |
{
|
87 |
return $this->stream->eof();
|
88 |
}
|
89 |
+
|
90 |
public function stream_seek($offset, $whence)
|
91 |
{
|
92 |
$this->stream->seek($offset, $whence);
|
93 |
+
|
94 |
+
return true;
|
95 |
}
|
96 |
+
|
97 |
public function stream_stat()
|
98 |
{
|
99 |
+
static $modeMap = [
|
100 |
+
'r' => 33060,
|
101 |
+
'r+' => 33206,
|
102 |
+
'w' => 33188
|
103 |
+
];
|
104 |
+
|
105 |
+
return [
|
106 |
+
'dev' => 0,
|
107 |
+
'ino' => 0,
|
108 |
+
'mode' => $modeMap[$this->mode],
|
109 |
+
'nlink' => 0,
|
110 |
+
'uid' => 0,
|
111 |
+
'gid' => 0,
|
112 |
+
'rdev' => 0,
|
113 |
+
'size' => $this->stream->getSize() ?: 0,
|
114 |
+
'atime' => 0,
|
115 |
+
'mtime' => 0,
|
116 |
+
'ctime' => 0,
|
117 |
+
'blksize' => 0,
|
118 |
+
'blocks' => 0
|
119 |
+
];
|
120 |
}
|
121 |
}
|
@@ -1,45 +1,62 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\GuzzleHttp\Psr7;
|
4 |
|
5 |
use InvalidArgumentException;
|
6 |
-
use
|
7 |
-
use
|
8 |
use RuntimeException;
|
9 |
-
|
|
|
10 |
{
|
11 |
/**
|
12 |
* @var int[]
|
13 |
*/
|
14 |
-
private static $errors = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
/**
|
16 |
* @var string
|
17 |
*/
|
18 |
private $clientFilename;
|
|
|
19 |
/**
|
20 |
* @var string
|
21 |
*/
|
22 |
private $clientMediaType;
|
|
|
23 |
/**
|
24 |
* @var int
|
25 |
*/
|
26 |
private $error;
|
|
|
27 |
/**
|
28 |
* @var null|string
|
29 |
*/
|
30 |
private $file;
|
|
|
31 |
/**
|
32 |
* @var bool
|
33 |
*/
|
34 |
-
private $moved =
|
|
|
35 |
/**
|
36 |
* @var int
|
37 |
*/
|
38 |
private $size;
|
|
|
39 |
/**
|
40 |
* @var StreamInterface|null
|
41 |
*/
|
42 |
private $stream;
|
|
|
43 |
/**
|
44 |
* @param StreamInterface|string|resource $streamOrFile
|
45 |
* @param int $size
|
@@ -47,16 +64,23 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
47 |
* @param string|null $clientFilename
|
48 |
* @param string|null $clientMediaType
|
49 |
*/
|
50 |
-
public function __construct(
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
52 |
$this->setError($errorStatus);
|
53 |
$this->setSize($size);
|
54 |
$this->setClientFilename($clientFilename);
|
55 |
$this->setClientMediaType($clientMediaType);
|
|
|
56 |
if ($this->isOk()) {
|
57 |
$this->setStreamOrFile($streamOrFile);
|
58 |
}
|
59 |
}
|
|
|
60 |
/**
|
61 |
* Depending on the value set file or stream variable
|
62 |
*
|
@@ -65,79 +89,103 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
65 |
*/
|
66 |
private function setStreamOrFile($streamOrFile)
|
67 |
{
|
68 |
-
if (
|
69 |
$this->file = $streamOrFile;
|
70 |
-
} elseif (
|
71 |
-
$this->stream = new
|
72 |
-
} elseif ($streamOrFile instanceof
|
73 |
$this->stream = $streamOrFile;
|
74 |
} else {
|
75 |
-
throw new
|
|
|
|
|
76 |
}
|
77 |
}
|
|
|
78 |
/**
|
79 |
* @param int $error
|
80 |
* @throws InvalidArgumentException
|
81 |
*/
|
82 |
private function setError($error)
|
83 |
{
|
84 |
-
if (
|
85 |
-
throw new
|
|
|
|
|
86 |
}
|
87 |
-
|
88 |
-
|
|
|
|
|
|
|
89 |
}
|
|
|
90 |
$this->error = $error;
|
91 |
}
|
|
|
92 |
/**
|
93 |
* @param int $size
|
94 |
* @throws InvalidArgumentException
|
95 |
*/
|
96 |
private function setSize($size)
|
97 |
{
|
98 |
-
if (
|
99 |
-
throw new
|
|
|
|
|
100 |
}
|
|
|
101 |
$this->size = $size;
|
102 |
}
|
|
|
103 |
/**
|
104 |
* @param mixed $param
|
105 |
* @return boolean
|
106 |
*/
|
107 |
private function isStringOrNull($param)
|
108 |
{
|
109 |
-
return
|
110 |
}
|
|
|
111 |
/**
|
112 |
* @param mixed $param
|
113 |
* @return boolean
|
114 |
*/
|
115 |
private function isStringNotEmpty($param)
|
116 |
{
|
117 |
-
return
|
118 |
}
|
|
|
119 |
/**
|
120 |
* @param string|null $clientFilename
|
121 |
* @throws InvalidArgumentException
|
122 |
*/
|
123 |
private function setClientFilename($clientFilename)
|
124 |
{
|
125 |
-
if (
|
126 |
-
throw new
|
|
|
|
|
127 |
}
|
|
|
128 |
$this->clientFilename = $clientFilename;
|
129 |
}
|
|
|
130 |
/**
|
131 |
* @param string|null $clientMediaType
|
132 |
* @throws InvalidArgumentException
|
133 |
*/
|
134 |
private function setClientMediaType($clientMediaType)
|
135 |
{
|
136 |
-
if (
|
137 |
-
throw new
|
|
|
|
|
138 |
}
|
|
|
139 |
$this->clientMediaType = $clientMediaType;
|
140 |
}
|
|
|
141 |
/**
|
142 |
* Return true if there is no upload error
|
143 |
*
|
@@ -145,8 +193,9 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
145 |
*/
|
146 |
private function isOk()
|
147 |
{
|
148 |
-
return $this->error ===
|
149 |
}
|
|
|
150 |
/**
|
151 |
* @return boolean
|
152 |
*/
|
@@ -154,18 +203,21 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
154 |
{
|
155 |
return $this->moved;
|
156 |
}
|
|
|
157 |
/**
|
158 |
* @throws RuntimeException if is moved or not ok
|
159 |
*/
|
160 |
private function validateActive()
|
161 |
{
|
162 |
-
if (
|
163 |
-
throw new
|
164 |
}
|
|
|
165 |
if ($this->isMoved()) {
|
166 |
-
throw new
|
167 |
}
|
168 |
}
|
|
|
169 |
/**
|
170 |
* {@inheritdoc}
|
171 |
* @throws RuntimeException if the upload was not successful.
|
@@ -173,11 +225,14 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
173 |
public function getStream()
|
174 |
{
|
175 |
$this->validateActive();
|
176 |
-
|
|
|
177 |
return $this->stream;
|
178 |
}
|
179 |
-
|
|
|
180 |
}
|
|
|
181 |
/**
|
182 |
* {@inheritdoc}
|
183 |
*
|
@@ -192,19 +247,33 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
192 |
public function moveTo($targetPath)
|
193 |
{
|
194 |
$this->validateActive();
|
195 |
-
|
196 |
-
|
|
|
|
|
|
|
197 |
}
|
|
|
198 |
if ($this->file) {
|
199 |
-
$this->moved =
|
|
|
|
|
200 |
} else {
|
201 |
-
copy_to_stream(
|
202 |
-
|
|
|
|
|
|
|
|
|
203 |
}
|
204 |
-
|
205 |
-
|
|
|
|
|
|
|
206 |
}
|
207 |
}
|
|
|
208 |
/**
|
209 |
* {@inheritdoc}
|
210 |
*
|
@@ -214,6 +283,7 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
214 |
{
|
215 |
return $this->size;
|
216 |
}
|
|
|
217 |
/**
|
218 |
* {@inheritdoc}
|
219 |
*
|
@@ -224,6 +294,7 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
224 |
{
|
225 |
return $this->error;
|
226 |
}
|
|
|
227 |
/**
|
228 |
* {@inheritdoc}
|
229 |
*
|
@@ -234,6 +305,7 @@ class UploadedFile implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Uploaded
|
|
234 |
{
|
235 |
return $this->clientFilename;
|
236 |
}
|
|
|
237 |
/**
|
238 |
* {@inheritdoc}
|
239 |
*/
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
|
|
3 |
|
4 |
use InvalidArgumentException;
|
5 |
+
use Psr\Http\Message\StreamInterface;
|
6 |
+
use Psr\Http\Message\UploadedFileInterface;
|
7 |
use RuntimeException;
|
8 |
+
|
9 |
+
class UploadedFile implements UploadedFileInterface
|
10 |
{
|
11 |
/**
|
12 |
* @var int[]
|
13 |
*/
|
14 |
+
private static $errors = [
|
15 |
+
UPLOAD_ERR_OK,
|
16 |
+
UPLOAD_ERR_INI_SIZE,
|
17 |
+
UPLOAD_ERR_FORM_SIZE,
|
18 |
+
UPLOAD_ERR_PARTIAL,
|
19 |
+
UPLOAD_ERR_NO_FILE,
|
20 |
+
UPLOAD_ERR_NO_TMP_DIR,
|
21 |
+
UPLOAD_ERR_CANT_WRITE,
|
22 |
+
UPLOAD_ERR_EXTENSION,
|
23 |
+
];
|
24 |
+
|
25 |
/**
|
26 |
* @var string
|
27 |
*/
|
28 |
private $clientFilename;
|
29 |
+
|
30 |
/**
|
31 |
* @var string
|
32 |
*/
|
33 |
private $clientMediaType;
|
34 |
+
|
35 |
/**
|
36 |
* @var int
|
37 |
*/
|
38 |
private $error;
|
39 |
+
|
40 |
/**
|
41 |
* @var null|string
|
42 |
*/
|
43 |
private $file;
|
44 |
+
|
45 |
/**
|
46 |
* @var bool
|
47 |
*/
|
48 |
+
private $moved = false;
|
49 |
+
|
50 |
/**
|
51 |
* @var int
|
52 |
*/
|
53 |
private $size;
|
54 |
+
|
55 |
/**
|
56 |
* @var StreamInterface|null
|
57 |
*/
|
58 |
private $stream;
|
59 |
+
|
60 |
/**
|
61 |
* @param StreamInterface|string|resource $streamOrFile
|
62 |
* @param int $size
|
64 |
* @param string|null $clientFilename
|
65 |
* @param string|null $clientMediaType
|
66 |
*/
|
67 |
+
public function __construct(
|
68 |
+
$streamOrFile,
|
69 |
+
$size,
|
70 |
+
$errorStatus,
|
71 |
+
$clientFilename = null,
|
72 |
+
$clientMediaType = null
|
73 |
+
) {
|
74 |
$this->setError($errorStatus);
|
75 |
$this->setSize($size);
|
76 |
$this->setClientFilename($clientFilename);
|
77 |
$this->setClientMediaType($clientMediaType);
|
78 |
+
|
79 |
if ($this->isOk()) {
|
80 |
$this->setStreamOrFile($streamOrFile);
|
81 |
}
|
82 |
}
|
83 |
+
|
84 |
/**
|
85 |
* Depending on the value set file or stream variable
|
86 |
*
|
89 |
*/
|
90 |
private function setStreamOrFile($streamOrFile)
|
91 |
{
|
92 |
+
if (is_string($streamOrFile)) {
|
93 |
$this->file = $streamOrFile;
|
94 |
+
} elseif (is_resource($streamOrFile)) {
|
95 |
+
$this->stream = new Stream($streamOrFile);
|
96 |
+
} elseif ($streamOrFile instanceof StreamInterface) {
|
97 |
$this->stream = $streamOrFile;
|
98 |
} else {
|
99 |
+
throw new InvalidArgumentException(
|
100 |
+
'Invalid stream or file provided for UploadedFile'
|
101 |
+
);
|
102 |
}
|
103 |
}
|
104 |
+
|
105 |
/**
|
106 |
* @param int $error
|
107 |
* @throws InvalidArgumentException
|
108 |
*/
|
109 |
private function setError($error)
|
110 |
{
|
111 |
+
if (false === is_int($error)) {
|
112 |
+
throw new InvalidArgumentException(
|
113 |
+
'Upload file error status must be an integer'
|
114 |
+
);
|
115 |
}
|
116 |
+
|
117 |
+
if (false === in_array($error, UploadedFile::$errors)) {
|
118 |
+
throw new InvalidArgumentException(
|
119 |
+
'Invalid error status for UploadedFile'
|
120 |
+
);
|
121 |
}
|
122 |
+
|
123 |
$this->error = $error;
|
124 |
}
|
125 |
+
|
126 |
/**
|
127 |
* @param int $size
|
128 |
* @throws InvalidArgumentException
|
129 |
*/
|
130 |
private function setSize($size)
|
131 |
{
|
132 |
+
if (false === is_int($size)) {
|
133 |
+
throw new InvalidArgumentException(
|
134 |
+
'Upload file size must be an integer'
|
135 |
+
);
|
136 |
}
|
137 |
+
|
138 |
$this->size = $size;
|
139 |
}
|
140 |
+
|
141 |
/**
|
142 |
* @param mixed $param
|
143 |
* @return boolean
|
144 |
*/
|
145 |
private function isStringOrNull($param)
|
146 |
{
|
147 |
+
return in_array(gettype($param), ['string', 'NULL']);
|
148 |
}
|
149 |
+
|
150 |
/**
|
151 |
* @param mixed $param
|
152 |
* @return boolean
|
153 |
*/
|
154 |
private function isStringNotEmpty($param)
|
155 |
{
|
156 |
+
return is_string($param) && false === empty($param);
|
157 |
}
|
158 |
+
|
159 |
/**
|
160 |
* @param string|null $clientFilename
|
161 |
* @throws InvalidArgumentException
|
162 |
*/
|
163 |
private function setClientFilename($clientFilename)
|
164 |
{
|
165 |
+
if (false === $this->isStringOrNull($clientFilename)) {
|
166 |
+
throw new InvalidArgumentException(
|
167 |
+
'Upload file client filename must be a string or null'
|
168 |
+
);
|
169 |
}
|
170 |
+
|
171 |
$this->clientFilename = $clientFilename;
|
172 |
}
|
173 |
+
|
174 |
/**
|
175 |
* @param string|null $clientMediaType
|
176 |
* @throws InvalidArgumentException
|
177 |
*/
|
178 |
private function setClientMediaType($clientMediaType)
|
179 |
{
|
180 |
+
if (false === $this->isStringOrNull($clientMediaType)) {
|
181 |
+
throw new InvalidArgumentException(
|
182 |
+
'Upload file client media type must be a string or null'
|
183 |
+
);
|
184 |
}
|
185 |
+
|
186 |
$this->clientMediaType = $clientMediaType;
|
187 |
}
|
188 |
+
|
189 |
/**
|
190 |
* Return true if there is no upload error
|
191 |
*
|
193 |
*/
|
194 |
private function isOk()
|
195 |
{
|
196 |
+
return $this->error === UPLOAD_ERR_OK;
|
197 |
}
|
198 |
+
|
199 |
/**
|
200 |
* @return boolean
|
201 |
*/
|
203 |
{
|
204 |
return $this->moved;
|
205 |
}
|
206 |
+
|
207 |
/**
|
208 |
* @throws RuntimeException if is moved or not ok
|
209 |
*/
|
210 |
private function validateActive()
|
211 |
{
|
212 |
+
if (false === $this->isOk()) {
|
213 |
+
throw new RuntimeException('Cannot retrieve stream due to upload error');
|
214 |
}
|
215 |
+
|
216 |
if ($this->isMoved()) {
|
217 |
+
throw new RuntimeException('Cannot retrieve stream after it has already been moved');
|
218 |
}
|
219 |
}
|
220 |
+
|
221 |
/**
|
222 |
* {@inheritdoc}
|
223 |
* @throws RuntimeException if the upload was not successful.
|
225 |
public function getStream()
|
226 |
{
|
227 |
$this->validateActive();
|
228 |
+
|
229 |
+
if ($this->stream instanceof StreamInterface) {
|
230 |
return $this->stream;
|
231 |
}
|
232 |
+
|
233 |
+
return new LazyOpenStream($this->file, 'r+');
|
234 |
}
|
235 |
+
|
236 |
/**
|
237 |
* {@inheritdoc}
|
238 |
*
|
247 |
public function moveTo($targetPath)
|
248 |
{
|
249 |
$this->validateActive();
|
250 |
+
|
251 |
+
if (false === $this->isStringNotEmpty($targetPath)) {
|
252 |
+
throw new InvalidArgumentException(
|
253 |
+
'Invalid path provided for move operation; must be a non-empty string'
|
254 |
+
);
|
255 |
}
|
256 |
+
|
257 |
if ($this->file) {
|
258 |
+
$this->moved = php_sapi_name() == 'cli'
|
259 |
+
? rename($this->file, $targetPath)
|
260 |
+
: move_uploaded_file($this->file, $targetPath);
|
261 |
} else {
|
262 |
+
copy_to_stream(
|
263 |
+
$this->getStream(),
|
264 |
+
new LazyOpenStream($targetPath, 'w')
|
265 |
+
);
|
266 |
+
|
267 |
+
$this->moved = true;
|
268 |
}
|
269 |
+
|
270 |
+
if (false === $this->moved) {
|
271 |
+
throw new RuntimeException(
|
272 |
+
sprintf('Uploaded file could not be moved to %s', $targetPath)
|
273 |
+
);
|
274 |
}
|
275 |
}
|
276 |
+
|
277 |
/**
|
278 |
* {@inheritdoc}
|
279 |
*
|
283 |
{
|
284 |
return $this->size;
|
285 |
}
|
286 |
+
|
287 |
/**
|
288 |
* {@inheritdoc}
|
289 |
*
|
294 |
{
|
295 |
return $this->error;
|
296 |
}
|
297 |
+
|
298 |
/**
|
299 |
* {@inheritdoc}
|
300 |
*
|
305 |
{
|
306 |
return $this->clientFilename;
|
307 |
}
|
308 |
+
|
309 |
/**
|
310 |
* {@inheritdoc}
|
311 |
*/
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
6 |
/**
|
7 |
* PSR-7 URI implementation.
|
8 |
*
|
@@ -10,7 +10,7 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
|
10 |
* @author Tobias Schultze
|
11 |
* @author Matthew Weier O'Phinney
|
12 |
*/
|
13 |
-
class Uri implements
|
14 |
{
|
15 |
/**
|
16 |
* Absolute http and https URIs require a host per RFC 7230 Section 2.7
|
@@ -19,24 +19,46 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
19 |
* valid URI.
|
20 |
*/
|
21 |
const HTTP_DEFAULT_HOST = 'localhost';
|
22 |
-
|
23 |
-
private static $
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
private static $replaceQuery = ['=' => '%3D', '&' => '%26'];
|
|
|
26 |
/** @var string Uri scheme. */
|
27 |
private $scheme = '';
|
|
|
28 |
/** @var string Uri user info. */
|
29 |
private $userInfo = '';
|
|
|
30 |
/** @var string Uri host. */
|
31 |
private $host = '';
|
|
|
32 |
/** @var int|null Uri port. */
|
33 |
private $port;
|
|
|
34 |
/** @var string Uri path. */
|
35 |
private $path = '';
|
|
|
36 |
/** @var string Uri query string. */
|
37 |
private $query = '';
|
|
|
38 |
/** @var string Uri fragment. */
|
39 |
private $fragment = '';
|
|
|
40 |
/**
|
41 |
* @param string $uri URI to parse
|
42 |
*/
|
@@ -44,17 +66,25 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
44 |
{
|
45 |
// weak type check to also accept null until we can add scalar type hints
|
46 |
if ($uri != '') {
|
47 |
-
$parts =
|
48 |
-
if ($parts ===
|
49 |
-
throw new \InvalidArgumentException("Unable to parse URI:
|
50 |
}
|
51 |
$this->applyParts($parts);
|
52 |
}
|
53 |
}
|
|
|
54 |
public function __toString()
|
55 |
{
|
56 |
-
return self::composeComponents(
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
}
|
|
|
58 |
/**
|
59 |
* Composes a URI reference string from its various components.
|
60 |
*
|
@@ -84,22 +114,29 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
84 |
public static function composeComponents($scheme, $authority, $path, $query, $fragment)
|
85 |
{
|
86 |
$uri = '';
|
|
|
87 |
// weak type checks to also accept null until we can add scalar type hints
|
88 |
if ($scheme != '') {
|
89 |
$uri .= $scheme . ':';
|
90 |
}
|
91 |
-
|
|
|
92 |
$uri .= '//' . $authority;
|
93 |
}
|
|
|
94 |
$uri .= $path;
|
|
|
95 |
if ($query != '') {
|
96 |
$uri .= '?' . $query;
|
97 |
}
|
|
|
98 |
if ($fragment != '') {
|
99 |
$uri .= '#' . $fragment;
|
100 |
}
|
|
|
101 |
return $uri;
|
102 |
}
|
|
|
103 |
/**
|
104 |
* Whether the URI has the default port of the current scheme.
|
105 |
*
|
@@ -110,10 +147,12 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
110 |
*
|
111 |
* @return bool
|
112 |
*/
|
113 |
-
public static function isDefaultPort(
|
114 |
{
|
115 |
-
return $uri->getPort() === null
|
|
|
116 |
}
|
|
|
117 |
/**
|
118 |
* Whether the URI is absolute, i.e. it has a scheme.
|
119 |
*
|
@@ -132,10 +171,11 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
132 |
* @see Uri::isRelativePathReference
|
133 |
* @link https://tools.ietf.org/html/rfc3986#section-4
|
134 |
*/
|
135 |
-
public static function isAbsolute(
|
136 |
{
|
137 |
return $uri->getScheme() !== '';
|
138 |
}
|
|
|
139 |
/**
|
140 |
* Whether the URI is a network-path reference.
|
141 |
*
|
@@ -146,10 +186,11 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
146 |
* @return bool
|
147 |
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
148 |
*/
|
149 |
-
public static function isNetworkPathReference(
|
150 |
{
|
151 |
return $uri->getScheme() === '' && $uri->getAuthority() !== '';
|
152 |
}
|
|
|
153 |
/**
|
154 |
* Whether the URI is a absolute-path reference.
|
155 |
*
|
@@ -160,10 +201,14 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
160 |
* @return bool
|
161 |
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
162 |
*/
|
163 |
-
public static function isAbsolutePathReference(
|
164 |
{
|
165 |
-
return $uri->getScheme() === ''
|
|
|
|
|
|
|
166 |
}
|
|
|
167 |
/**
|
168 |
* Whether the URI is a relative-path reference.
|
169 |
*
|
@@ -174,10 +219,13 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
174 |
* @return bool
|
175 |
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
176 |
*/
|
177 |
-
public static function isRelativePathReference(
|
178 |
{
|
179 |
-
return $uri->getScheme() === ''
|
|
|
|
|
180 |
}
|
|
|
181 |
/**
|
182 |
* Whether the URI is a same-document reference.
|
183 |
*
|
@@ -191,14 +239,20 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
191 |
* @return bool
|
192 |
* @link https://tools.ietf.org/html/rfc3986#section-4.4
|
193 |
*/
|
194 |
-
public static function isSameDocumentReference(
|
195 |
{
|
196 |
if ($base !== null) {
|
197 |
-
$uri =
|
198 |
-
|
|
|
|
|
|
|
|
|
199 |
}
|
|
|
200 |
return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
|
201 |
}
|
|
|
202 |
/**
|
203 |
* Removes dot segments from a path and returns the new path.
|
204 |
*
|
@@ -211,8 +265,9 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
211 |
*/
|
212 |
public static function removeDotSegments($path)
|
213 |
{
|
214 |
-
return
|
215 |
}
|
|
|
216 |
/**
|
217 |
* Converts the relative URI into a new URI that is resolved against the base URI.
|
218 |
*
|
@@ -224,13 +279,15 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
224 |
* @deprecated since version 1.4. Use UriResolver::resolve instead.
|
225 |
* @see UriResolver::resolve
|
226 |
*/
|
227 |
-
public static function resolve(
|
228 |
{
|
229 |
-
if (
|
230 |
$rel = new self($rel);
|
231 |
}
|
232 |
-
|
|
|
233 |
}
|
|
|
234 |
/**
|
235 |
* Creates a new URI with a specific query string value removed.
|
236 |
*
|
@@ -242,18 +299,21 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
242 |
*
|
243 |
* @return UriInterface
|
244 |
*/
|
245 |
-
public static function withoutQueryValue(
|
246 |
{
|
247 |
$current = $uri->getQuery();
|
248 |
if ($current === '') {
|
249 |
return $uri;
|
250 |
}
|
251 |
-
|
252 |
-
$
|
253 |
-
|
|
|
254 |
});
|
255 |
-
|
|
|
256 |
}
|
|
|
257 |
/**
|
258 |
* Creates a new URI with a specific query string value.
|
259 |
*
|
@@ -269,28 +329,33 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
269 |
*
|
270 |
* @return UriInterface
|
271 |
*/
|
272 |
-
public static function withQueryValue(
|
273 |
{
|
274 |
$current = $uri->getQuery();
|
|
|
275 |
if ($current === '') {
|
276 |
$result = [];
|
277 |
} else {
|
278 |
-
$decodedKey =
|
279 |
-
$result =
|
280 |
-
return
|
281 |
});
|
282 |
}
|
|
|
283 |
// Query string separators ("=", "&") within the key or value need to be encoded
|
284 |
// (while preventing double-encoding) before setting the query string. All other
|
285 |
// chars that need percent-encoding will be encoded by withQuery().
|
286 |
-
$key =
|
|
|
287 |
if ($value !== null) {
|
288 |
-
$result[] = $key . '=' .
|
289 |
} else {
|
290 |
$result[] = $key;
|
291 |
}
|
292 |
-
|
|
|
293 |
}
|
|
|
294 |
/**
|
295 |
* Creates a URI from a hash of `parse_url` components.
|
296 |
*
|
@@ -306,127 +371,167 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
306 |
$uri = new self();
|
307 |
$uri->applyParts($parts);
|
308 |
$uri->validateState();
|
|
|
309 |
return $uri;
|
310 |
}
|
|
|
311 |
public function getScheme()
|
312 |
{
|
313 |
return $this->scheme;
|
314 |
}
|
|
|
315 |
public function getAuthority()
|
316 |
{
|
317 |
$authority = $this->host;
|
318 |
if ($this->userInfo !== '') {
|
319 |
$authority = $this->userInfo . '@' . $authority;
|
320 |
}
|
|
|
321 |
if ($this->port !== null) {
|
322 |
$authority .= ':' . $this->port;
|
323 |
}
|
|
|
324 |
return $authority;
|
325 |
}
|
|
|
326 |
public function getUserInfo()
|
327 |
{
|
328 |
return $this->userInfo;
|
329 |
}
|
|
|
330 |
public function getHost()
|
331 |
{
|
332 |
return $this->host;
|
333 |
}
|
|
|
334 |
public function getPort()
|
335 |
{
|
336 |
return $this->port;
|
337 |
}
|
|
|
338 |
public function getPath()
|
339 |
{
|
340 |
return $this->path;
|
341 |
}
|
|
|
342 |
public function getQuery()
|
343 |
{
|
344 |
return $this->query;
|
345 |
}
|
|
|
346 |
public function getFragment()
|
347 |
{
|
348 |
return $this->fragment;
|
349 |
}
|
|
|
350 |
public function withScheme($scheme)
|
351 |
{
|
352 |
$scheme = $this->filterScheme($scheme);
|
|
|
353 |
if ($this->scheme === $scheme) {
|
354 |
return $this;
|
355 |
}
|
|
|
356 |
$new = clone $this;
|
357 |
$new->scheme = $scheme;
|
358 |
$new->removeDefaultPort();
|
359 |
$new->validateState();
|
|
|
360 |
return $new;
|
361 |
}
|
|
|
362 |
public function withUserInfo($user, $password = null)
|
363 |
{
|
364 |
$info = $user;
|
365 |
if ($password != '') {
|
366 |
$info .= ':' . $password;
|
367 |
}
|
|
|
368 |
if ($this->userInfo === $info) {
|
369 |
return $this;
|
370 |
}
|
|
|
371 |
$new = clone $this;
|
372 |
$new->userInfo = $info;
|
373 |
$new->validateState();
|
|
|
374 |
return $new;
|
375 |
}
|
|
|
376 |
public function withHost($host)
|
377 |
{
|
378 |
$host = $this->filterHost($host);
|
|
|
379 |
if ($this->host === $host) {
|
380 |
return $this;
|
381 |
}
|
|
|
382 |
$new = clone $this;
|
383 |
$new->host = $host;
|
384 |
$new->validateState();
|
|
|
385 |
return $new;
|
386 |
}
|
|
|
387 |
public function withPort($port)
|
388 |
{
|
389 |
$port = $this->filterPort($port);
|
|
|
390 |
if ($this->port === $port) {
|
391 |
return $this;
|
392 |
}
|
|
|
393 |
$new = clone $this;
|
394 |
$new->port = $port;
|
395 |
$new->removeDefaultPort();
|
396 |
$new->validateState();
|
|
|
397 |
return $new;
|
398 |
}
|
|
|
399 |
public function withPath($path)
|
400 |
{
|
401 |
$path = $this->filterPath($path);
|
|
|
402 |
if ($this->path === $path) {
|
403 |
return $this;
|
404 |
}
|
|
|
405 |
$new = clone $this;
|
406 |
$new->path = $path;
|
407 |
$new->validateState();
|
|
|
408 |
return $new;
|
409 |
}
|
|
|
410 |
public function withQuery($query)
|
411 |
{
|
412 |
$query = $this->filterQueryAndFragment($query);
|
|
|
413 |
if ($this->query === $query) {
|
414 |
return $this;
|
415 |
}
|
|
|
416 |
$new = clone $this;
|
417 |
$new->query = $query;
|
|
|
418 |
return $new;
|
419 |
}
|
|
|
420 |
public function withFragment($fragment)
|
421 |
{
|
422 |
$fragment = $this->filterQueryAndFragment($fragment);
|
|
|
423 |
if ($this->fragment === $fragment) {
|
424 |
return $this;
|
425 |
}
|
|
|
426 |
$new = clone $this;
|
427 |
$new->fragment = $fragment;
|
|
|
428 |
return $new;
|
429 |
}
|
|
|
430 |
/**
|
431 |
* Apply parse_url parts to a URI.
|
432 |
*
|
@@ -434,18 +539,32 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
434 |
*/
|
435 |
private function applyParts(array $parts)
|
436 |
{
|
437 |
-
$this->scheme = isset($parts['scheme'])
|
|
|
|
|
438 |
$this->userInfo = isset($parts['user']) ? $parts['user'] : '';
|
439 |
-
$this->host = isset($parts['host'])
|
440 |
-
|
441 |
-
|
442 |
-
$this->
|
443 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
444 |
if (isset($parts['pass'])) {
|
445 |
$this->userInfo .= ':' . $parts['pass'];
|
446 |
}
|
|
|
447 |
$this->removeDefaultPort();
|
448 |
}
|
|
|
449 |
/**
|
450 |
* @param string $scheme
|
451 |
*
|
@@ -455,11 +574,13 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
455 |
*/
|
456 |
private function filterScheme($scheme)
|
457 |
{
|
458 |
-
if (
|
459 |
throw new \InvalidArgumentException('Scheme must be a string');
|
460 |
}
|
461 |
-
|
|
|
462 |
}
|
|
|
463 |
/**
|
464 |
* @param string $host
|
465 |
*
|
@@ -469,11 +590,13 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
469 |
*/
|
470 |
private function filterHost($host)
|
471 |
{
|
472 |
-
if (
|
473 |
throw new \InvalidArgumentException('Host must be a string');
|
474 |
}
|
475 |
-
|
|
|
476 |
}
|
|
|
477 |
/**
|
478 |
* @param int|null $port
|
479 |
*
|
@@ -486,18 +609,24 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
486 |
if ($port === null) {
|
487 |
return null;
|
488 |
}
|
|
|
489 |
$port = (int) $port;
|
490 |
if (1 > $port || 0xffff < $port) {
|
491 |
-
throw new \InvalidArgumentException(
|
|
|
|
|
492 |
}
|
|
|
493 |
return $port;
|
494 |
}
|
|
|
495 |
private function removeDefaultPort()
|
496 |
{
|
497 |
if ($this->port !== null && self::isDefaultPort($this)) {
|
498 |
$this->port = null;
|
499 |
}
|
500 |
}
|
|
|
501 |
/**
|
502 |
* Filters the path of a URI
|
503 |
*
|
@@ -509,11 +638,17 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
509 |
*/
|
510 |
private function filterPath($path)
|
511 |
{
|
512 |
-
if (
|
513 |
throw new \InvalidArgumentException('Path must be a string');
|
514 |
}
|
515 |
-
|
|
|
|
|
|
|
|
|
|
|
516 |
}
|
|
|
517 |
/**
|
518 |
* Filters the query string or fragment of a URI.
|
519 |
*
|
@@ -525,30 +660,42 @@ class Uri implements \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface
|
|
525 |
*/
|
526 |
private function filterQueryAndFragment($str)
|
527 |
{
|
528 |
-
if (
|
529 |
throw new \InvalidArgumentException('Query and fragment must be a string');
|
530 |
}
|
531 |
-
|
|
|
|
|
|
|
|
|
|
|
532 |
}
|
|
|
533 |
private function rawurlencodeMatchZero(array $match)
|
534 |
{
|
535 |
-
return
|
536 |
}
|
|
|
537 |
private function validateState()
|
538 |
{
|
539 |
if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
|
540 |
$this->host = self::HTTP_DEFAULT_HOST;
|
541 |
}
|
|
|
542 |
if ($this->getAuthority() === '') {
|
543 |
-
if (0 ===
|
544 |
throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
|
545 |
}
|
546 |
-
if ($this->scheme === '' &&
|
547 |
throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
|
548 |
}
|
549 |
} elseif (isset($this->path[0]) && $this->path[0] !== '/') {
|
550 |
-
|
551 |
-
|
|
|
|
|
|
|
|
|
552 |
//throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
|
553 |
}
|
554 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\UriInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* PSR-7 URI implementation.
|
8 |
*
|
10 |
* @author Tobias Schultze
|
11 |
* @author Matthew Weier O'Phinney
|
12 |
*/
|
13 |
+
class Uri implements UriInterface
|
14 |
{
|
15 |
/**
|
16 |
* Absolute http and https URIs require a host per RFC 7230 Section 2.7
|
19 |
* valid URI.
|
20 |
*/
|
21 |
const HTTP_DEFAULT_HOST = 'localhost';
|
22 |
+
|
23 |
+
private static $defaultPorts = [
|
24 |
+
'http' => 80,
|
25 |
+
'https' => 443,
|
26 |
+
'ftp' => 21,
|
27 |
+
'gopher' => 70,
|
28 |
+
'nntp' => 119,
|
29 |
+
'news' => 119,
|
30 |
+
'telnet' => 23,
|
31 |
+
'tn3270' => 23,
|
32 |
+
'imap' => 143,
|
33 |
+
'pop' => 110,
|
34 |
+
'ldap' => 389,
|
35 |
+
];
|
36 |
+
|
37 |
+
private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
|
38 |
+
private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
|
39 |
private static $replaceQuery = ['=' => '%3D', '&' => '%26'];
|
40 |
+
|
41 |
/** @var string Uri scheme. */
|
42 |
private $scheme = '';
|
43 |
+
|
44 |
/** @var string Uri user info. */
|
45 |
private $userInfo = '';
|
46 |
+
|
47 |
/** @var string Uri host. */
|
48 |
private $host = '';
|
49 |
+
|
50 |
/** @var int|null Uri port. */
|
51 |
private $port;
|
52 |
+
|
53 |
/** @var string Uri path. */
|
54 |
private $path = '';
|
55 |
+
|
56 |
/** @var string Uri query string. */
|
57 |
private $query = '';
|
58 |
+
|
59 |
/** @var string Uri fragment. */
|
60 |
private $fragment = '';
|
61 |
+
|
62 |
/**
|
63 |
* @param string $uri URI to parse
|
64 |
*/
|
66 |
{
|
67 |
// weak type check to also accept null until we can add scalar type hints
|
68 |
if ($uri != '') {
|
69 |
+
$parts = parse_url($uri);
|
70 |
+
if ($parts === false) {
|
71 |
+
throw new \InvalidArgumentException("Unable to parse URI: $uri");
|
72 |
}
|
73 |
$this->applyParts($parts);
|
74 |
}
|
75 |
}
|
76 |
+
|
77 |
public function __toString()
|
78 |
{
|
79 |
+
return self::composeComponents(
|
80 |
+
$this->scheme,
|
81 |
+
$this->getAuthority(),
|
82 |
+
$this->path,
|
83 |
+
$this->query,
|
84 |
+
$this->fragment
|
85 |
+
);
|
86 |
}
|
87 |
+
|
88 |
/**
|
89 |
* Composes a URI reference string from its various components.
|
90 |
*
|
114 |
public static function composeComponents($scheme, $authority, $path, $query, $fragment)
|
115 |
{
|
116 |
$uri = '';
|
117 |
+
|
118 |
// weak type checks to also accept null until we can add scalar type hints
|
119 |
if ($scheme != '') {
|
120 |
$uri .= $scheme . ':';
|
121 |
}
|
122 |
+
|
123 |
+
if ($authority != ''|| $scheme === 'file') {
|
124 |
$uri .= '//' . $authority;
|
125 |
}
|
126 |
+
|
127 |
$uri .= $path;
|
128 |
+
|
129 |
if ($query != '') {
|
130 |
$uri .= '?' . $query;
|
131 |
}
|
132 |
+
|
133 |
if ($fragment != '') {
|
134 |
$uri .= '#' . $fragment;
|
135 |
}
|
136 |
+
|
137 |
return $uri;
|
138 |
}
|
139 |
+
|
140 |
/**
|
141 |
* Whether the URI has the default port of the current scheme.
|
142 |
*
|
147 |
*
|
148 |
* @return bool
|
149 |
*/
|
150 |
+
public static function isDefaultPort(UriInterface $uri)
|
151 |
{
|
152 |
+
return $uri->getPort() === null
|
153 |
+
|| (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]);
|
154 |
}
|
155 |
+
|
156 |
/**
|
157 |
* Whether the URI is absolute, i.e. it has a scheme.
|
158 |
*
|
171 |
* @see Uri::isRelativePathReference
|
172 |
* @link https://tools.ietf.org/html/rfc3986#section-4
|
173 |
*/
|
174 |
+
public static function isAbsolute(UriInterface $uri)
|
175 |
{
|
176 |
return $uri->getScheme() !== '';
|
177 |
}
|
178 |
+
|
179 |
/**
|
180 |
* Whether the URI is a network-path reference.
|
181 |
*
|
186 |
* @return bool
|
187 |
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
188 |
*/
|
189 |
+
public static function isNetworkPathReference(UriInterface $uri)
|
190 |
{
|
191 |
return $uri->getScheme() === '' && $uri->getAuthority() !== '';
|
192 |
}
|
193 |
+
|
194 |
/**
|
195 |
* Whether the URI is a absolute-path reference.
|
196 |
*
|
201 |
* @return bool
|
202 |
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
203 |
*/
|
204 |
+
public static function isAbsolutePathReference(UriInterface $uri)
|
205 |
{
|
206 |
+
return $uri->getScheme() === ''
|
207 |
+
&& $uri->getAuthority() === ''
|
208 |
+
&& isset($uri->getPath()[0])
|
209 |
+
&& $uri->getPath()[0] === '/';
|
210 |
}
|
211 |
+
|
212 |
/**
|
213 |
* Whether the URI is a relative-path reference.
|
214 |
*
|
219 |
* @return bool
|
220 |
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
221 |
*/
|
222 |
+
public static function isRelativePathReference(UriInterface $uri)
|
223 |
{
|
224 |
+
return $uri->getScheme() === ''
|
225 |
+
&& $uri->getAuthority() === ''
|
226 |
+
&& (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
|
227 |
}
|
228 |
+
|
229 |
/**
|
230 |
* Whether the URI is a same-document reference.
|
231 |
*
|
239 |
* @return bool
|
240 |
* @link https://tools.ietf.org/html/rfc3986#section-4.4
|
241 |
*/
|
242 |
+
public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null)
|
243 |
{
|
244 |
if ($base !== null) {
|
245 |
+
$uri = UriResolver::resolve($base, $uri);
|
246 |
+
|
247 |
+
return ($uri->getScheme() === $base->getScheme())
|
248 |
+
&& ($uri->getAuthority() === $base->getAuthority())
|
249 |
+
&& ($uri->getPath() === $base->getPath())
|
250 |
+
&& ($uri->getQuery() === $base->getQuery());
|
251 |
}
|
252 |
+
|
253 |
return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
|
254 |
}
|
255 |
+
|
256 |
/**
|
257 |
* Removes dot segments from a path and returns the new path.
|
258 |
*
|
265 |
*/
|
266 |
public static function removeDotSegments($path)
|
267 |
{
|
268 |
+
return UriResolver::removeDotSegments($path);
|
269 |
}
|
270 |
+
|
271 |
/**
|
272 |
* Converts the relative URI into a new URI that is resolved against the base URI.
|
273 |
*
|
279 |
* @deprecated since version 1.4. Use UriResolver::resolve instead.
|
280 |
* @see UriResolver::resolve
|
281 |
*/
|
282 |
+
public static function resolve(UriInterface $base, $rel)
|
283 |
{
|
284 |
+
if (!($rel instanceof UriInterface)) {
|
285 |
$rel = new self($rel);
|
286 |
}
|
287 |
+
|
288 |
+
return UriResolver::resolve($base, $rel);
|
289 |
}
|
290 |
+
|
291 |
/**
|
292 |
* Creates a new URI with a specific query string value removed.
|
293 |
*
|
299 |
*
|
300 |
* @return UriInterface
|
301 |
*/
|
302 |
+
public static function withoutQueryValue(UriInterface $uri, $key)
|
303 |
{
|
304 |
$current = $uri->getQuery();
|
305 |
if ($current === '') {
|
306 |
return $uri;
|
307 |
}
|
308 |
+
|
309 |
+
$decodedKey = rawurldecode($key);
|
310 |
+
$result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
|
311 |
+
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
|
312 |
});
|
313 |
+
|
314 |
+
return $uri->withQuery(implode('&', $result));
|
315 |
}
|
316 |
+
|
317 |
/**
|
318 |
* Creates a new URI with a specific query string value.
|
319 |
*
|
329 |
*
|
330 |
* @return UriInterface
|
331 |
*/
|
332 |
+
public static function withQueryValue(UriInterface $uri, $key, $value)
|
333 |
{
|
334 |
$current = $uri->getQuery();
|
335 |
+
|
336 |
if ($current === '') {
|
337 |
$result = [];
|
338 |
} else {
|
339 |
+
$decodedKey = rawurldecode($key);
|
340 |
+
$result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
|
341 |
+
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
|
342 |
});
|
343 |
}
|
344 |
+
|
345 |
// Query string separators ("=", "&") within the key or value need to be encoded
|
346 |
// (while preventing double-encoding) before setting the query string. All other
|
347 |
// chars that need percent-encoding will be encoded by withQuery().
|
348 |
+
$key = strtr($key, self::$replaceQuery);
|
349 |
+
|
350 |
if ($value !== null) {
|
351 |
+
$result[] = $key . '=' . strtr($value, self::$replaceQuery);
|
352 |
} else {
|
353 |
$result[] = $key;
|
354 |
}
|
355 |
+
|
356 |
+
return $uri->withQuery(implode('&', $result));
|
357 |
}
|
358 |
+
|
359 |
/**
|
360 |
* Creates a URI from a hash of `parse_url` components.
|
361 |
*
|
371 |
$uri = new self();
|
372 |
$uri->applyParts($parts);
|
373 |
$uri->validateState();
|
374 |
+
|
375 |
return $uri;
|
376 |
}
|
377 |
+
|
378 |
public function getScheme()
|
379 |
{
|
380 |
return $this->scheme;
|
381 |
}
|
382 |
+
|
383 |
public function getAuthority()
|
384 |
{
|
385 |
$authority = $this->host;
|
386 |
if ($this->userInfo !== '') {
|
387 |
$authority = $this->userInfo . '@' . $authority;
|
388 |
}
|
389 |
+
|
390 |
if ($this->port !== null) {
|
391 |
$authority .= ':' . $this->port;
|
392 |
}
|
393 |
+
|
394 |
return $authority;
|
395 |
}
|
396 |
+
|
397 |
public function getUserInfo()
|
398 |
{
|
399 |
return $this->userInfo;
|
400 |
}
|
401 |
+
|
402 |
public function getHost()
|
403 |
{
|
404 |
return $this->host;
|
405 |
}
|
406 |
+
|
407 |
public function getPort()
|
408 |
{
|
409 |
return $this->port;
|
410 |
}
|
411 |
+
|
412 |
public function getPath()
|
413 |
{
|
414 |
return $this->path;
|
415 |
}
|
416 |
+
|
417 |
public function getQuery()
|
418 |
{
|
419 |
return $this->query;
|
420 |
}
|
421 |
+
|
422 |
public function getFragment()
|
423 |
{
|
424 |
return $this->fragment;
|
425 |
}
|
426 |
+
|
427 |
public function withScheme($scheme)
|
428 |
{
|
429 |
$scheme = $this->filterScheme($scheme);
|
430 |
+
|
431 |
if ($this->scheme === $scheme) {
|
432 |
return $this;
|
433 |
}
|
434 |
+
|
435 |
$new = clone $this;
|
436 |
$new->scheme = $scheme;
|
437 |
$new->removeDefaultPort();
|
438 |
$new->validateState();
|
439 |
+
|
440 |
return $new;
|
441 |
}
|
442 |
+
|
443 |
public function withUserInfo($user, $password = null)
|
444 |
{
|
445 |
$info = $user;
|
446 |
if ($password != '') {
|
447 |
$info .= ':' . $password;
|
448 |
}
|
449 |
+
|
450 |
if ($this->userInfo === $info) {
|
451 |
return $this;
|
452 |
}
|
453 |
+
|
454 |
$new = clone $this;
|
455 |
$new->userInfo = $info;
|
456 |
$new->validateState();
|
457 |
+
|
458 |
return $new;
|
459 |
}
|
460 |
+
|
461 |
public function withHost($host)
|
462 |
{
|
463 |
$host = $this->filterHost($host);
|
464 |
+
|
465 |
if ($this->host === $host) {
|
466 |
return $this;
|
467 |
}
|
468 |
+
|
469 |
$new = clone $this;
|
470 |
$new->host = $host;
|
471 |
$new->validateState();
|
472 |
+
|
473 |
return $new;
|
474 |
}
|
475 |
+
|
476 |
public function withPort($port)
|
477 |
{
|
478 |
$port = $this->filterPort($port);
|
479 |
+
|
480 |
if ($this->port === $port) {
|
481 |
return $this;
|
482 |
}
|
483 |
+
|
484 |
$new = clone $this;
|
485 |
$new->port = $port;
|
486 |
$new->removeDefaultPort();
|
487 |
$new->validateState();
|
488 |
+
|
489 |
return $new;
|
490 |
}
|
491 |
+
|
492 |
public function withPath($path)
|
493 |
{
|
494 |
$path = $this->filterPath($path);
|
495 |
+
|
496 |
if ($this->path === $path) {
|
497 |
return $this;
|
498 |
}
|
499 |
+
|
500 |
$new = clone $this;
|
501 |
$new->path = $path;
|
502 |
$new->validateState();
|
503 |
+
|
504 |
return $new;
|
505 |
}
|
506 |
+
|
507 |
public function withQuery($query)
|
508 |
{
|
509 |
$query = $this->filterQueryAndFragment($query);
|
510 |
+
|
511 |
if ($this->query === $query) {
|
512 |
return $this;
|
513 |
}
|
514 |
+
|
515 |
$new = clone $this;
|
516 |
$new->query = $query;
|
517 |
+
|
518 |
return $new;
|
519 |
}
|
520 |
+
|
521 |
public function withFragment($fragment)
|
522 |
{
|
523 |
$fragment = $this->filterQueryAndFragment($fragment);
|
524 |
+
|
525 |
if ($this->fragment === $fragment) {
|
526 |
return $this;
|
527 |
}
|
528 |
+
|
529 |
$new = clone $this;
|
530 |
$new->fragment = $fragment;
|
531 |
+
|
532 |
return $new;
|
533 |
}
|
534 |
+
|
535 |
/**
|
536 |
* Apply parse_url parts to a URI.
|
537 |
*
|
539 |
*/
|
540 |
private function applyParts(array $parts)
|
541 |
{
|
542 |
+
$this->scheme = isset($parts['scheme'])
|
543 |
+
? $this->filterScheme($parts['scheme'])
|
544 |
+
: '';
|
545 |
$this->userInfo = isset($parts['user']) ? $parts['user'] : '';
|
546 |
+
$this->host = isset($parts['host'])
|
547 |
+
? $this->filterHost($parts['host'])
|
548 |
+
: '';
|
549 |
+
$this->port = isset($parts['port'])
|
550 |
+
? $this->filterPort($parts['port'])
|
551 |
+
: null;
|
552 |
+
$this->path = isset($parts['path'])
|
553 |
+
? $this->filterPath($parts['path'])
|
554 |
+
: '';
|
555 |
+
$this->query = isset($parts['query'])
|
556 |
+
? $this->filterQueryAndFragment($parts['query'])
|
557 |
+
: '';
|
558 |
+
$this->fragment = isset($parts['fragment'])
|
559 |
+
? $this->filterQueryAndFragment($parts['fragment'])
|
560 |
+
: '';
|
561 |
if (isset($parts['pass'])) {
|
562 |
$this->userInfo .= ':' . $parts['pass'];
|
563 |
}
|
564 |
+
|
565 |
$this->removeDefaultPort();
|
566 |
}
|
567 |
+
|
568 |
/**
|
569 |
* @param string $scheme
|
570 |
*
|
574 |
*/
|
575 |
private function filterScheme($scheme)
|
576 |
{
|
577 |
+
if (!is_string($scheme)) {
|
578 |
throw new \InvalidArgumentException('Scheme must be a string');
|
579 |
}
|
580 |
+
|
581 |
+
return strtolower($scheme);
|
582 |
}
|
583 |
+
|
584 |
/**
|
585 |
* @param string $host
|
586 |
*
|
590 |
*/
|
591 |
private function filterHost($host)
|
592 |
{
|
593 |
+
if (!is_string($host)) {
|
594 |
throw new \InvalidArgumentException('Host must be a string');
|
595 |
}
|
596 |
+
|
597 |
+
return strtolower($host);
|
598 |
}
|
599 |
+
|
600 |
/**
|
601 |
* @param int|null $port
|
602 |
*
|
609 |
if ($port === null) {
|
610 |
return null;
|
611 |
}
|
612 |
+
|
613 |
$port = (int) $port;
|
614 |
if (1 > $port || 0xffff < $port) {
|
615 |
+
throw new \InvalidArgumentException(
|
616 |
+
sprintf('Invalid port: %d. Must be between 1 and 65535', $port)
|
617 |
+
);
|
618 |
}
|
619 |
+
|
620 |
return $port;
|
621 |
}
|
622 |
+
|
623 |
private function removeDefaultPort()
|
624 |
{
|
625 |
if ($this->port !== null && self::isDefaultPort($this)) {
|
626 |
$this->port = null;
|
627 |
}
|
628 |
}
|
629 |
+
|
630 |
/**
|
631 |
* Filters the path of a URI
|
632 |
*
|
638 |
*/
|
639 |
private function filterPath($path)
|
640 |
{
|
641 |
+
if (!is_string($path)) {
|
642 |
throw new \InvalidArgumentException('Path must be a string');
|
643 |
}
|
644 |
+
|
645 |
+
return preg_replace_callback(
|
646 |
+
'/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/',
|
647 |
+
[$this, 'rawurlencodeMatchZero'],
|
648 |
+
$path
|
649 |
+
);
|
650 |
}
|
651 |
+
|
652 |
/**
|
653 |
* Filters the query string or fragment of a URI.
|
654 |
*
|
660 |
*/
|
661 |
private function filterQueryAndFragment($str)
|
662 |
{
|
663 |
+
if (!is_string($str)) {
|
664 |
throw new \InvalidArgumentException('Query and fragment must be a string');
|
665 |
}
|
666 |
+
|
667 |
+
return preg_replace_callback(
|
668 |
+
'/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/',
|
669 |
+
[$this, 'rawurlencodeMatchZero'],
|
670 |
+
$str
|
671 |
+
);
|
672 |
}
|
673 |
+
|
674 |
private function rawurlencodeMatchZero(array $match)
|
675 |
{
|
676 |
+
return rawurlencode($match[0]);
|
677 |
}
|
678 |
+
|
679 |
private function validateState()
|
680 |
{
|
681 |
if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
|
682 |
$this->host = self::HTTP_DEFAULT_HOST;
|
683 |
}
|
684 |
+
|
685 |
if ($this->getAuthority() === '') {
|
686 |
+
if (0 === strpos($this->path, '//')) {
|
687 |
throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
|
688 |
}
|
689 |
+
if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) {
|
690 |
throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
|
691 |
}
|
692 |
} elseif (isset($this->path[0]) && $this->path[0] !== '/') {
|
693 |
+
@trigger_error(
|
694 |
+
'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' .
|
695 |
+
'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.',
|
696 |
+
E_USER_DEPRECATED
|
697 |
+
);
|
698 |
+
$this->path = '/'. $this->path;
|
699 |
//throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
|
700 |
}
|
701 |
}
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
6 |
/**
|
7 |
* Provides methods to normalize and compare URIs.
|
8 |
*
|
@@ -19,12 +19,14 @@ final class UriNormalizer
|
|
19 |
* self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS
|
20 |
*/
|
21 |
const PRESERVING_NORMALIZATIONS = 63;
|
|
|
22 |
/**
|
23 |
* All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
|
24 |
*
|
25 |
* Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
|
26 |
*/
|
27 |
const CAPITALIZE_PERCENT_ENCODING = 1;
|
|
|
28 |
/**
|
29 |
* Decodes percent-encoded octets of unreserved characters.
|
30 |
*
|
@@ -35,12 +37,14 @@ final class UriNormalizer
|
|
35 |
* Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
|
36 |
*/
|
37 |
const DECODE_UNRESERVED_CHARACTERS = 2;
|
|
|
38 |
/**
|
39 |
* Converts the empty path to "/" for http and https URIs.
|
40 |
*
|
41 |
* Example: http://example.org → http://example.org/
|
42 |
*/
|
43 |
const CONVERT_EMPTY_PATH = 4;
|
|
|
44 |
/**
|
45 |
* Removes the default host of the given URI scheme from the URI.
|
46 |
*
|
@@ -53,12 +57,14 @@ final class UriNormalizer
|
|
53 |
* Example: file://localhost/myfile → file:///myfile
|
54 |
*/
|
55 |
const REMOVE_DEFAULT_HOST = 8;
|
|
|
56 |
/**
|
57 |
* Removes the default port of the given URI scheme from the URI.
|
58 |
*
|
59 |
* Example: http://example.org:80/ → http://example.org/
|
60 |
*/
|
61 |
const REMOVE_DEFAULT_PORT = 16;
|
|
|
62 |
/**
|
63 |
* Removes unnecessary dot-segments.
|
64 |
*
|
@@ -68,6 +74,7 @@ final class UriNormalizer
|
|
68 |
* Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html
|
69 |
*/
|
70 |
const REMOVE_DOT_SEGMENTS = 32;
|
|
|
71 |
/**
|
72 |
* Paths which include two or more adjacent slashes are converted to one.
|
73 |
*
|
@@ -78,6 +85,7 @@ final class UriNormalizer
|
|
78 |
* Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html
|
79 |
*/
|
80 |
const REMOVE_DUPLICATE_SLASHES = 64;
|
|
|
81 |
/**
|
82 |
* Sort query parameters with their values in alphabetical order.
|
83 |
*
|
@@ -90,6 +98,7 @@ final class UriNormalizer
|
|
90 |
* purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.
|
91 |
*/
|
92 |
const SORT_QUERY_PARAMETERS = 128;
|
|
|
93 |
/**
|
94 |
* Returns a normalized URI.
|
95 |
*
|
@@ -107,36 +116,47 @@ final class UriNormalizer
|
|
107 |
* @return UriInterface The normalized URI
|
108 |
* @link https://tools.ietf.org/html/rfc3986#section-6.2
|
109 |
*/
|
110 |
-
public static function normalize(
|
111 |
{
|
112 |
if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {
|
113 |
$uri = self::capitalizePercentEncoding($uri);
|
114 |
}
|
|
|
115 |
if ($flags & self::DECODE_UNRESERVED_CHARACTERS) {
|
116 |
$uri = self::decodeUnreservedCharacters($uri);
|
117 |
}
|
118 |
-
|
|
|
|
|
|
|
119 |
$uri = $uri->withPath('/');
|
120 |
}
|
|
|
121 |
if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {
|
122 |
$uri = $uri->withHost('');
|
123 |
}
|
124 |
-
|
|
|
125 |
$uri = $uri->withPort(null);
|
126 |
}
|
127 |
-
|
128 |
-
|
|
|
129 |
}
|
|
|
130 |
if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
|
131 |
-
$uri = $uri->withPath(
|
132 |
}
|
|
|
133 |
if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
|
134 |
-
$queryKeyValues =
|
135 |
-
|
136 |
-
$uri = $uri->withQuery(
|
137 |
}
|
|
|
138 |
return $uri;
|
139 |
}
|
|
|
140 |
/**
|
141 |
* Whether two URIs can be considered equivalent.
|
142 |
*
|
@@ -152,26 +172,43 @@ final class UriNormalizer
|
|
152 |
* @return bool
|
153 |
* @link https://tools.ietf.org/html/rfc3986#section-6.1
|
154 |
*/
|
155 |
-
public static function isEquivalent(
|
156 |
{
|
157 |
return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
|
158 |
}
|
159 |
-
|
|
|
160 |
{
|
161 |
$regex = '/(?:%[A-Fa-f0-9]{2})++/';
|
|
|
162 |
$callback = function (array $match) {
|
163 |
-
return
|
164 |
};
|
165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
}
|
167 |
-
|
|
|
168 |
{
|
169 |
$regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
|
|
|
170 |
$callback = function (array $match) {
|
171 |
-
return
|
172 |
};
|
173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
}
|
|
|
175 |
private function __construct()
|
176 |
{
|
177 |
// cannot be instantiated
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\UriInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Provides methods to normalize and compare URIs.
|
8 |
*
|
19 |
* self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS
|
20 |
*/
|
21 |
const PRESERVING_NORMALIZATIONS = 63;
|
22 |
+
|
23 |
/**
|
24 |
* All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
|
25 |
*
|
26 |
* Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
|
27 |
*/
|
28 |
const CAPITALIZE_PERCENT_ENCODING = 1;
|
29 |
+
|
30 |
/**
|
31 |
* Decodes percent-encoded octets of unreserved characters.
|
32 |
*
|
37 |
* Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
|
38 |
*/
|
39 |
const DECODE_UNRESERVED_CHARACTERS = 2;
|
40 |
+
|
41 |
/**
|
42 |
* Converts the empty path to "/" for http and https URIs.
|
43 |
*
|
44 |
* Example: http://example.org → http://example.org/
|
45 |
*/
|
46 |
const CONVERT_EMPTY_PATH = 4;
|
47 |
+
|
48 |
/**
|
49 |
* Removes the default host of the given URI scheme from the URI.
|
50 |
*
|
57 |
* Example: file://localhost/myfile → file:///myfile
|
58 |
*/
|
59 |
const REMOVE_DEFAULT_HOST = 8;
|
60 |
+
|
61 |
/**
|
62 |
* Removes the default port of the given URI scheme from the URI.
|
63 |
*
|
64 |
* Example: http://example.org:80/ → http://example.org/
|
65 |
*/
|
66 |
const REMOVE_DEFAULT_PORT = 16;
|
67 |
+
|
68 |
/**
|
69 |
* Removes unnecessary dot-segments.
|
70 |
*
|
74 |
* Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html
|
75 |
*/
|
76 |
const REMOVE_DOT_SEGMENTS = 32;
|
77 |
+
|
78 |
/**
|
79 |
* Paths which include two or more adjacent slashes are converted to one.
|
80 |
*
|
85 |
* Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html
|
86 |
*/
|
87 |
const REMOVE_DUPLICATE_SLASHES = 64;
|
88 |
+
|
89 |
/**
|
90 |
* Sort query parameters with their values in alphabetical order.
|
91 |
*
|
98 |
* purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.
|
99 |
*/
|
100 |
const SORT_QUERY_PARAMETERS = 128;
|
101 |
+
|
102 |
/**
|
103 |
* Returns a normalized URI.
|
104 |
*
|
116 |
* @return UriInterface The normalized URI
|
117 |
* @link https://tools.ietf.org/html/rfc3986#section-6.2
|
118 |
*/
|
119 |
+
public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS)
|
120 |
{
|
121 |
if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {
|
122 |
$uri = self::capitalizePercentEncoding($uri);
|
123 |
}
|
124 |
+
|
125 |
if ($flags & self::DECODE_UNRESERVED_CHARACTERS) {
|
126 |
$uri = self::decodeUnreservedCharacters($uri);
|
127 |
}
|
128 |
+
|
129 |
+
if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' &&
|
130 |
+
($uri->getScheme() === 'http' || $uri->getScheme() === 'https')
|
131 |
+
) {
|
132 |
$uri = $uri->withPath('/');
|
133 |
}
|
134 |
+
|
135 |
if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {
|
136 |
$uri = $uri->withHost('');
|
137 |
}
|
138 |
+
|
139 |
+
if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) {
|
140 |
$uri = $uri->withPort(null);
|
141 |
}
|
142 |
+
|
143 |
+
if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) {
|
144 |
+
$uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath()));
|
145 |
}
|
146 |
+
|
147 |
if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
|
148 |
+
$uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath()));
|
149 |
}
|
150 |
+
|
151 |
if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
|
152 |
+
$queryKeyValues = explode('&', $uri->getQuery());
|
153 |
+
sort($queryKeyValues);
|
154 |
+
$uri = $uri->withQuery(implode('&', $queryKeyValues));
|
155 |
}
|
156 |
+
|
157 |
return $uri;
|
158 |
}
|
159 |
+
|
160 |
/**
|
161 |
* Whether two URIs can be considered equivalent.
|
162 |
*
|
172 |
* @return bool
|
173 |
* @link https://tools.ietf.org/html/rfc3986#section-6.1
|
174 |
*/
|
175 |
+
public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS)
|
176 |
{
|
177 |
return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
|
178 |
}
|
179 |
+
|
180 |
+
private static function capitalizePercentEncoding(UriInterface $uri)
|
181 |
{
|
182 |
$regex = '/(?:%[A-Fa-f0-9]{2})++/';
|
183 |
+
|
184 |
$callback = function (array $match) {
|
185 |
+
return strtoupper($match[0]);
|
186 |
};
|
187 |
+
|
188 |
+
return
|
189 |
+
$uri->withPath(
|
190 |
+
preg_replace_callback($regex, $callback, $uri->getPath())
|
191 |
+
)->withQuery(
|
192 |
+
preg_replace_callback($regex, $callback, $uri->getQuery())
|
193 |
+
);
|
194 |
}
|
195 |
+
|
196 |
+
private static function decodeUnreservedCharacters(UriInterface $uri)
|
197 |
{
|
198 |
$regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
|
199 |
+
|
200 |
$callback = function (array $match) {
|
201 |
+
return rawurldecode($match[0]);
|
202 |
};
|
203 |
+
|
204 |
+
return
|
205 |
+
$uri->withPath(
|
206 |
+
preg_replace_callback($regex, $callback, $uri->getPath())
|
207 |
+
)->withQuery(
|
208 |
+
preg_replace_callback($regex, $callback, $uri->getQuery())
|
209 |
+
);
|
210 |
}
|
211 |
+
|
212 |
private function __construct()
|
213 |
{
|
214 |
// cannot be instantiated
|
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
6 |
/**
|
7 |
* Resolves a URI reference in the context of a base URI and the opposite way.
|
8 |
*
|
@@ -25,16 +25,19 @@ final class UriResolver
|
|
25 |
if ($path === '' || $path === '/') {
|
26 |
return $path;
|
27 |
}
|
|
|
28 |
$results = [];
|
29 |
-
$segments =
|
30 |
foreach ($segments as $segment) {
|
31 |
if ($segment === '..') {
|
32 |
-
|
33 |
} elseif ($segment !== '.') {
|
34 |
$results[] = $segment;
|
35 |
}
|
36 |
}
|
37 |
-
|
|
|
|
|
38 |
if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {
|
39 |
// Re-add the leading slash if necessary for cases like "/.."
|
40 |
$newPath = '/' . $newPath;
|
@@ -43,8 +46,10 @@ final class UriResolver
|
|
43 |
// If newPath is not empty, then $segment must be set and is the last segment from the foreach
|
44 |
$newPath .= '/';
|
45 |
}
|
|
|
46 |
return $newPath;
|
47 |
}
|
|
|
48 |
/**
|
49 |
* Converts the relative URI into a new URI that is resolved against the base URI.
|
50 |
*
|
@@ -54,15 +59,17 @@ final class UriResolver
|
|
54 |
* @return UriInterface
|
55 |
* @link http://tools.ietf.org/html/rfc3986#section-5.2
|
56 |
*/
|
57 |
-
public static function resolve(
|
58 |
{
|
59 |
if ((string) $rel === '') {
|
60 |
// we can simply return the same base URI instance for this same-document reference
|
61 |
return $base;
|
62 |
}
|
|
|
63 |
if ($rel->getScheme() != '') {
|
64 |
return $rel->withPath(self::removeDotSegments($rel->getPath()));
|
65 |
}
|
|
|
66 |
if ($rel->getAuthority() != '') {
|
67 |
$targetAuthority = $rel->getAuthority();
|
68 |
$targetPath = self::removeDotSegments($rel->getPath());
|
@@ -79,11 +86,11 @@ final class UriResolver
|
|
79 |
if ($targetAuthority != '' && $base->getPath() === '') {
|
80 |
$targetPath = '/' . $rel->getPath();
|
81 |
} else {
|
82 |
-
$lastSlashPos =
|
83 |
-
if ($lastSlashPos ===
|
84 |
$targetPath = $rel->getPath();
|
85 |
} else {
|
86 |
-
$targetPath =
|
87 |
}
|
88 |
}
|
89 |
}
|
@@ -91,8 +98,16 @@ final class UriResolver
|
|
91 |
$targetQuery = $rel->getQuery();
|
92 |
}
|
93 |
}
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
|
|
96 |
/**
|
97 |
* Returns the target URI as a relative reference from the base URI.
|
98 |
*
|
@@ -119,46 +134,57 @@ final class UriResolver
|
|
119 |
*
|
120 |
* @return UriInterface The relative URI reference
|
121 |
*/
|
122 |
-
public static function relativize(
|
123 |
{
|
124 |
-
if ($target->getScheme() !== '' &&
|
|
|
|
|
125 |
return $target;
|
126 |
}
|
127 |
-
|
|
|
128 |
// As the target is already highly relative we return it as-is. It would be possible to resolve
|
129 |
// the target with `$target = self::resolve($base, $target);` and then try make it more relative
|
130 |
// by removing a duplicate query. But let's not do that automatically.
|
131 |
return $target;
|
132 |
}
|
|
|
133 |
if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
|
134 |
return $target->withScheme('');
|
135 |
}
|
|
|
136 |
// We must remove the path before removing the authority because if the path starts with two slashes, the URI
|
137 |
// would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
|
138 |
// invalid.
|
139 |
$emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
|
|
|
140 |
if ($base->getPath() !== $target->getPath()) {
|
141 |
return $emptyPathUri->withPath(self::getRelativePath($base, $target));
|
142 |
}
|
|
|
143 |
if ($base->getQuery() === $target->getQuery()) {
|
144 |
// Only the target fragment is left. And it must be returned even if base and target fragment are the same.
|
145 |
return $emptyPathUri->withQuery('');
|
146 |
}
|
|
|
147 |
// If the base URI has a query but the target has none, we cannot return an empty path reference as it would
|
148 |
// inherit the base query component when resolving.
|
149 |
if ($target->getQuery() === '') {
|
150 |
-
$segments =
|
151 |
-
$lastSegment =
|
|
|
152 |
return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
|
153 |
}
|
|
|
154 |
return $emptyPathUri;
|
155 |
}
|
156 |
-
|
|
|
157 |
{
|
158 |
-
$sourceSegments =
|
159 |
-
$targetSegments =
|
160 |
-
|
161 |
-
$targetLastSegment =
|
162 |
foreach ($sourceSegments as $i => $segment) {
|
163 |
if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
|
164 |
unset($sourceSegments[$i], $targetSegments[$i]);
|
@@ -167,22 +193,25 @@ final class UriResolver
|
|
167 |
}
|
168 |
}
|
169 |
$targetSegments[] = $targetLastSegment;
|
170 |
-
$relativePath =
|
|
|
171 |
// A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
|
172 |
// This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
|
173 |
// as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
|
174 |
-
if ('' === $relativePath ||
|
175 |
-
$relativePath = "
|
176 |
} elseif ('/' === $relativePath[0]) {
|
177 |
if ($base->getAuthority() != '' && $base->getPath() === '') {
|
178 |
// In this case an extra slash is added by resolve() automatically. So we must not add one here.
|
179 |
-
$relativePath = "
|
180 |
} else {
|
181 |
-
$relativePath = "
|
182 |
}
|
183 |
}
|
|
|
184 |
return $relativePath;
|
185 |
}
|
|
|
186 |
private function __construct()
|
187 |
{
|
188 |
// cannot be instantiated
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\UriInterface;
|
5 |
|
|
|
6 |
/**
|
7 |
* Resolves a URI reference in the context of a base URI and the opposite way.
|
8 |
*
|
25 |
if ($path === '' || $path === '/') {
|
26 |
return $path;
|
27 |
}
|
28 |
+
|
29 |
$results = [];
|
30 |
+
$segments = explode('/', $path);
|
31 |
foreach ($segments as $segment) {
|
32 |
if ($segment === '..') {
|
33 |
+
array_pop($results);
|
34 |
} elseif ($segment !== '.') {
|
35 |
$results[] = $segment;
|
36 |
}
|
37 |
}
|
38 |
+
|
39 |
+
$newPath = implode('/', $results);
|
40 |
+
|
41 |
if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {
|
42 |
// Re-add the leading slash if necessary for cases like "/.."
|
43 |
$newPath = '/' . $newPath;
|
46 |
// If newPath is not empty, then $segment must be set and is the last segment from the foreach
|
47 |
$newPath .= '/';
|
48 |
}
|
49 |
+
|
50 |
return $newPath;
|
51 |
}
|
52 |
+
|
53 |
/**
|
54 |
* Converts the relative URI into a new URI that is resolved against the base URI.
|
55 |
*
|
59 |
* @return UriInterface
|
60 |
* @link http://tools.ietf.org/html/rfc3986#section-5.2
|
61 |
*/
|
62 |
+
public static function resolve(UriInterface $base, UriInterface $rel)
|
63 |
{
|
64 |
if ((string) $rel === '') {
|
65 |
// we can simply return the same base URI instance for this same-document reference
|
66 |
return $base;
|
67 |
}
|
68 |
+
|
69 |
if ($rel->getScheme() != '') {
|
70 |
return $rel->withPath(self::removeDotSegments($rel->getPath()));
|
71 |
}
|
72 |
+
|
73 |
if ($rel->getAuthority() != '') {
|
74 |
$targetAuthority = $rel->getAuthority();
|
75 |
$targetPath = self::removeDotSegments($rel->getPath());
|
86 |
if ($targetAuthority != '' && $base->getPath() === '') {
|
87 |
$targetPath = '/' . $rel->getPath();
|
88 |
} else {
|
89 |
+
$lastSlashPos = strrpos($base->getPath(), '/');
|
90 |
+
if ($lastSlashPos === false) {
|
91 |
$targetPath = $rel->getPath();
|
92 |
} else {
|
93 |
+
$targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();
|
94 |
}
|
95 |
}
|
96 |
}
|
98 |
$targetQuery = $rel->getQuery();
|
99 |
}
|
100 |
}
|
101 |
+
|
102 |
+
return new Uri(Uri::composeComponents(
|
103 |
+
$base->getScheme(),
|
104 |
+
$targetAuthority,
|
105 |
+
$targetPath,
|
106 |
+
$targetQuery,
|
107 |
+
$rel->getFragment()
|
108 |
+
));
|
109 |
}
|
110 |
+
|
111 |
/**
|
112 |
* Returns the target URI as a relative reference from the base URI.
|
113 |
*
|
134 |
*
|
135 |
* @return UriInterface The relative URI reference
|
136 |
*/
|
137 |
+
public static function relativize(UriInterface $base, UriInterface $target)
|
138 |
{
|
139 |
+
if ($target->getScheme() !== '' &&
|
140 |
+
($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')
|
141 |
+
) {
|
142 |
return $target;
|
143 |
}
|
144 |
+
|
145 |
+
if (Uri::isRelativePathReference($target)) {
|
146 |
// As the target is already highly relative we return it as-is. It would be possible to resolve
|
147 |
// the target with `$target = self::resolve($base, $target);` and then try make it more relative
|
148 |
// by removing a duplicate query. But let's not do that automatically.
|
149 |
return $target;
|
150 |
}
|
151 |
+
|
152 |
if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
|
153 |
return $target->withScheme('');
|
154 |
}
|
155 |
+
|
156 |
// We must remove the path before removing the authority because if the path starts with two slashes, the URI
|
157 |
// would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
|
158 |
// invalid.
|
159 |
$emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
|
160 |
+
|
161 |
if ($base->getPath() !== $target->getPath()) {
|
162 |
return $emptyPathUri->withPath(self::getRelativePath($base, $target));
|
163 |
}
|
164 |
+
|
165 |
if ($base->getQuery() === $target->getQuery()) {
|
166 |
// Only the target fragment is left. And it must be returned even if base and target fragment are the same.
|
167 |
return $emptyPathUri->withQuery('');
|
168 |
}
|
169 |
+
|
170 |
// If the base URI has a query but the target has none, we cannot return an empty path reference as it would
|
171 |
// inherit the base query component when resolving.
|
172 |
if ($target->getQuery() === '') {
|
173 |
+
$segments = explode('/', $target->getPath());
|
174 |
+
$lastSegment = end($segments);
|
175 |
+
|
176 |
return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
|
177 |
}
|
178 |
+
|
179 |
return $emptyPathUri;
|
180 |
}
|
181 |
+
|
182 |
+
private static function getRelativePath(UriInterface $base, UriInterface $target)
|
183 |
{
|
184 |
+
$sourceSegments = explode('/', $base->getPath());
|
185 |
+
$targetSegments = explode('/', $target->getPath());
|
186 |
+
array_pop($sourceSegments);
|
187 |
+
$targetLastSegment = array_pop($targetSegments);
|
188 |
foreach ($sourceSegments as $i => $segment) {
|
189 |
if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
|
190 |
unset($sourceSegments[$i], $targetSegments[$i]);
|
193 |
}
|
194 |
}
|
195 |
$targetSegments[] = $targetLastSegment;
|
196 |
+
$relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments);
|
197 |
+
|
198 |
// A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
|
199 |
// This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
|
200 |
// as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
|
201 |
+
if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) {
|
202 |
+
$relativePath = "./$relativePath";
|
203 |
} elseif ('/' === $relativePath[0]) {
|
204 |
if ($base->getAuthority() != '' && $base->getPath() === '') {
|
205 |
// In this case an extra slash is added by resolve() automatically. So we must not add one here.
|
206 |
+
$relativePath = ".$relativePath";
|
207 |
} else {
|
208 |
+
$relativePath = "./$relativePath";
|
209 |
}
|
210 |
}
|
211 |
+
|
212 |
return $relativePath;
|
213 |
}
|
214 |
+
|
215 |
private function __construct()
|
216 |
{
|
217 |
// cannot be instantiated
|
@@ -1,13 +1,13 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\MessageInterface;
|
6 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterface;
|
7 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ResponseInterface;
|
8 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\ServerRequestInterface;
|
9 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface;
|
10 |
-
use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
11 |
/**
|
12 |
* Returns the string representation of an HTTP message.
|
13 |
*
|
@@ -15,23 +15,30 @@ use _PhpScoper5bbb1f4b001f3\Psr\Http\Message\UriInterface;
|
|
15 |
*
|
16 |
* @return string
|
17 |
*/
|
18 |
-
function str(
|
19 |
{
|
20 |
-
if ($message instanceof
|
21 |
-
$msg =
|
|
|
|
|
22 |
if (!$message->hasHeader('host')) {
|
23 |
$msg .= "\r\nHost: " . $message->getUri()->getHost();
|
24 |
}
|
25 |
-
} elseif ($message instanceof
|
26 |
-
$msg = 'HTTP/' . $message->getProtocolVersion() . ' '
|
|
|
|
|
27 |
} else {
|
28 |
throw new \InvalidArgumentException('Unknown message type');
|
29 |
}
|
|
|
30 |
foreach ($message->getHeaders() as $name => $values) {
|
31 |
-
$msg .= "\r\n{$name}: " .
|
32 |
}
|
|
|
33 |
return "{$msg}\r\n\r\n" . $message->getBody();
|
34 |
}
|
|
|
35 |
/**
|
36 |
* Returns a UriInterface for the given value.
|
37 |
*
|
@@ -46,13 +53,15 @@ function str(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\MessageInterface $message
|
|
46 |
*/
|
47 |
function uri_for($uri)
|
48 |
{
|
49 |
-
if ($uri instanceof
|
50 |
return $uri;
|
51 |
-
} elseif (
|
52 |
-
return new
|
53 |
}
|
|
|
54 |
throw new \InvalidArgumentException('URI must be a string or UriInterface');
|
55 |
}
|
|
|
56 |
/**
|
57 |
* Create a new stream based on the input type.
|
58 |
*
|
@@ -68,41 +77,45 @@ function uri_for($uri)
|
|
68 |
*/
|
69 |
function stream_for($resource = '', array $options = [])
|
70 |
{
|
71 |
-
if (
|
72 |
-
$stream =
|
73 |
if ($resource !== '') {
|
74 |
-
|
75 |
-
|
76 |
}
|
77 |
-
return new
|
78 |
}
|
79 |
-
|
|
|
80 |
case 'resource':
|
81 |
-
return new
|
82 |
case 'object':
|
83 |
-
if ($resource instanceof
|
84 |
return $resource;
|
85 |
} elseif ($resource instanceof \Iterator) {
|
86 |
-
return new
|
87 |
if (!$resource->valid()) {
|
88 |
-
return
|
89 |
}
|
90 |
$result = $resource->current();
|
91 |
$resource->next();
|
92 |
return $result;
|
93 |
}, $options);
|
94 |
-
} elseif (
|
95 |
return stream_for((string) $resource, $options);
|
96 |
}
|
97 |
break;
|
98 |
case 'NULL':
|
99 |
-
return new
|
100 |
}
|
101 |
-
|
102 |
-
|
|
|
103 |
}
|
104 |
-
|
|
|
105 |
}
|
|
|
106 |
/**
|
107 |
* Parse an array of header values containing ";" separated data into an
|
108 |
* array of associative arrays representing the header key value pair
|
@@ -117,15 +130,16 @@ function parse_header($header)
|
|
117 |
{
|
118 |
static $trimmed = "\"' \n\t\r";
|
119 |
$params = $matches = [];
|
|
|
120 |
foreach (normalize_header($header) as $val) {
|
121 |
$part = [];
|
122 |
-
foreach (
|
123 |
-
if (
|
124 |
$m = $matches[0];
|
125 |
if (isset($m[1])) {
|
126 |
-
$part[
|
127 |
} else {
|
128 |
-
$part[] =
|
129 |
}
|
130 |
}
|
131 |
}
|
@@ -133,8 +147,10 @@ function parse_header($header)
|
|
133 |
$params[] = $part;
|
134 |
}
|
135 |
}
|
|
|
136 |
return $params;
|
137 |
}
|
|
|
138 |
/**
|
139 |
* Converts an array of header values that may contain comma separated
|
140 |
* headers into an array of headers with no comma separated values.
|
@@ -145,23 +161,26 @@ function parse_header($header)
|
|
145 |
*/
|
146 |
function normalize_header($header)
|
147 |
{
|
148 |
-
if (
|
149 |
-
return
|
150 |
}
|
|
|
151 |
$result = [];
|
152 |
foreach ($header as $value) {
|
153 |
foreach ((array) $value as $v) {
|
154 |
-
if (
|
155 |
$result[] = $v;
|
156 |
continue;
|
157 |
}
|
158 |
-
foreach (
|
159 |
-
$result[] =
|
160 |
}
|
161 |
}
|
162 |
}
|
|
|
163 |
return $result;
|
164 |
}
|
|
|
165 |
/**
|
166 |
* Clone and modify a request with the given changes.
|
167 |
*
|
@@ -179,43 +198,69 @@ function normalize_header($header)
|
|
179 |
*
|
180 |
* @return RequestInterface
|
181 |
*/
|
182 |
-
function modify_request(
|
183 |
{
|
184 |
if (!$changes) {
|
185 |
return $request;
|
186 |
}
|
|
|
187 |
$headers = $request->getHeaders();
|
|
|
188 |
if (!isset($changes['uri'])) {
|
189 |
$uri = $request->getUri();
|
190 |
} else {
|
191 |
// Remove the host header if one is on the URI
|
192 |
if ($host = $changes['uri']->getHost()) {
|
193 |
$changes['set_headers']['Host'] = $host;
|
|
|
194 |
if ($port = $changes['uri']->getPort()) {
|
195 |
$standardPorts = ['http' => 80, 'https' => 443];
|
196 |
$scheme = $changes['uri']->getScheme();
|
197 |
if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) {
|
198 |
-
$changes['set_headers']['Host'] .= ':'
|
199 |
}
|
200 |
}
|
201 |
}
|
202 |
$uri = $changes['uri'];
|
203 |
}
|
|
|
204 |
if (!empty($changes['remove_headers'])) {
|
205 |
$headers = _caseless_remove($changes['remove_headers'], $headers);
|
206 |
}
|
|
|
207 |
if (!empty($changes['set_headers'])) {
|
208 |
-
$headers = _caseless_remove(
|
209 |
$headers = $changes['set_headers'] + $headers;
|
210 |
}
|
|
|
211 |
if (isset($changes['query'])) {
|
212 |
$uri = $uri->withQuery($changes['query']);
|
213 |
}
|
214 |
-
|
215 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
}
|
217 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
}
|
|
|
219 |
/**
|
220 |
* Attempts to rewind a message body and throws an exception on failure.
|
221 |
*
|
@@ -226,13 +271,15 @@ function modify_request(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\RequestInterfa
|
|
226 |
*
|
227 |
* @throws \RuntimeException
|
228 |
*/
|
229 |
-
function rewind_body(
|
230 |
{
|
231 |
$body = $message->getBody();
|
|
|
232 |
if ($body->tell()) {
|
233 |
$body->rewind();
|
234 |
}
|
235 |
}
|
|
|
236 |
/**
|
237 |
* Safely opens a PHP stream resource using a filename.
|
238 |
*
|
@@ -248,17 +295,26 @@ function rewind_body(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\MessageInterface
|
|
248 |
function try_fopen($filename, $mode)
|
249 |
{
|
250 |
$ex = null;
|
251 |
-
|
252 |
-
$ex = new \RuntimeException(
|
|
|
|
|
|
|
|
|
|
|
253 |
});
|
254 |
-
|
255 |
-
|
|
|
|
|
256 |
if ($ex) {
|
257 |
/** @var $ex \RuntimeException */
|
258 |
throw $ex;
|
259 |
}
|
|
|
260 |
return $handle;
|
261 |
}
|
|
|
262 |
/**
|
263 |
* Copy the contents of a stream into a string until the given number of
|
264 |
* bytes have been read.
|
@@ -269,9 +325,10 @@ function try_fopen($filename, $mode)
|
|
269 |
* @return string
|
270 |
* @throws \RuntimeException on error.
|
271 |
*/
|
272 |
-
function copy_to_string(
|
273 |
{
|
274 |
$buffer = '';
|
|
|
275 |
if ($maxLen === -1) {
|
276 |
while (!$stream->eof()) {
|
277 |
$buf = $stream->read(1048576);
|
@@ -283,6 +340,7 @@ function copy_to_string(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
283 |
}
|
284 |
return $buffer;
|
285 |
}
|
|
|
286 |
$len = 0;
|
287 |
while (!$stream->eof() && $len < $maxLen) {
|
288 |
$buf = $stream->read($maxLen - $len);
|
@@ -291,10 +349,12 @@ function copy_to_string(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
291 |
break;
|
292 |
}
|
293 |
$buffer .= $buf;
|
294 |
-
$len =
|
295 |
}
|
|
|
296 |
return $buffer;
|
297 |
}
|
|
|
298 |
/**
|
299 |
* Copy the contents of a stream into another stream until the given number
|
300 |
* of bytes have been read.
|
@@ -306,9 +366,13 @@ function copy_to_string(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
306 |
*
|
307 |
* @throws \RuntimeException on error.
|
308 |
*/
|
309 |
-
function copy_to_stream(
|
310 |
-
|
|
|
|
|
|
|
311 |
$bufferSize = 8192;
|
|
|
312 |
if ($maxLen === -1) {
|
313 |
while (!$source->eof()) {
|
314 |
if (!$dest->write($source->read($bufferSize))) {
|
@@ -318,8 +382,8 @@ function copy_to_stream(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
318 |
} else {
|
319 |
$remaining = $maxLen;
|
320 |
while ($remaining > 0 && !$source->eof()) {
|
321 |
-
$buf = $source->read(
|
322 |
-
$len =
|
323 |
if (!$len) {
|
324 |
break;
|
325 |
}
|
@@ -328,6 +392,7 @@ function copy_to_stream(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
328 |
}
|
329 |
}
|
330 |
}
|
|
|
331 |
/**
|
332 |
* Calculate a hash of a Stream
|
333 |
*
|
@@ -338,20 +403,28 @@ function copy_to_stream(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterfac
|
|
338 |
* @return string Returns the hash of the stream
|
339 |
* @throws \RuntimeException on error.
|
340 |
*/
|
341 |
-
function hash(
|
342 |
-
|
|
|
|
|
|
|
343 |
$pos = $stream->tell();
|
|
|
344 |
if ($pos > 0) {
|
345 |
$stream->rewind();
|
346 |
}
|
347 |
-
|
|
|
348 |
while (!$stream->eof()) {
|
349 |
-
|
350 |
}
|
351 |
-
|
|
|
352 |
$stream->seek($pos);
|
|
|
353 |
return $out;
|
354 |
}
|
|
|
355 |
/**
|
356 |
* Read a line from the stream up to the maximum allowed buffer length
|
357 |
*
|
@@ -360,10 +433,11 @@ function hash(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface $stream,
|
|
360 |
*
|
361 |
* @return string|bool
|
362 |
*/
|
363 |
-
function readline(
|
364 |
{
|
365 |
$buffer = '';
|
366 |
$size = 0;
|
|
|
367 |
while (!$stream->eof()) {
|
368 |
// Using a loose equality here to match on '' and false.
|
369 |
if (null == ($byte = $stream->read(1))) {
|
@@ -375,8 +449,10 @@ function readline(\_PhpScoper5bbb1f4b001f3\Psr\Http\Message\StreamInterface $str
|
|
375 |
break;
|
376 |
}
|
377 |
}
|
|
|
378 |
return $buffer;
|
379 |
}
|
|
|
380 |
/**
|
381 |
* Parses a request message string into a request object.
|
382 |
*
|
@@ -388,14 +464,23 @@ function parse_request($message)
|
|
388 |
{
|
389 |
$data = _parse_message($message);
|
390 |
$matches = [];
|
391 |
-
if (
|
392 |
throw new \InvalidArgumentException('Invalid request string');
|
393 |
}
|
394 |
-
$parts =
|
395 |
-
$version = isset($parts[2]) ?
|
396 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
397 |
return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]);
|
398 |
}
|
|
|
399 |
/**
|
400 |
* Parses a response message string into a response object.
|
401 |
*
|
@@ -409,12 +494,20 @@ function parse_response($message)
|
|
409 |
// According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
|
410 |
// between status-code and reason-phrase is required. But browsers accept
|
411 |
// responses without space and reason as well.
|
412 |
-
if (
|
413 |
throw new \InvalidArgumentException('Invalid response string');
|
414 |
}
|
415 |
-
$parts =
|
416 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
}
|
|
|
418 |
/**
|
419 |
* Parse a query string into an associative array.
|
420 |
*
|
@@ -428,40 +521,43 @@ function parse_response($message)
|
|
428 |
*
|
429 |
* @return array
|
430 |
*/
|
431 |
-
function parse_query($str, $urlEncoding =
|
432 |
{
|
433 |
$result = [];
|
|
|
434 |
if ($str === '') {
|
435 |
return $result;
|
436 |
}
|
437 |
-
|
|
|
438 |
$decoder = function ($value) {
|
439 |
-
return
|
440 |
};
|
441 |
-
} elseif ($urlEncoding ==
|
442 |
$decoder = 'rawurldecode';
|
443 |
-
} elseif ($urlEncoding ==
|
444 |
$decoder = 'urldecode';
|
445 |
} else {
|
446 |
-
$decoder = function ($str) {
|
447 |
-
return $str;
|
448 |
-
};
|
449 |
}
|
450 |
-
|
451 |
-
|
|
|
452 |
$key = $decoder($parts[0]);
|
453 |
$value = isset($parts[1]) ? $decoder($parts[1]) : null;
|
454 |
if (!isset($result[$key])) {
|
455 |
$result[$key] = $value;
|
456 |
} else {
|
457 |
-
if (
|
458 |
$result[$key] = [$result[$key]];
|
459 |
}
|
460 |
$result[$key][] = $value;
|
461 |
}
|
462 |
}
|
|
|
463 |
return $result;
|
464 |
}
|
|
|
465 |
/**
|
466 |
* Build a query string from an array of key value pairs.
|
467 |
*
|
@@ -475,26 +571,26 @@ function parse_query($str, $urlEncoding = \true)
|
|
475 |
* to encode using RFC1738.
|
476 |
* @return string
|
477 |
*/
|
478 |
-
function build_query(array $params, $encoding =
|
479 |
{
|
480 |
if (!$params) {
|
481 |
return '';
|
482 |
}
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
} elseif ($encoding === \PHP_QUERY_RFC3986) {
|
488 |
$encoder = 'rawurlencode';
|
489 |
-
} elseif ($encoding ===
|
490 |
$encoder = 'urlencode';
|
491 |
} else {
|
492 |
throw new \InvalidArgumentException('Invalid type');
|
493 |
}
|
|
|
494 |
$qs = '';
|
495 |
foreach ($params as $k => $v) {
|
496 |
$k = $encoder($k);
|
497 |
-
if (
|
498 |
$qs .= $k;
|
499 |
if ($v !== null) {
|
500 |
$qs .= '=' . $encoder($v);
|
@@ -510,8 +606,10 @@ function build_query(array $params, $encoding = \PHP_QUERY_RFC3986)
|
|
510 |
}
|
511 |
}
|
512 |
}
|
513 |
-
|
|
|
514 |
}
|
|
|
515 |
/**
|
516 |
* Determines the mimetype of a file by looking at its extension.
|
517 |
*
|
@@ -521,8 +619,9 @@ function build_query(array $params, $encoding = \PHP_QUERY_RFC3986)
|
|
521 |
*/
|
522 |
function mimetype_from_filename($filename)
|
523 |
{
|
524 |
-
return mimetype_from_extension(
|
525 |
}
|
|
|
526 |
/**
|
527 |
* Maps a file extensions to a mimetype.
|
528 |
*
|
@@ -533,10 +632,114 @@ function mimetype_from_filename($filename)
|
|
533 |
*/
|
534 |
function mimetype_from_extension($extension)
|
535 |
{
|
536 |
-
static $mimetypes = [
|
537 |
-
|
538 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
}
|
|
|
540 |
/**
|
541 |
* Parses an HTTP message into an associative array.
|
542 |
*
|
@@ -554,28 +757,32 @@ function _parse_message($message)
|
|
554 |
if (!$message) {
|
555 |
throw new \InvalidArgumentException('Invalid message');
|
556 |
}
|
|
|
557 |
// Iterate over each line in the message, accounting for line endings
|
558 |
-
$lines =
|
559 |
-
$result = ['start-line' =>
|
560 |
-
|
561 |
-
|
|
|
562 |
$line = $lines[$i];
|
563 |
// If two line breaks were encountered, then this is the end of body
|
564 |
if (empty($line)) {
|
565 |
if ($i < $totalLines - 1) {
|
566 |
-
$result['body'] =
|
567 |
}
|
568 |
break;
|
569 |
}
|
570 |
-
if (
|
571 |
-
$parts =
|
572 |
-
$key =
|
573 |
-
$value = isset($parts[1]) ?
|
574 |
$result['headers'][$key][] = $value;
|
575 |
}
|
576 |
}
|
|
|
577 |
return $result;
|
578 |
}
|
|
|
579 |
/**
|
580 |
* Constructs a URI for an HTTP request message.
|
581 |
*
|
@@ -587,28 +794,35 @@ function _parse_message($message)
|
|
587 |
*/
|
588 |
function _parse_request_uri($path, array $headers)
|
589 |
{
|
590 |
-
$hostKey =
|
591 |
-
return
|
592 |
});
|
|
|
593 |
// If no host is found, then a full URI cannot be constructed.
|
594 |
if (!$hostKey) {
|
595 |
return $path;
|
596 |
}
|
597 |
-
|
598 |
-
$
|
599 |
-
|
|
|
|
|
600 |
}
|
|
|
601 |
/** @internal */
|
602 |
function _caseless_remove($keys, array $data)
|
603 |
{
|
604 |
$result = [];
|
|
|
605 |
foreach ($keys as &$key) {
|
606 |
-
$key =
|
607 |
}
|
|
|
608 |
foreach ($data as $k => $v) {
|
609 |
-
if (
|
610 |
$result[$k] = $v;
|
611 |
}
|
612 |
}
|
|
|
613 |
return $result;
|
614 |
}
|
1 |
<?php
|
2 |
+
namespace GuzzleHttp\Psr7;
|
3 |
|
4 |
+
use Psr\Http\Message\MessageInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
use Psr\Http\Message\ServerRequestInterface;
|
8 |
+
use Psr\Http\Message\StreamInterface;
|
9 |
+
use Psr\Http\Message\UriInterface;
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* Returns the string representation of an HTTP message.
|
13 |
*
|
15 |
*
|
16 |
* @return string
|
17 |
*/
|
18 |
+
function str(MessageInterface $message)
|
19 |
{
|
20 |
+
if ($message instanceof RequestInterface) {
|
21 |
+
$msg = trim($message->getMethod() . ' '
|
22 |
+
. $message->getRequestTarget())
|
23 |
+
. ' HTTP/' . $message->getProtocolVersion();
|
24 |
if (!$message->hasHeader('host')) {
|
25 |
$msg .= "\r\nHost: " . $message->getUri()->getHost();
|
26 |
}
|
27 |
+
} elseif ($message instanceof ResponseInterface) {
|
28 |
+
$msg = 'HTTP/' . $message->getProtocolVersion() . ' '
|
29 |
+
. $message->getStatusCode() . ' '
|
30 |
+
. $message->getReasonPhrase();
|
31 |
} else {
|
32 |
throw new \InvalidArgumentException('Unknown message type');
|
33 |
}
|
34 |
+
|
35 |
foreach ($message->getHeaders() as $name => $values) {
|
36 |
+
$msg .= "\r\n{$name}: " . implode(', ', $values);
|
37 |
}
|
38 |
+
|
39 |
return "{$msg}\r\n\r\n" . $message->getBody();
|
40 |
}
|
41 |
+
|
42 |
/**
|
43 |
* Returns a UriInterface for the given value.
|
44 |
*
|
53 |
*/
|
54 |
function uri_for($uri)
|
55 |
{
|
56 |
+
if ($uri instanceof UriInterface) {
|
57 |
return $uri;
|
58 |
+
} elseif (is_string($uri)) {
|
59 |
+
return new Uri($uri);
|
60 |
}
|
61 |
+
|
62 |
throw new \InvalidArgumentException('URI must be a string or UriInterface');
|
63 |
}
|
64 |
+
|
65 |
/**
|
66 |
* Create a new stream based on the input type.
|
67 |
*
|
77 |
*/
|
78 |
function stream_for($resource = '', array $options = [])
|
79 |
{
|
80 |
+
if (is_scalar($resource)) {
|
81 |
+
$stream = fopen('php://temp', 'r+');
|
82 |
if ($resource !== '') {
|
83 |
+
fwrite($stream, $resource);
|
84 |
+
fseek($stream, 0);
|
85 |
}
|
86 |
+
return new Stream($stream, $options);
|
87 |
}
|
88 |
+
|
89 |
+
switch (gettype($resource)) {
|
90 |
case 'resource':
|
91 |
+
return new Stream($resource, $options);
|
92 |
case 'object':
|
93 |
+
if ($resource instanceof StreamInterface) {
|
94 |
return $resource;
|
95 |
} elseif ($resource instanceof \Iterator) {
|
96 |
+
return new PumpStream(function () use ($resource) {
|
97 |
if (!$resource->valid()) {
|
98 |
+
return false;
|
99 |
}
|
100 |
$result = $resource->current();
|
101 |
$resource->next();
|
102 |
return $result;
|
103 |
}, $options);
|
104 |
+
} elseif (method_exists($resource, '__toString')) {
|
105 |
return stream_for((string) $resource, $options);
|
106 |
}
|
107 |
break;
|
108 |
case 'NULL':
|
109 |
+
return new Stream(fopen('php://temp', 'r+'), $options);
|
110 |
}
|
111 |
+
|
112 |
+
if (is_callable($resource)) {
|
113 |
+
return new PumpStream($resource, $options);
|
114 |
}
|
115 |
+
|
116 |
+
throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource));
|
117 |
}
|
118 |
+
|
119 |
/**
|
120 |
* Parse an array of header values containing ";" separated data into an
|
121 |
* array of associative arrays representing the header key value pair
|
130 |
{
|
131 |
static $trimmed = "\"' \n\t\r";
|
132 |
$params = $matches = [];
|
133 |
+
|
134 |
foreach (normalize_header($header) as $val) {
|
135 |
$part = [];
|
136 |
+
foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
|
137 |
+
if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
|
138 |
$m = $matches[0];
|
139 |
if (isset($m[1])) {
|
140 |
+
$part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);
|
141 |
} else {
|
142 |
+
$part[] = trim($m[0], $trimmed);
|
143 |
}
|
144 |
}
|
145 |
}
|
147 |
$params[] = $part;
|
148 |
}
|
149 |
}
|
150 |
+
|
151 |
return $params;
|
152 |
}
|
153 |
+
|
154 |
/**
|
155 |
* Converts an array of header values that may contain comma separated
|
156 |
* headers into an array of headers with no comma separated values.
|
161 |
*/
|
162 |
function normalize_header($header)
|
163 |
{
|
164 |
+
if (!is_array($header)) {
|
165 |
+
return array_map('trim', explode(',', $header));
|
166 |
}
|
167 |
+
|
168 |
$result = [];
|
169 |
foreach ($header as $value) {
|
170 |
foreach ((array) $value as $v) {
|
171 |
+
if (strpos($v, ',') === false) {
|
172 |
$result[] = $v;
|
173 |
continue;
|
174 |
}
|
175 |
+
foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) {
|
176 |
+
$result[] = trim($vv);
|
177 |
}
|
178 |
}
|
179 |
}
|
180 |
+
|
181 |
return $result;
|
182 |
}
|
183 |
+
|
184 |
/**
|
185 |
* Clone and modify a request with the given changes.
|
186 |
*
|
198 |
*
|
199 |
* @return RequestInterface
|
200 |
*/
|
201 |
+
function modify_request(RequestInterface $request, array $changes)
|
202 |
{
|
203 |
if (!$changes) {
|
204 |
return $request;
|
205 |
}
|
206 |
+
|
207 |
$headers = $request->getHeaders();
|
208 |
+
|
209 |
if (!isset($changes['uri'])) {
|
210 |
$uri = $request->getUri();
|
211 |
} else {
|
212 |
// Remove the host header if one is on the URI
|
213 |
if ($host = $changes['uri']->getHost()) {
|
214 |
$changes['set_headers']['Host'] = $host;
|
215 |
+
|
216 |
if ($port = $changes['uri']->getPort()) {
|
217 |
$standardPorts = ['http' => 80, 'https' => 443];
|
218 |
$scheme = $changes['uri']->getScheme();
|
219 |
if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) {
|
220 |
+
$changes['set_headers']['Host'] .= ':'.$port;
|
221 |
}
|
222 |
}
|
223 |
}
|
224 |
$uri = $changes['uri'];
|
225 |
}
|
226 |
+
|
227 |
if (!empty($changes['remove_headers'])) {
|
228 |
$headers = _caseless_remove($changes['remove_headers'], $headers);
|
229 |
}
|
230 |
+
|
231 |
if (!empty($changes['set_headers'])) {
|
232 |
+
$headers = _caseless_remove(array_keys($changes['set_headers']), $headers);
|
233 |
$headers = $changes['set_headers'] + $headers;
|
234 |
}
|
235 |
+
|
236 |
if (isset($changes['query'])) {
|
237 |
$uri = $uri->withQuery($changes['query']);
|
238 |
}
|
239 |
+
|
240 |
+
if ($request instanceof ServerRequestInterface) {
|
241 |
+
return new ServerRequest(
|
242 |
+
isset($changes['method']) ? $changes['method'] : $request->getMethod(),
|
243 |
+
$uri,
|
244 |
+
$headers,
|
245 |
+
isset($changes['body']) ? $changes['body'] : $request->getBody(),
|
246 |
+
isset($changes['version'])
|
247 |
+
? $changes['version']
|
248 |
+
: $request->getProtocolVersion(),
|
249 |
+
$request->getServerParams()
|
250 |
+
);
|
251 |
}
|
252 |
+
|
253 |
+
return new Request(
|
254 |
+
isset($changes['method']) ? $changes['method'] : $request->getMethod(),
|
255 |
+
$uri,
|
256 |
+
$headers,
|
257 |
+
isset($changes['body']) ? $changes['body'] : $request->getBody(),
|
258 |
+
isset($changes['version'])
|
259 |
+
? $changes['version']
|
260 |
+
: $request->getProtocolVersion()
|
261 |
+
);
|
262 |
}
|
263 |
+
|
264 |
/**
|
265 |
* Attempts to rewind a message body and throws an exception on failure.
|
266 |
*
|
271 |
*
|
272 |
* @throws \RuntimeException
|
273 |
*/
|
274 |
+
function rewind_body(MessageInterface $message)
|
275 |
{
|
276 |
$body = $message->getBody();
|
277 |
+
|
278 |
if ($body->tell()) {
|
279 |
$body->rewind();
|
280 |
}
|
281 |
}
|
282 |
+
|
283 |
/**
|
284 |
* Safely opens a PHP stream resource using a filename.
|
285 |
*
|
295 |
function try_fopen($filename, $mode)
|
296 |
{
|
297 |
$ex = null;
|
298 |
+
set_error_handler(function () use ($filename, $mode, &$ex) {
|
299 |
+
$ex = new \RuntimeException(sprintf(
|
300 |
+
'Unable to open %s using mode %s: %s',
|
301 |
+
$filename,
|
302 |
+
$mode,
|
303 |
+
func_get_args()[1]
|
304 |
+
));
|
305 |
});
|
306 |
+
|
307 |
+
$handle = fopen($filename, $mode);
|
308 |
+
restore_error_handler();
|
309 |
+
|
310 |
if ($ex) {
|
311 |
/** @var $ex \RuntimeException */
|
312 |
throw $ex;
|
313 |
}
|
314 |
+
|
315 |
return $handle;
|
316 |
}
|
317 |
+
|
318 |
/**
|
319 |
* Copy the contents of a stream into a string until the given number of
|
320 |
* bytes have been read.
|
325 |
* @return string
|
326 |
* @throws \RuntimeException on error.
|
327 |
*/
|
328 |
+
function copy_to_string(StreamInterface $stream, $maxLen = -1)
|
329 |
{
|
330 |
$buffer = '';
|
331 |
+
|
332 |
if ($maxLen === -1) {
|
333 |
while (!$stream->eof()) {
|
334 |
$buf = $stream->read(1048576);
|
340 |
}
|
341 |
return $buffer;
|
342 |
}
|
343 |
+
|
344 |
$len = 0;
|
345 |
while (!$stream->eof() && $len < $maxLen) {
|
346 |
$buf = $stream->read($maxLen - $len);
|
349 |
break;
|
350 |
}
|
351 |
$buffer .= $buf;
|
352 |
+
$len = strlen($buffer);
|
353 |
}
|
354 |
+
|
355 |
return $buffer;
|
356 |
}
|
357 |
+
|
358 |
/**
|
359 |
* Copy the contents of a stream into another stream until the given number
|
360 |
* of bytes have been read.
|
366 |
*
|
367 |
* @throws \RuntimeException on error.
|
368 |
*/
|
369 |
+
function copy_to_stream(
|
370 |
+
StreamInterface $source,
|
371 |
+
StreamInterface $dest,
|
372 |
+
$maxLen = -1
|
373 |
+
) {
|
374 |
$bufferSize = 8192;
|
375 |
+
|
376 |
if ($maxLen === -1) {
|
377 |
while (!$source->eof()) {
|
378 |
if (!$dest->write($source->read($bufferSize))) {
|
382 |
} else {
|
383 |
$remaining = $maxLen;
|
384 |
while ($remaining > 0 && !$source->eof()) {
|
385 |
+
$buf = $source->read(min($bufferSize, $remaining));
|
386 |
+
$len = strlen($buf);
|
387 |
if (!$len) {
|
388 |
break;
|
389 |
}
|
392 |
}
|
393 |
}
|
394 |
}
|
395 |
+
|
396 |
/**
|
397 |
* Calculate a hash of a Stream
|
398 |
*
|
403 |
* @return string Returns the hash of the stream
|
404 |
* @throws \RuntimeException on error.
|
405 |
*/
|
406 |
+
function hash(
|
407 |
+
StreamInterface $stream,
|
408 |
+
$algo,
|
409 |
+
$rawOutput = false
|
410 |
+
) {
|
411 |
$pos = $stream->tell();
|
412 |
+
|
413 |
if ($pos > 0) {
|
414 |
$stream->rewind();
|
415 |
}
|
416 |
+
|
417 |
+
$ctx = hash_init($algo);
|
418 |
while (!$stream->eof()) {
|
419 |
+
hash_update($ctx, $stream->read(1048576));
|
420 |
}
|
421 |
+
|
422 |
+
$out = hash_final($ctx, (bool) $rawOutput);
|
423 |
$stream->seek($pos);
|
424 |
+
|
425 |
return $out;
|
426 |
}
|
427 |
+
|
428 |
/**
|
429 |
* Read a line from the stream up to the maximum allowed buffer length
|
430 |
*
|
433 |
*
|
434 |
* @return string|bool
|
435 |
*/
|
436 |
+
function readline(StreamInterface $stream, $maxLength = null)
|
437 |
{
|
438 |
$buffer = '';
|
439 |
$size = 0;
|
440 |
+
|
441 |
while (!$stream->eof()) {
|
442 |
// Using a loose equality here to match on '' and false.
|
443 |
if (null == ($byte = $stream->read(1))) {
|
449 |
break;
|
450 |
}
|
451 |
}
|
452 |
+
|
453 |
return $buffer;
|
454 |
}
|
455 |
+
|
456 |
/**
|
457 |
* Parses a request message string into a request object.
|
458 |
*
|
464 |
{
|
465 |
$data = _parse_message($message);
|
466 |
$matches = [];
|
467 |
+
if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) {
|
468 |
throw new \InvalidArgumentException('Invalid request string');
|
469 |
}
|
470 |
+
$parts = explode(' ', $data['start-line'], 3);
|
471 |
+
$version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1';
|
472 |
+
|
473 |
+
$request = new Request(
|
474 |
+
$parts[0],
|
475 |
+
$matches[1] === '/' ? _parse_request_uri($parts[1], $data['headers']) : $parts[1],
|
476 |
+
$data['headers'],
|
477 |
+
$data['body'],
|
478 |
+
$version
|
479 |
+
);
|
480 |
+
|
481 |
return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]);
|
482 |
}
|
483 |
+
|
484 |
/**
|
485 |
* Parses a response message string into a response object.
|
486 |
*
|
494 |
// According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
|
495 |
// between status-code and reason-phrase is required. But browsers accept
|
496 |
// responses without space and reason as well.
|
497 |
+
if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
|
498 |
throw new \InvalidArgumentException('Invalid response string');
|
499 |
}
|
500 |
+
$parts = explode(' ', $data['start-line'], 3);
|
501 |
+
|
502 |
+
return new Response(
|
503 |
+
$parts[1],
|
504 |
+
$data['headers'],
|
505 |
+
$data['body'],
|
506 |
+
explode('/', $parts[0])[1],
|
507 |
+
isset($parts[2]) ? $parts[2] : null
|
508 |
+
);
|
509 |
}
|
510 |
+
|
511 |
/**
|
512 |
* Parse a query string into an associative array.
|
513 |
*
|
521 |
*
|
522 |
* @return array
|
523 |
*/
|
524 |
+
function parse_query($str, $urlEncoding = true)
|
525 |
{
|
526 |
$result = [];
|
527 |
+
|
528 |
if ($str === '') {
|
529 |
return $result;
|
530 |
}
|
531 |
+
|
532 |
+
if ($urlEncoding === true) {
|
533 |
$decoder = function ($value) {
|
534 |
+
return rawurldecode(str_replace('+', ' ', $value));
|
535 |
};
|
536 |
+
} elseif ($urlEncoding == PHP_QUERY_RFC3986) {
|
537 |
$decoder = 'rawurldecode';
|
538 |
+
} elseif ($urlEncoding == PHP_QUERY_RFC1738) {
|
539 |
$decoder = 'urldecode';
|
540 |
} else {
|
541 |
+
$decoder = function ($str) { return $str; };
|
|
|
|
|
542 |
}
|
543 |
+
|
544 |
+
foreach (explode('&', $str) as $kvp) {
|
545 |
+
$parts = explode('=', $kvp, 2);
|
546 |
$key = $decoder($parts[0]);
|
547 |
$value = isset($parts[1]) ? $decoder($parts[1]) : null;
|
548 |
if (!isset($result[$key])) {
|
549 |
$result[$key] = $value;
|
550 |
} else {
|
551 |
+
if (!is_array($result[$key])) {
|
552 |
$result[$key] = [$result[$key]];
|
553 |
}
|
554 |
$result[$key][] = $value;
|
555 |
}
|
556 |
}
|
557 |
+
|
558 |
return $result;
|
559 |
}
|
560 |
+
|
561 |
/**
|
562 |
* Build a query string from an array of key value pairs.
|
563 |
*
|
571 |
* to encode using RFC1738.
|
572 |
* @return string
|
573 |
*/
|
574 |
+
function build_query(array $params, $encoding = PHP_QUERY_RFC3986)
|
575 |
{
|
576 |
if (!$params) {
|
577 |
return '';
|
578 |
}
|
579 |
+
|
580 |
+
if ($encoding === false) {
|
581 |
+
$encoder = function ($str) { return $str; };
|
582 |
+
} elseif ($encoding === PHP_QUERY_RFC3986) {
|
|
|
583 |
$encoder = 'rawurlencode';
|
584 |
+
} elseif ($encoding === PHP_QUERY_RFC1738) {
|
585 |
$encoder = 'urlencode';
|
586 |
} else {
|
587 |
throw new \InvalidArgumentException('Invalid type');
|
588 |
}
|
589 |
+
|
590 |
$qs = '';
|
591 |
foreach ($params as $k => $v) {
|
592 |
$k = $encoder($k);
|
593 |
+
if (!is_array($v)) {
|
594 |
$qs .= $k;
|
595 |
if ($v !== null) {
|
596 |
$qs .= '=' . $encoder($v);
|
606 |
}
|
607 |
}
|
608 |
}
|
609 |
+
|
610 |
+
return $qs ? (string) substr($qs, 0, -1) : '';
|
611 |
}
|
612 |
+
|
613 |
/**
|
614 |
* Determines the mimetype of a file by looking at its extension.
|
615 |
*
|
619 |
*/
|
620 |
function mimetype_from_filename($filename)
|
621 |
{
|
622 |
+
return mimetype_from_extension(pathinfo($filename, PATHINFO_EXTENSION));
|
623 |
}
|
624 |
+
|
625 |
/**
|
626 |
* Maps a file extensions to a mimetype.
|
627 |
*
|
632 |
*/
|
633 |
function mimetype_from_extension($extension)
|
634 |
{
|
635 |
+
static $mimetypes = [
|
636 |
+
'7z' => 'application/x-7z-compressed',
|
637 |
+
'aac' => 'audio/x-aac',
|
638 |
+
'ai' => 'application/postscript',
|
639 |
+
'aif' => 'audio/x-aiff',
|
640 |
+
'asc' => 'text/plain',
|
641 |
+
'asf' => 'video/x-ms-asf',
|
642 |
+
'atom' => 'application/atom+xml',
|
643 |
+
'avi' => 'video/x-msvideo',
|
644 |
+
'bmp' => 'image/bmp',
|
645 |
+
'bz2' => 'application/x-bzip2',
|
646 |
+
'cer' => 'application/pkix-cert',
|
647 |
+
'crl' => 'application/pkix-crl',
|
648 |
+
'crt' => 'application/x-x509-ca-cert',
|
649 |
+
'css' => 'text/css',
|
650 |
+
'csv' => 'text/csv',
|
651 |
+
'cu' => 'application/cu-seeme',
|
652 |
+
'deb' => 'application/x-debian-package',
|
653 |
+
'doc' => 'application/msword',
|
654 |
+
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
655 |
+
'dvi' => 'application/x-dvi',
|
656 |
+
'eot' => 'application/vnd.ms-fontobject',
|
657 |
+
'eps' => 'application/postscript',
|
658 |
+
'epub' => 'application/epub+zip',
|
659 |
+
'etx' => 'text/x-setext',
|
660 |
+
'flac' => 'audio/flac',
|
661 |
+
'flv' => 'video/x-flv',
|
662 |
+
'gif' => 'image/gif',
|
663 |
+
'gz' => 'application/gzip',
|
664 |
+
'htm' => 'text/html',
|
665 |
+
'html' => 'text/html',
|
666 |
+
'ico' => 'image/x-icon',
|
667 |
+
'ics' => 'text/calendar',
|
668 |
+
'ini' => 'text/plain',
|
669 |
+
'iso' => 'application/x-iso9660-image',
|
670 |
+
'jar' => 'application/java-archive',
|
671 |
+
'jpe' => 'image/jpeg',
|
672 |
+
'jpeg' => 'image/jpeg',
|
673 |
+
'jpg' => 'image/jpeg',
|
674 |
+
'js' => 'text/javascript',
|
675 |
+
'json' => 'application/json',
|
676 |
+
'latex' => 'application/x-latex',
|
677 |
+
'log' => 'text/plain',
|
678 |
+
'm4a' => 'audio/mp4',
|
679 |
+
'm4v' => 'video/mp4',
|
680 |
+
'mid' => 'audio/midi',
|
681 |
+
'midi' => 'audio/midi',
|
682 |
+
'mov' => 'video/quicktime',
|
683 |
+
'mp3' => 'audio/mpeg',
|
684 |
+
'mp4' => 'video/mp4',
|
685 |
+
'mp4a' => 'audio/mp4',
|
686 |
+
'mp4v' => 'video/mp4',
|
687 |
+
'mpe' => 'video/mpeg',
|
688 |
+
'mpeg' => 'video/mpeg',
|
689 |
+
'mpg' => 'video/mpeg',
|
690 |
+
'mpg4' => 'video/mp4',
|
691 |
+
'oga' => 'audio/ogg',
|
692 |
+
'ogg' => 'audio/ogg',
|
693 |
+
'ogv' => 'video/ogg',
|
694 |
+
'ogx' => 'application/ogg',
|
695 |
+
'pbm' => 'image/x-portable-bitmap',
|
696 |
+
'pdf' => 'application/pdf',
|
697 |
+
'pgm' => 'image/x-portable-graymap',
|
698 |
+
'png' => 'image/png',
|
699 |
+
'pnm' => 'image/x-portable-anymap',
|
700 |
+
'ppm' => 'image/x-portable-pixmap',
|
701 |
+
'ppt' => 'application/vnd.ms-powerpoint',
|
702 |
+
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
703 |
+
'ps' => 'application/postscript',
|
704 |
+
'qt' => 'video/quicktime',
|
705 |
+
'rar' => 'application/x-rar-compressed',
|
706 |
+
'ras' => 'image/x-cmu-raster',
|
707 |
+
'rss' => 'application/rss+xml',
|
708 |
+
'rtf' => 'application/rtf',
|
709 |
+
'sgm' => 'text/sgml',
|
710 |
+
'sgml' => 'text/sgml',
|
711 |
+
'svg' => 'image/svg+xml',
|
712 |
+
'swf' => 'application/x-shockwave-flash',
|
713 |
+
'tar' => 'application/x-tar',
|
714 |
+
'tif' => 'image/tiff',
|
715 |
+
'tiff' => 'image/tiff',
|
716 |
+
'torrent' => 'application/x-bittorrent',
|
717 |
+
'ttf' => 'application/x-font-ttf',
|
718 |
+
'txt' => 'text/plain',
|
719 |
+
'wav' => 'audio/x-wav',
|
720 |
+
'webm' => 'video/webm',
|
721 |
+
'wma' => 'audio/x-ms-wma',
|
722 |
+
'wmv' => 'video/x-ms-wmv',
|
723 |
+
'woff' => 'application/x-font-woff',
|
724 |
+
'wsdl' => 'application/wsdl+xml',
|
725 |
+
'xbm' => 'image/x-xbitmap',
|
726 |
+
'xls' => 'application/vnd.ms-excel',
|
727 |
+
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
728 |
+
'xml' => 'application/xml',
|
729 |
+
'xpm' => 'image/x-xpixmap',
|
730 |
+
'xwd' => 'image/x-xwindowdump',
|
731 |
+
'yaml' => 'text/yaml',
|
732 |
+
'yml' => 'text/yaml',
|
733 |
+
'zip' => 'application/zip',
|
734 |
+
];
|
735 |
+
|
736 |
+
$extension = strtolower($extension);
|
737 |
+
|
738 |
+
return isset($mimetypes[$extension])
|
739 |
+
? $mimetypes[$extension]
|
740 |
+
: null;
|
741 |
}
|
742 |
+
|
743 |
/**
|
744 |
* Parses an HTTP message into an associative array.
|
745 |
*
|
757 |
if (!$message) {
|
758 |
throw new \InvalidArgumentException('Invalid message');
|
759 |
}
|
760 |
+
|
761 |
// Iterate over each line in the message, accounting for line endings
|
762 |
+
$lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
|
763 |
+
$result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => ''];
|
764 |
+
array_shift($lines);
|
765 |
+
|
766 |
+
for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
|
767 |
$line = $lines[$i];
|
768 |
// If two line breaks were encountered, then this is the end of body
|
769 |
if (empty($line)) {
|
770 |
if ($i < $totalLines - 1) {
|
771 |
+
$result['body'] = implode('', array_slice($lines, $i + 2));
|
772 |
}
|
773 |
break;
|
774 |
}
|
775 |
+
if (strpos($line, ':')) {
|
776 |
+
$parts = explode(':', $line, 2);
|
777 |
+
$key = trim($parts[0]);
|
778 |
+
$value = isset($parts[1]) ? trim($parts[1]) : '';
|
779 |
$result['headers'][$key][] = $value;
|
780 |
}
|
781 |
}
|
782 |
+
|
783 |
return $result;
|
784 |
}
|
785 |
+
|
786 |
/**
|
787 |
* Constructs a URI for an HTTP request message.
|
788 |
*
|
794 |
*/
|
795 |
function _parse_request_uri($path, array $headers)
|
796 |
{
|
797 |
+
$hostKey = array_filter(array_keys($headers), function ($k) {
|
798 |
+
return strtolower($k) === 'host';
|
799 |
});
|
800 |
+
|
801 |
// If no host is found, then a full URI cannot be constructed.
|
802 |
if (!$hostKey) {
|
803 |
return $path;
|
804 |
}
|
805 |
+
|
806 |
+
$host = $headers[reset($hostKey)][0];
|
807 |
+
$scheme = substr($host, -4) === ':443' ? 'https' : 'http';
|
808 |
+
|
809 |
+
return $scheme . '://' . $host . '/' . ltrim($path, '/');
|
810 |
}
|
811 |
+
|
812 |
/** @internal */
|
813 |
function _caseless_remove($keys, array $data)
|
814 |
{
|
815 |
$result = [];
|
816 |
+
|
817 |
foreach ($keys as &$key) {
|
818 |
+
$key = strtolower($key);
|
819 |
}
|
820 |
+
|
821 |
foreach ($data as $k => $v) {
|
822 |
+
if (!in_array(strtolower($k), $keys)) {
|
823 |
$result[$k] = $v;
|
824 |
}
|
825 |
}
|
826 |
+
|
827 |
return $result;
|
828 |
}
|
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3;
|
4 |
-
|
5 |
// Don't redefine the functions if included multiple times.
|
6 |
-
if (
|
7 |
require __DIR__ . '/functions.php';
|
8 |
}
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
// Don't redefine the functions if included multiple times.
|
4 |
+
if (!function_exists('GuzzleHttp\Psr7\str')) {
|
5 |
require __DIR__ . '/functions.php';
|
6 |
}
|
@@ -1,20 +1,13 @@
|
|
1 |
{
|
2 |
-
"name": "psr
|
3 |
"description": "Common interface for HTTP messages",
|
4 |
-
"keywords": [
|
5 |
-
|
6 |
-
"psr-7",
|
7 |
-
"http",
|
8 |
-
"http-message",
|
9 |
-
"request",
|
10 |
-
"response"
|
11 |
-
],
|
12 |
-
"homepage": "https:\/\/github.com\/php-fig\/http-message",
|
13 |
"license": "MIT",
|
14 |
"authors": [
|
15 |
{
|
16 |
"name": "PHP-FIG",
|
17 |
-
"homepage": "http
|
18 |
}
|
19 |
],
|
20 |
"require": {
|
@@ -22,7 +15,7 @@
|
|
22 |
},
|
23 |
"autoload": {
|
24 |
"psr-4": {
|
25 |
-
"
|
26 |
}
|
27 |
},
|
28 |
"extra": {
|
@@ -30,4 +23,4 @@
|
|
30 |
"dev-master": "1.0.x-dev"
|
31 |
}
|
32 |
}
|
33 |
-
}
|
1 |
{
|
2 |
+
"name": "psr/http-message",
|
3 |
"description": "Common interface for HTTP messages",
|
4 |
+
"keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
|
5 |
+
"homepage": "https://github.com/php-fig/http-message",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
8 |
{
|
9 |
"name": "PHP-FIG",
|
10 |
+
"homepage": "http://www.php-fig.org/"
|
11 |
}
|
12 |
],
|
13 |
"require": {
|
15 |
},
|
16 |
"autoload": {
|
17 |
"psr-4": {
|
18 |
+
"Psr\\Http\\Message\\": "src/"
|
19 |
}
|
20 |
},
|
21 |
"extra": {
|
23 |
"dev-master": "1.0.x-dev"
|
24 |
}
|
25 |
}
|
26 |
+
}
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace
|
4 |
|
5 |
/**
|
6 |
* HTTP messages consist of requests from a client to a server and responses
|
@@ -24,6 +24,7 @@ interface MessageInterface
|
|
24 |
* @return string HTTP protocol version.
|
25 |
*/
|
26 |
public function getProtocolVersion();
|
|
|
27 |
/**
|
28 |
* Return an instance with the specified HTTP protocol version.
|
29 |
*
|
@@ -38,6 +39,7 @@ interface MessageInterface
|
|
38 |
* @return static
|
39 |
*/
|
40 |
public function withProtocolVersion($version);
|
|
|
41 |
/**
|
42 |
* Retrieves all message header values.
|
43 |
*
|
@@ -64,6 +66,7 @@ interface MessageInterface
|
|
64 |
* for that header.
|
65 |
*/
|
66 |
public function getHeaders();
|
|
|
67 |
/**
|
68 |
* Checks if a header exists by the given case-insensitive name.
|
69 |
*
|
@@ -73,6 +76,7 @@ interface MessageInterface
|
|
73 |
* no matching header name is found in the message.
|
74 |
*/
|
75 |
public function hasHeader($name);
|
|
|
76 |
/**
|
77 |
* Retrieves a message header value by the given case-insensitive name.
|
78 |
*
|
@@ -88,6 +92,7 @@ interface MessageInterface
|
|
88 |
* return an empty array.
|
89 |
*/
|
90 |
public function getHeader($name);
|
|
|
91 |
/**
|
92 |
* Retrieves a comma-separated string of the values for a single header.
|
93 |
*
|
@@ -108,6 +113,7 @@ interface MessageInterface
|
|
108 |
* the message, this method MUST return an empty string.
|
109 |
*/
|
110 |
public function getHeaderLine($name);
|
|
|
111 |
/**
|
112 |
* Return an instance with the provided value replacing the specified header.
|
113 |
*
|
@@ -124,6 +130,7 @@ interface MessageInterface
|
|
124 |
* @throws \InvalidArgumentException for invalid header names or values.
|
125 |
*/
|
126 |
public function withHeader($name, $value);
|
|
|
127 |
/**
|
128 |
* Return an instance with the specified header appended with the given value.
|
129 |
*
|
@@ -141,6 +148,7 @@ interface MessageInterface
|
|
141 |
* @throws \InvalidArgumentException for invalid header names or values.
|
142 |
*/
|
143 |
public function withAddedHeader($name, $value);
|
|
|
144 |
/**
|
145 |
* Return an instance without the specified header.
|
146 |
*
|
@@ -154,12 +162,14 @@ interface MessageInterface
|
|
154 |
* @return static
|
155 |
*/
|
156 |
public function withoutHeader($name);
|
|
|
157 |
/**
|
158 |
* Gets the body of the message.
|
159 |
*
|
160 |
* @return StreamInterface Returns the body as a stream.
|
161 |
*/
|
162 |
public function getBody();
|
|
|
163 |
/**
|
164 |
* Return an instance with the specified message body.
|
165 |
*
|
@@ -173,5 +183,5 @@ interface MessageInterface
|
|
173 |
* @return static
|
174 |
* @throws \InvalidArgumentException When the body is not valid.
|
175 |
*/
|
176 |
-
public function withBody(
|
177 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace Psr\Http\Message;
|
4 |
|
5 |
/**
|
6 |
* HTTP messages consist of requests from a client to a server and responses
|
24 |
* @return string HTTP protocol version.
|
25 |
*/
|
26 |
public function getProtocolVersion();
|
27 |
+
|
28 |
/**
|
29 |
* Return an instance with the specified HTTP protocol version.
|
30 |
*
|
39 |
* @return static
|
40 |
*/
|
41 |
public function withProtocolVersion($version);
|
42 |
+
|
43 |
/**
|
44 |
* Retrieves all message header values.
|
45 |
*
|
66 |
* for that header.
|
67 |
*/
|
68 |
public function getHeaders();
|
69 |
+
|
70 |
/**
|
71 |
* Checks if a header exists by the given case-insensitive name.
|
72 |
*
|
76 |
* no matching header name is found in the message.
|
77 |
*/
|
78 |
public function hasHeader($name);
|
79 |
+
|
80 |
/**
|
81 |
* Retrieves a message header value by the given case-insensitive name.
|
82 |
*
|
92 |
* return an empty array.
|
93 |
*/
|
94 |
public function getHeader($name);
|
95 |
+
|
96 |
/**
|
97 |
* Retrieves a comma-separated string of the values for a single header.
|
98 |
*
|
113 |
* the message, this method MUST return an empty string.
|
114 |
*/
|
115 |
public function getHeaderLine($name);
|
116 |
+
|
117 |
/**
|
118 |
* Return an instance with the provided value replacing the specified header.
|
119 |
*
|
130 |
* @throws \InvalidArgumentException for invalid header names or values.
|
131 |
*/
|
132 |
public function withHeader($name, $value);
|
133 |
+
|
134 |
/**
|
135 |
* Return an instance with the specified header appended with the given value.
|
136 |
*
|
148 |
* @throws \InvalidArgumentException for invalid header names or values.
|
149 |
*/
|
150 |
public function withAddedHeader($name, $value);
|
151 |
+
|
152 |
/**
|
153 |
* Return an instance without the specified header.
|
154 |
*
|
162 |
* @return static
|
163 |
*/
|
164 |
public function withoutHeader($name);
|
165 |
+
|
166 |
/**
|
167 |
* Gets the body of the message.
|
168 |
*
|
169 |
* @return StreamInterface Returns the body as a stream.
|
170 |
*/
|
171 |
public function getBody();
|
172 |
+
|
173 |
/**
|
174 |
* Return an instance with the specified message body.
|
175 |
*
|
183 |
* @return static
|
184 |
* @throws \InvalidArgumentException When the body is not valid.
|
185 |
*/
|
186 |
+
public function withBody(StreamInterface $body);
|
187 |
}
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace
|
4 |
|
5 |
/**
|
6 |
* Representation of an outgoing, client-side request.
|
@@ -21,7 +21,7 @@ namespace _PhpScoper5bbb1f4b001f3\Psr\Http\Message;
|
|
21 |
* be implemented such that they retain the internal state of the current
|
22 |
* message and return an instance that contains the changed state.
|
23 |
*/
|
24 |
-
interface RequestInterface extends
|
25 |
{
|
26 |
/**
|
27 |
* Retrieves the message's request target.
|
@@ -40,6 +40,7 @@ interface RequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Mes
|
|
40 |
* @return string
|
41 |
*/
|
42 |
public function getRequestTarget();
|
|
|
43 |
/**
|
44 |
* Return an instance with the specific request-target.
|
45 |
*
|
@@ -58,12 +59,14 @@ interface RequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Mes
|
|
58 |
* @return static
|
59 |
*/
|
60 |
public function withRequestTarget($requestTarget);
|
|
|
61 |
/**
|
62 |
* Retrieves the HTTP method of the request.
|
63 |
*
|
64 |
* @return string Returns the request method.
|
65 |
*/
|
66 |
public function getMethod();
|
|
|
67 |
/**
|
68 |
* Return an instance with the provided HTTP method.
|
69 |
*
|
@@ -80,6 +83,7 @@ interface RequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Mes
|
|
80 |
* @throws \InvalidArgumentException for invalid HTTP methods.
|
81 |
*/
|
82 |
public function withMethod($method);
|
|
|
83 |
/**
|
84 |
* Retrieves the URI instance.
|
85 |
*
|
@@ -90,6 +94,7 @@ interface RequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Mes
|
|
90 |
* representing the URI of the request.
|
91 |
*/
|
92 |
public function getUri();
|
|
|
93 |
/**
|
94 |
* Returns an instance with the provided URI.
|
95 |
*
|
@@ -120,5 +125,5 @@ interface RequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Mes
|
|
120 |
* @param bool $preserveHost Preserve the original state of the Host header.
|
121 |
* @return static
|
122 |
*/
|
123 |
-
public function withUri(
|
124 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace Psr\Http\Message;
|
4 |
|
5 |
/**
|
6 |
* Representation of an outgoing, client-side request.
|
21 |
* be implemented such that they retain the internal state of the current
|
22 |
* message and return an instance that contains the changed state.
|
23 |
*/
|
24 |
+
interface RequestInterface extends MessageInterface
|
25 |
{
|
26 |
/**
|
27 |
* Retrieves the message's request target.
|
40 |
* @return string
|
41 |
*/
|
42 |
public function getRequestTarget();
|
43 |
+
|
44 |
/**
|
45 |
* Return an instance with the specific request-target.
|
46 |
*
|
59 |
* @return static
|
60 |
*/
|
61 |
public function withRequestTarget($requestTarget);
|
62 |
+
|
63 |
/**
|
64 |
* Retrieves the HTTP method of the request.
|
65 |
*
|
66 |
* @return string Returns the request method.
|
67 |
*/
|
68 |
public function getMethod();
|
69 |
+
|
70 |
/**
|
71 |
* Return an instance with the provided HTTP method.
|
72 |
*
|
83 |
* @throws \InvalidArgumentException for invalid HTTP methods.
|
84 |
*/
|
85 |
public function withMethod($method);
|
86 |
+
|
87 |
/**
|
88 |
* Retrieves the URI instance.
|
89 |
*
|
94 |
* representing the URI of the request.
|
95 |
*/
|
96 |
public function getUri();
|
97 |
+
|
98 |
/**
|
99 |
* Returns an instance with the provided URI.
|
100 |
*
|
125 |
* @param bool $preserveHost Preserve the original state of the Host header.
|
126 |
* @return static
|
127 |
*/
|
128 |
+
public function withUri(UriInterface $uri, $preserveHost = false);
|
129 |
}
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace
|
4 |
|
5 |
/**
|
6 |
* Representation of an outgoing, server-side response.
|
@@ -17,7 +17,7 @@ namespace _PhpScoper5bbb1f4b001f3\Psr\Http\Message;
|
|
17 |
* be implemented such that they retain the internal state of the current
|
18 |
* message and return an instance that contains the changed state.
|
19 |
*/
|
20 |
-
interface ResponseInterface extends
|
21 |
{
|
22 |
/**
|
23 |
* Gets the response status code.
|
@@ -28,6 +28,7 @@ interface ResponseInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Me
|
|
28 |
* @return int Status code.
|
29 |
*/
|
30 |
public function getStatusCode();
|
|
|
31 |
/**
|
32 |
* Return an instance with the specified status code and, optionally, reason phrase.
|
33 |
*
|
@@ -49,6 +50,7 @@ interface ResponseInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Message\Me
|
|
49 |
* @throws \InvalidArgumentException For invalid status code arguments.
|
50 |
*/
|
51 |
public function withStatus($code, $reasonPhrase = '');
|
|
|
52 |
/**
|
53 |
* Gets the response reason phrase associated with the status code.
|
54 |
*
|
1 |
<?php
|
2 |
|
3 |
+
namespace Psr\Http\Message;
|
4 |
|
5 |
/**
|
6 |
* Representation of an outgoing, server-side response.
|
17 |
* be implemented such that they retain the internal state of the current
|
18 |
* message and return an instance that contains the changed state.
|
19 |
*/
|
20 |
+
interface ResponseInterface extends MessageInterface
|
21 |
{
|
22 |
/**
|
23 |
* Gets the response status code.
|
28 |
* @return int Status code.
|
29 |
*/
|
30 |
public function getStatusCode();
|
31 |
+
|
32 |
/**
|
33 |
* Return an instance with the specified status code and, optionally, reason phrase.
|
34 |
*
|
50 |
* @throws \InvalidArgumentException For invalid status code arguments.
|
51 |
*/
|
52 |
public function withStatus($code, $reasonPhrase = '');
|
53 |
+
|
54 |
/**
|
55 |
* Gets the response reason phrase associated with the status code.
|
56 |
*
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace
|
4 |
|
5 |
/**
|
6 |
* Representation of an incoming, server-side HTTP request.
|
@@ -40,7 +40,7 @@ namespace _PhpScoper5bbb1f4b001f3\Psr\Http\Message;
|
|
40 |
* be implemented such that they retain the internal state of the current
|
41 |
* message and return an instance that contains the changed state.
|
42 |
*/
|
43 |
-
interface ServerRequestInterface extends
|
44 |
{
|
45 |
/**
|
46 |
* Retrieve server parameters.
|
@@ -52,6 +52,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
52 |
* @return array
|
53 |
*/
|
54 |
public function getServerParams();
|
|
|
55 |
/**
|
56 |
* Retrieve cookies.
|
57 |
*
|
@@ -63,6 +64,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
63 |
* @return array
|
64 |
*/
|
65 |
public function getCookieParams();
|
|
|
66 |
/**
|
67 |
* Return an instance with the specified cookies.
|
68 |
*
|
@@ -81,6 +83,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
81 |
* @return static
|
82 |
*/
|
83 |
public function withCookieParams(array $cookies);
|
|
|
84 |
/**
|
85 |
* Retrieve query string arguments.
|
86 |
*
|
@@ -94,6 +97,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
94 |
* @return array
|
95 |
*/
|
96 |
public function getQueryParams();
|
|
|
97 |
/**
|
98 |
* Return an instance with the specified query string arguments.
|
99 |
*
|
@@ -117,6 +121,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
117 |
* @return static
|
118 |
*/
|
119 |
public function withQueryParams(array $query);
|
|
|
120 |
/**
|
121 |
* Retrieve normalized file upload data.
|
122 |
*
|
@@ -130,6 +135,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
130 |
* array MUST be returned if no data is present.
|
131 |
*/
|
132 |
public function getUploadedFiles();
|
|
|
133 |
/**
|
134 |
* Create a new instance with the specified uploaded files.
|
135 |
*
|
@@ -142,6 +148,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
142 |
* @throws \InvalidArgumentException if an invalid structure is provided.
|
143 |
*/
|
144 |
public function withUploadedFiles(array $uploadedFiles);
|
|
|
145 |
/**
|
146 |
* Retrieve any parameters provided in the request body.
|
147 |
*
|
@@ -158,6 +165,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
158 |
* These will typically be an array or object.
|
159 |
*/
|
160 |
public function getParsedBody();
|
|
|
161 |
/**
|
162 |
* Return an instance with the specified body parameters.
|
163 |
*
|
@@ -187,6 +195,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
187 |
* provided.
|
188 |
*/
|
189 |
public function withParsedBody($data);
|
|
|
190 |
/**
|
191 |
* Retrieve attributes derived from the request.
|
192 |
*
|
@@ -199,6 +208,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
199 |
* @return array Attributes derived from the request.
|
200 |
*/
|
201 |
public function getAttributes();
|
|
|
202 |
/**
|
203 |
* Retrieve a single derived request attribute.
|
204 |
*
|
@@ -215,6 +225,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
215 |
* @return mixed
|
216 |
*/
|
217 |
public function getAttribute($name, $default = null);
|
|
|
218 |
/**
|
219 |
* Return an instance with the specified derived request attribute.
|
220 |
*
|
@@ -231,6 +242,7 @@ interface ServerRequestInterface extends \_PhpScoper5bbb1f4b001f3\Psr\Http\Messa
|
|
231 |
* @return static
|
232 |
*/
|
233 |
public function withAttribute($name, $value);
|
|
|
234 |
/**
|
235 |
* Return an instance that removes the specified derived request attribute.
|
236 |
*
|
1 |
<?php
|
2 |
|
3 |
+
namespace Psr\Http\Message;
|
4 |
|
5 |
/**
|
6 |
* Representation of an incoming, server-side HTTP request.
|
40 |
* be implemented such that they retain the internal state of the current
|
41 |
* message and return an instance that contains the changed state.
|
42 |
*/
|
43 |
+
interface ServerRequestInterface extends RequestInterface
|
44 |
{
|
45 |
/**
|
46 |
* Retrieve server parameters.
|
52 |
* @return array
|
53 |
*/
|
54 |
public function getServerParams();
|
55 |
+
|
56 |
/**
|
57 |
* Retrieve cookies.
|
58 |
*
|
64 |
* @return array
|
65 |
*/
|
66 |
public function getCookieParams();
|
67 |
+
|
68 |
/**
|
69 |
* Return an instance with the specified cookies.
|
70 |
*
|
83 |
* @return static
|
84 |
*/
|
85 |
public function withCookieParams(array $cookies);
|
86 |
+
|
87 |
/**
|
88 |
* Retrieve query string arguments.
|
89 |
*
|
97 |
* @return array
|
98 |
*/
|
99 |
public function getQueryParams();
|
100 |
+
|
101 |
/**
|
102 |
* Return an instance with the specified query string arguments.
|
103 |
*
|
121 |
* @return static
|
122 |
*/
|
123 |
public function withQueryParams(array $query);
|
124 |
+
|
125 |
/**
|
126 |
* Retrieve normalized file upload data.
|
127 |
*
|
135 |
* array MUST be returned if no data is present.
|
136 |
*/
|
137 |
public function getUploadedFiles();
|
138 |
+
|
139 |
/**
|
140 |
* Create a new instance with the specified uploaded files.
|
141 |
*
|
148 |
* @throws \InvalidArgumentException if an invalid structure is provided.
|
149 |
*/
|
150 |
public function withUploadedFiles(array $uploadedFiles);
|
151 |
+
|
152 |
/**
|
153 |
* Retrieve any parameters provided in the request body.
|
154 |
*
|
165 |
* These will typically be an array or object.
|
166 |
*/
|
167 |
public function getParsedBody();
|
168 |
+
|
169 |
/**
|
170 |
* Return an instance with the specified body parameters.
|
171 |
*
|
195 |
* provided.
|
196 |
*/
|
197 |
public function withParsedBody($data);
|
198 |
+
|
199 |
/**
|
200 |
* Retrieve attributes derived from the request.
|
201 |
*
|
208 |
* @return array Attributes derived from the request.
|
209 |
*/
|
210 |
public function getAttributes();
|
211 |
+
|
212 |
/**
|
213 |
* Retrieve a single derived request attribute.
|
214 |
*
|
225 |
* @return mixed
|
226 |
*/
|
227 |
public function getAttribute($name, $default = null);
|
228 |
+
|
229 |
/**
|
230 |
* Return an instance with the specified derived request attribute.
|
231 |
*
|
242 |
* @return static
|
243 |
*/
|
244 |
public function withAttribute($name, $value);
|
245 |
+
|
246 |
/**
|
247 |
* Return an instance that removes the specified derived request attribute.
|
248 |
*
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace
|
4 |
|
5 |
/**
|
6 |
* Describes a data stream.
|
@@ -26,12 +26,14 @@ interface StreamInterface
|
|
26 |
* @return string
|
27 |
*/
|
28 |
public function __toString();
|
|
|
29 |
/**
|
30 |
* Closes the stream and any underlying resources.
|
31 |
*
|
32 |
* @return void
|
33 |
*/
|
34 |
public function close();
|
|
|
35 |
/**
|
36 |
* Separates any underlying resources from the stream.
|
37 |
*
|
@@ -40,12 +42,14 @@ interface StreamInterface
|
|
40 |
* @return resource|null Underlying PHP stream, if any
|
41 |
*/
|
42 |
public function detach();
|
|
|
43 |
/**
|
44 |
* Get the size of the stream if known.
|
45 |
*
|
46 |
* @return int|null Returns the size in bytes if known, or null if unknown.
|
47 |
*/
|
48 |
public function getSize();
|
|
|
49 |
/**
|
50 |
* Returns the current position of the file read/write pointer
|
51 |
*
|
@@ -53,18 +57,21 @@ interface StreamInterface
|
|
53 |
* @throws \RuntimeException on error.
|
54 |
*/
|
55 |
public function tell();
|
|
|
56 |
/**
|
57 |
* Returns true if the stream is at the end of the stream.
|
58 |
*
|
59 |
* @return bool
|
60 |
*/
|
61 |
public function eof();
|
|
|
62 |
/**
|
63 |
* Returns whether or not the stream is seekable.
|
64 |
*
|
65 |
* @return bool
|
66 |
*/
|
67 |
public function isSeekable();
|
|
|
68 |
/**
|
69 |
* Seek to a position in the stream.
|
70 |
*
|
@@ -77,7 +84,8 @@ interface StreamInterface
|
|
77 |
* SEEK_END: Set position to end-of-stream plus offset.
|
78 |
* @throws \RuntimeException on failure.
|
79 |
*/
|
80 |
-
public function seek($offset, $whence =
|
|
|
81 |
/**
|
82 |
* Seek to the beginning of the stream.
|
83 |
*
|
@@ -89,12 +97,14 @@ interface StreamInterface
|
|
89 |
* @throws \RuntimeException on failure.
|
90 |
*/
|
91 |
public function rewind();
|
|
|
92 |
/**
|
93 |
* Returns whether or not the stream is writable.
|
94 |
*
|
95 |
* @return bool
|
96 |
*/
|
97 |
public function isWritable();
|
|
|
98 |
/**
|
99 |
* Write data to the stream.
|
100 |
*
|
@@ -103,12 +113,14 @@ interface StreamInterface
|
|
103 |
* @throws \RuntimeException on failure.
|
104 |
*/
|
105 |
public function write($string);
|
|
|
106 |
/**
|
107 |
* Returns whether or not the stream is readable.
|
108 |
*
|
109 |
* @return bool
|
110 |
*/
|
111 |
public function isReadable();
|
|
|
112 |
/**
|
113 |
* Read data from the stream.
|
114 |
*
|
@@ -120,6 +132,7 @@ interface StreamInterface
|
|
120 |
* @throws \RuntimeException if an error occurs.
|
121 |
*/
|
122 |
public function read($length);
|
|
|
123 |
/**
|
124 |
* Returns the remaining contents in a string
|
125 |
*
|
@@ -128,6 +141,7 @@ interface StreamInterface
|
|
128 |
* reading.
|
129 |
*/
|
130 |
public function getContents();
|
|
|
131 |
/**
|
132 |
* Get stream metadata as an associative array or retrieve a specific key.
|
133 |
*
|
1 |
<?php
|
2 |
|
3 |
+
namespace Psr\Http\Message;
|
4 |
|
5 |
/**
|
6 |
* Describes a data stream.
|
26 |
* @return string
|
27 |
*/
|
28 |
public function __toString();
|
29 |
+
|
30 |
/**
|
31 |
* Closes the stream and any underlying resources.
|
32 |
*
|
33 |
* @return void
|
34 |
*/
|
35 |
public function close();
|
36 |
+
|
37 |
/**
|
38 |
* Separates any underlying resources from the stream.
|
39 |
*
|
42 |
* @return resource|null Underlying PHP stream, if any
|
43 |
*/
|
44 |
public function detach();
|
45 |
+
|
46 |
/**
|
47 |
* Get the size of the stream if known.
|
48 |
*
|
49 |
* @return int|null Returns the size in bytes if known, or null if unknown.
|
50 |
*/
|
51 |
public function getSize();
|
52 |
+
|
53 |
/**
|
54 |
* Returns the current position of the file read/write pointer
|
55 |
*
|
57 |
* @throws \RuntimeException on error.
|
58 |
*/
|
59 |
public function tell();
|
60 |
+
|
61 |
/**
|
62 |
* Returns true if the stream is at the end of the stream.
|
63 |
*
|
64 |
* @return bool
|
65 |
*/
|
66 |
public function eof();
|
67 |
+
|
68 |
/**
|
69 |
* Returns whether or not the stream is seekable.
|
70 |
*
|
71 |
* @return bool
|
72 |
*/
|
73 |
public function isSeekable();
|
74 |
+
|
75 |
/**
|
76 |
* Seek to a position in the stream.
|
77 |
*
|
84 |
* SEEK_END: Set position to end-of-stream plus offset.
|
85 |
* @throws \RuntimeException on failure.
|
86 |
*/
|
87 |
+
public function seek($offset, $whence = SEEK_SET);
|
88 |
+
|
89 |
/**
|
90 |
* Seek to the beginning of the stream.
|
91 |
*
|
97 |
* @throws \RuntimeException on failure.
|
98 |
*/
|
99 |
public function rewind();
|
100 |
+
|
101 |
/**
|
102 |
* Returns whether or not the stream is writable.
|
103 |
*
|
104 |
* @return bool
|
105 |
*/
|
106 |
public function isWritable();
|
107 |
+
|
108 |
/**
|
109 |
* Write data to the stream.
|
110 |
*
|
113 |
* @throws \RuntimeException on failure.
|
114 |
*/
|
115 |
public function write($string);
|
116 |
+
|
117 |
/**
|
118 |
* Returns whether or not the stream is readable.
|
119 |
*
|
120 |
* @return bool
|
121 |
*/
|
122 |
public function isReadable();
|
123 |
+
|
124 |
/**
|
125 |
* Read data from the stream.
|
126 |
*
|
132 |
* @throws \RuntimeException if an error occurs.
|
133 |
*/
|
134 |
public function read($length);
|
135 |
+
|
136 |
/**
|
137 |
* Returns the remaining contents in a string
|
138 |
*
|
141 |
* reading.
|
142 |
*/
|
143 |
public function getContents();
|
144 |
+
|
145 |
/**
|
146 |
* Get stream metadata as an associative array or retrieve a specific key.
|
147 |
*
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace
|
4 |
|
5 |
/**
|
6 |
* Value object representing a file uploaded through an HTTP request.
|
@@ -29,6 +29,7 @@ interface UploadedFileInterface
|
|
29 |
* created.
|
30 |
*/
|
31 |
public function getStream();
|
|
|
32 |
/**
|
33 |
* Move the uploaded file to a new location.
|
34 |
*
|
@@ -62,6 +63,7 @@ interface UploadedFileInterface
|
|
62 |
* the second or subsequent call to the method.
|
63 |
*/
|
64 |
public function moveTo($targetPath);
|
|
|
65 |
/**
|
66 |
* Retrieve the file size.
|
67 |
*
|
@@ -72,6 +74,7 @@ interface UploadedFileInterface
|
|
72 |
* @return int|null The file size in bytes or null if unknown.
|
73 |
*/
|
74 |
public function getSize();
|
|
|
75 |
/**
|
76 |
* Retrieve the error associated with the uploaded file.
|
77 |
*
|
@@ -87,6 +90,7 @@ interface UploadedFileInterface
|
|
87 |
* @return int One of PHP's UPLOAD_ERR_XXX constants.
|
88 |
*/
|
89 |
public function getError();
|
|
|
90 |
/**
|
91 |
* Retrieve the filename sent by the client.
|
92 |
*
|
@@ -101,6 +105,7 @@ interface UploadedFileInterface
|
|
101 |
* was provided.
|
102 |
*/
|
103 |
public function getClientFilename();
|
|
|
104 |
/**
|
105 |
* Retrieve the media type sent by the client.
|
106 |
*
|
1 |
<?php
|
2 |
|
3 |
+
namespace Psr\Http\Message;
|
4 |
|
5 |
/**
|
6 |
* Value object representing a file uploaded through an HTTP request.
|
29 |
* created.
|
30 |
*/
|
31 |
public function getStream();
|
32 |
+
|
33 |
/**
|
34 |
* Move the uploaded file to a new location.
|
35 |
*
|
63 |
* the second or subsequent call to the method.
|
64 |
*/
|
65 |
public function moveTo($targetPath);
|
66 |
+
|
67 |
/**
|
68 |
* Retrieve the file size.
|
69 |
*
|
74 |
* @return int|null The file size in bytes or null if unknown.
|
75 |
*/
|
76 |
public function getSize();
|
77 |
+
|
78 |
/**
|
79 |
* Retrieve the error associated with the uploaded file.
|
80 |
*
|
90 |
* @return int One of PHP's UPLOAD_ERR_XXX constants.
|
91 |
*/
|
92 |
public function getError();
|
93 |
+
|
94 |
/**
|
95 |
* Retrieve the filename sent by the client.
|
96 |
*
|
105 |
* was provided.
|
106 |
*/
|
107 |
public function getClientFilename();
|
108 |
+
|
109 |
/**
|
110 |
* Retrieve the media type sent by the client.
|
111 |
*
|
@@ -1,6 +1,5 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace _PhpScoper5bbb1f4b001f3\Psr\Http\Message;
|
4 |
|
5 |
/**
|
6 |
* Value object representing a URI.
|
@@ -39,6 +38,7 @@ interface UriInterface
|
|
39 |
* @return string The URI scheme.
|
40 |
*/
|
41 |
public function getScheme();
|
|
|
42 |
/**
|
43 |
* Retrieve the authority component of the URI.
|
44 |
*
|
@@ -58,6 +58,7 @@ interface UriInterface
|
|
58 |
* @return string The URI authority, in "[user-info@]host[:port]" format.
|
59 |
*/
|
60 |
public function getAuthority();
|
|
|
61 |
/**
|
62 |
* Retrieve the user information component of the URI.
|
63 |
*
|
@@ -74,6 +75,7 @@ interface UriInterface
|
|
74 |
* @return string The URI user information, in "username[:password]" format.
|
75 |
*/
|
76 |
public function getUserInfo();
|
|
|
77 |
/**
|
78 |
* Retrieve the host component of the URI.
|
79 |
*
|
@@ -86,6 +88,7 @@ interface UriInterface
|
|
86 |
* @return string The URI host.
|
87 |
*/
|
88 |
public function getHost();
|
|
|
89 |
/**
|
90 |
* Retrieve the port component of the URI.
|
91 |
*
|
@@ -102,6 +105,7 @@ interface UriInterface
|
|
102 |
* @return null|int The URI port.
|
103 |
*/
|
104 |
public function getPort();
|
|
|
105 |
/**
|
106 |
* Retrieve the path component of the URI.
|
107 |
*
|
@@ -128,6 +132,7 @@ interface UriInterface
|
|
128 |
* @return string The URI path.
|
129 |
*/
|
130 |
public function getPath();
|
|
|
131 |
/**
|
132 |
* Retrieve the query string of the URI.
|
133 |
*
|
@@ -149,6 +154,7 @@ interface UriInterface
|
|
149 |
* @return string The URI query string.
|
150 |
*/
|
151 |
public function getQuery();
|
|
|
152 |
/**
|
153 |
* Retrieve the fragment component of the URI.
|
154 |
*
|
@@ -166,6 +172,7 @@ interface UriInterface
|
|
166 |
* @return string The URI fragment.
|
167 |
*/
|
168 |
public function getFragment();
|
|
|
169 |
/**
|
170 |
* Return an instance with the specified scheme.
|
171 |
*
|
@@ -182,6 +189,7 @@ interface UriInterface
|
|
182 |
* @throws \InvalidArgumentException for invalid or unsupported schemes.
|
183 |
*/
|
184 |
public function withScheme($scheme);
|
|
|
185 |
/**
|
186 |
* Return an instance with the specified user information.
|
187 |
*
|
@@ -197,6 +205,7 @@ interface UriInterface
|
|
197 |
* @return static A new instance with the specified user information.
|
198 |
*/
|
199 |
public function withUserInfo($user, $password = null);
|
|
|
200 |
/**
|
201 |
* Return an instance with the specified host.
|
202 |
*
|
@@ -210,6 +219,7 @@ interface UriInterface
|
|
210 |
* @throws \InvalidArgumentException for invalid hostnames.
|
211 |
*/
|
212 |
public function withHost($host);
|
|
|
213 |
/**
|
214 |
* Return an instance with the specified port.
|
215 |
*
|
@@ -228,6 +238,7 @@ interface UriInterface
|
|
228 |
* @throws \InvalidArgumentException for invalid ports.
|
229 |
*/
|
230 |
public function withPort($port);
|
|
|
231 |
/**
|
232 |
* Return an instance with the specified path.
|
233 |
*
|
@@ -251,6 +262,7 @@ interface UriInterface
|
|
251 |
* @throws \InvalidArgumentException for invalid paths.
|
252 |
*/
|
253 |
public function withPath($path);
|
|
|
254 |
/**
|
255 |
* Return an instance with the specified query string.
|
256 |
*
|
@@ -267,6 +279,7 @@ interface UriInterface
|
|
267 |
* @throws \InvalidArgumentException for invalid query strings.
|
268 |
*/
|
269 |
public function withQuery($query);
|
|
|
270 |
/**
|
271 |
* Return an instance with the specified URI fragment.
|
272 |
*
|
@@ -282,6 +295,7 @@ interface UriInterface
|
|
282 |
* @return static A new instance with the specified fragment.
|
283 |
*/
|
284 |
public function withFragment($fragment);
|
|
|
285 |
/**
|
286 |
* Return the string representation as a URI reference.
|
287 |
*
|
1 |
<?php
|
2 |
+
namespace Psr\Http\Message;
|
|
|
3 |
|
4 |
/**
|
5 |
* Value object representing a URI.
|
38 |
* @return string The URI scheme.
|
39 |
*/
|
40 |
public function getScheme();
|
41 |
+
|
42 |
/**
|
43 |
* Retrieve the authority component of the URI.
|
44 |
*
|
58 |
* @return string The URI authority, in "[user-info@]host[:port]" format.
|
59 |
*/
|
60 |
public function getAuthority();
|
61 |
+
|
62 |
/**
|
63 |
* Retrieve the user information component of the URI.
|
64 |
*
|
75 |
* @return string The URI user information, in "username[:password]" format.
|
76 |
*/
|
77 |
public function getUserInfo();
|
78 |
+
|
79 |
/**
|
80 |
* Retrieve the host component of the URI.
|
81 |
*
|
88 |
* @return string The URI host.
|
89 |
*/
|
90 |
public function getHost();
|
91 |
+
|
92 |
/**
|
93 |
* Retrieve the port component of the URI.
|
94 |
*
|
105 |
* @return null|int The URI port.
|
106 |
*/
|
107 |
public function getPort();
|
108 |
+
|
109 |
/**
|
110 |
* Retrieve the path component of the URI.
|
111 |
*
|
132 |
* @return string The URI path.
|
133 |
*/
|
134 |
public function getPath();
|
135 |
+
|
136 |
/**
|
137 |
* Retrieve the query string of the URI.
|
138 |
*
|
154 |
* @return string The URI query string.
|
155 |
*/
|
156 |
public function getQuery();
|
157 |
+
|
158 |
/**
|
159 |
* Retrieve the fragment component of the URI.
|
160 |
*
|
172 |
* @return string The URI fragment.
|
173 |
*/
|
174 |
public function getFragment();
|
175 |
+
|
176 |
/**
|
177 |
* Return an instance with the specified scheme.
|
178 |
*
|
189 |
* @throws \InvalidArgumentException for invalid or unsupported schemes.
|
190 |
*/
|
191 |
public function withScheme($scheme);
|
192 |
+
|
193 |
/**
|
194 |
* Return an instance with the specified user information.
|
195 |
*
|
205 |
* @return static A new instance with the specified user information.
|
206 |
*/
|
207 |
public function withUserInfo($user, $password = null);
|
208 |
+
|
209 |
/**
|
210 |
* Return an instance with the specified host.
|
211 |
*
|
219 |
* @throws \InvalidArgumentException for invalid hostnames.
|
220 |
*/
|
221 |
public function withHost($host);
|
222 |
+
|
223 |
/**
|
224 |
* Return an instance with the specified port.
|
225 |
*
|
238 |
* @throws \InvalidArgumentException for invalid ports.
|
239 |
*/
|
240 |
public function withPort($port);
|
241 |
+
|
242 |
/**
|
243 |
* Return an instance with the specified path.
|
244 |
*
|
262 |
* @throws \InvalidArgumentException for invalid paths.
|
263 |
*/
|
264 |
public function withPath($path);
|
265 |
+
|
266 |
/**
|
267 |
* Return an instance with the specified query string.
|
268 |
*
|
279 |
* @throws \InvalidArgumentException for invalid query strings.
|
280 |
*/
|
281 |
public function withQuery($query);
|
282 |
+
|
283 |
/**
|
284 |
* Return an instance with the specified URI fragment.
|
285 |
*
|
295 |
* @return static A new instance with the specified fragment.
|
296 |
*/
|
297 |
public function withFragment($fragment);
|
298 |
+
|
299 |
/**
|
300 |
* Return the string representation as a URI reference.
|
301 |
*
|
@@ -7,7 +7,7 @@ class Mollie_WC_Plugin
|
|
7 |
{
|
8 |
const PLUGIN_ID = 'mollie-payments-for-woocommerce';
|
9 |
const PLUGIN_TITLE = 'Mollie Payments for WooCommerce';
|
10 |
-
const PLUGIN_VERSION = '5.0.
|
11 |
|
12 |
const DB_VERSION = '1.0';
|
13 |
const DB_VERSION_PARAM_NAME = 'mollie-db-version';
|
7 |
{
|
8 |
const PLUGIN_ID = 'mollie-payments-for-woocommerce';
|
9 |
const PLUGIN_TITLE = 'Mollie Payments for WooCommerce';
|
10 |
+
const PLUGIN_VERSION = '5.0.1';
|
11 |
|
12 |
const DB_VERSION = '1.0';
|
13 |
const DB_VERSION_PARAM_NAME = 'mollie-db-version';
|
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Mollie Payments for WooCommerce
|
4 |
* Plugin URI: https://www.mollie.com
|
5 |
* Description: Accept payments in WooCommerce with the official Mollie plugin
|
6 |
-
* Version: 5.0.
|
7 |
* Author: Mollie
|
8 |
* Author URI: https://www.mollie.com
|
9 |
* Requires at least: 3.8
|
3 |
* Plugin Name: Mollie Payments for WooCommerce
|
4 |
* Plugin URI: https://www.mollie.com
|
5 |
* Description: Accept payments in WooCommerce with the official Mollie plugin
|
6 |
+
* Version: 5.0.1
|
7 |
* Author: Mollie
|
8 |
* Author URI: https://www.mollie.com
|
9 |
* Requires at least: 3.8
|
@@ -3,7 +3,7 @@ Contributors: daanvm, davdebcom, l.vangunst, ndijkstra, robin-mollie
|
|
3 |
Tags: mollie, payments, woocommerce, payment gateway, e-commerce, credit card, ideal, sofort, bancontact, bitcoin, direct debit, subscriptions
|
4 |
Requires at least: 3.8
|
5 |
Tested up to: 4.9
|
6 |
-
Stable tag: 5.0.
|
7 |
Requires PHP: 5.6
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -55,8 +55,8 @@ International payment methods:
|
|
55 |
|
56 |
Pay after delivery payment methods:
|
57 |
|
58 |
-
* Klarna Pay later
|
59 |
-
* Klarna Slice it
|
60 |
|
61 |
Please go to the [signup page](https://www.mollie.com/signup) to create a new Mollie account and start receiving payments in a couple of minutes. Contact info@mollie.com if you have any questions or comments about this plugin.
|
62 |
|
@@ -181,7 +181,7 @@ Automatic updates should work like a charm; as always though, ensure you backup
|
|
181 |
|
182 |
== Changelog ==
|
183 |
|
184 |
-
= 5.0.
|
185 |
|
186 |
IMPORTANT
|
187 |
This version requires PHP 5.6 or higher. If you are using an older PHP version, please read this article: [PHP & Mollie API v2](https://github.com/mollie/WooCommerce/wiki/PHP-&-Mollie-API-v2).
|
@@ -191,6 +191,8 @@ This version requires PHP 5.6 or higher. If you are using an older PHP version,
|
|
191 |
* New - Tested with and updated for WooCommerce 3.5 beta compatibility
|
192 |
* New - EPS, GiroPay: implemented support for SEPA first payments (recurring payments)
|
193 |
|
|
|
|
|
194 |
* Fix - WooCommerce emails: make sure "Payment completed by..." message is only shown once per email
|
195 |
* Fix - WooCommerce Subscriptions: add support for "Accept Manual Renewals". This enables Bank Transfer and PayPal in checkout for subscription products.
|
196 |
* Fix - Mollie payment gateways weren't always shows when cart was empty.
|
3 |
Tags: mollie, payments, woocommerce, payment gateway, e-commerce, credit card, ideal, sofort, bancontact, bitcoin, direct debit, subscriptions
|
4 |
Requires at least: 3.8
|
5 |
Tested up to: 4.9
|
6 |
+
Stable tag: 5.0.1
|
7 |
Requires PHP: 5.6
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
55 |
|
56 |
Pay after delivery payment methods:
|
57 |
|
58 |
+
* Klarna Pay later (Netherlands, Germany, Austria, Finland)
|
59 |
+
* Klarna Slice it (Germany, Austria, Finland)
|
60 |
|
61 |
Please go to the [signup page](https://www.mollie.com/signup) to create a new Mollie account and start receiving payments in a couple of minutes. Contact info@mollie.com if you have any questions or comments about this plugin.
|
62 |
|
181 |
|
182 |
== Changelog ==
|
183 |
|
184 |
+
= 5.0.1 - 11-10-2018 =
|
185 |
|
186 |
IMPORTANT
|
187 |
This version requires PHP 5.6 or higher. If you are using an older PHP version, please read this article: [PHP & Mollie API v2](https://github.com/mollie/WooCommerce/wiki/PHP-&-Mollie-API-v2).
|
191 |
* New - Tested with and updated for WooCommerce 3.5 beta compatibility
|
192 |
* New - EPS, GiroPay: implemented support for SEPA first payments (recurring payments)
|
193 |
|
194 |
+
* Fix - Fixed issue with Guzzle and PhpScoper
|
195 |
+
|
196 |
* Fix - WooCommerce emails: make sure "Payment completed by..." message is only shown once per email
|
197 |
* Fix - WooCommerce Subscriptions: add support for "Accept Manual Renewals". This enables Bank Transfer and PayPal in checkout for subscription products.
|
198 |
* Fix - Mollie payment gateways weren't always shows when cart was empty.
|