Skip to content

Commit b4d847e

Browse files
committed
Merge branch 'v3' into feat/assert-sent-typehint
2 parents c5a023e + d5bb5d6 commit b4d847e

29 files changed

+692
-296
lines changed

.github/workflows/phpstan.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Setup PHP
2525
uses: shivammathur/setup-php@v2
2626
with:
27-
php-version: '8.1'
27+
php-version: '8.3'
2828
coverage: none
2929

3030
- name: Install composer dependencies

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
fail-fast: true
2525
matrix:
2626
os: [ ubuntu-latest, windows-latest ]
27-
php: [ 8.1, 8.2, 8.3 ]
27+
php: [ 8.1, 8.2, 8.3, 8.4 ]
2828
stability: [ prefer-lowest, prefer-stable ]
2929

3030
name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023 Sam Carré
3+
Copyright (c) 2024 Sam Carré
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"friendsofphp/php-cs-fixer": "^3.5",
3232
"illuminate/collections": "^9.39 || ^10.0",
3333
"league/flysystem": "^3.0",
34-
"pestphp/pest": "^2.6",
34+
"pestphp/pest": "^2.10",
3535
"phpstan/phpstan": "^1.11.4",
3636
"saloonphp/xml-wrangler": "^1.1",
3737
"spatie/ray": "^1.33",

phpstan.baseline.neon

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@ parameters:
2020
count: 1
2121
path: src/Http/Faking/MockClient.php
2222

23-
-
24-
message: "#^Result of \\&\\& is always false.$#"
25-
count: 1
26-
path: src/Data/MultipartValue.php
27-
2823
-
2924
message: "#^Parameter \\#1 \\$response of method Saloon\\\\Http\\\\PendingRequest\\:\\:executeResponsePipeline\\(\\) expects Saloon\\\\Http\\\\Response\\, GuzzleHttp\\\\Promise\\\\PromiseInterface\\|Saloon\\\\Http\\\\Response given.$#"
3025
count: 1

src/Exceptions/InvalidResponseClassException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class InvalidResponseClassException extends SaloonException
1111
/**
1212
* Constructor
1313
*/
14-
public function __construct(string $message = null)
14+
public function __construct(?string $message = null)
1515
{
1616
parent::__construct($message ?? sprintf('The provided response must exist and implement the %s contract.', Response::class));
1717
}

src/Exceptions/InvalidStateException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class InvalidStateException extends SaloonException
1010
{
11-
public function __construct(string $message = null, int $code = 0, ?Throwable $previous = null)
11+
public function __construct(?string $message = null, int $code = 0, ?Throwable $previous = null)
1212
{
1313
parent::__construct($message ?? 'Invalid state.', $code, $previous);
1414
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Saloon\Exceptions\Request\Statuses;
6+
7+
use Saloon\Exceptions\Request\ClientException;
8+
9+
class PaymentRequiredException extends ClientException
10+
{
11+
//
12+
}

src/Helpers/FixtureHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static function recursivelyReplaceAttributes(array $source, array $rules,
2424

2525
array_walk_recursive($source, static function (&$value, $key) use ($rules, $caseSensitiveKeys) {
2626
if ($caseSensitiveKeys === false) {
27-
$key = mb_strtolower($key);
27+
$key = mb_strtolower((string) $key);
2828
}
2929

3030
if (! array_key_exists($key, $rules)) {

src/Helpers/MiddlewarePipeline.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Saloon\Enums\PipeOrder;
99
use Saloon\Http\PendingRequest;
1010
use Saloon\Contracts\FakeResponse;
11+
use Saloon\Exceptions\Request\FatalRequestException;
1112

1213
class MiddlewarePipeline
1314
{
@@ -21,13 +22,19 @@ class MiddlewarePipeline
2122
*/
2223
protected Pipeline $responsePipeline;
2324

25+
/**
26+
* Fatal Pipeline
27+
*/
28+
protected Pipeline $fatalPipeline;
29+
2430
/**
2531
* Constructor
2632
*/
2733
public function __construct()
2834
{
2935
$this->requestPipeline = new Pipeline;
3036
$this->responsePipeline = new Pipeline;
37+
$this->fatalPipeline = new Pipeline;
3138
}
3239

3340
/**
@@ -92,6 +99,33 @@ public function onResponse(callable $callable, ?string $name = null, ?PipeOrder
9299
return $this;
93100
}
94101

102+
/**
103+
* Add a middleware to run on fatal errors
104+
*
105+
* @param callable(FatalRequestException): (void) $callable
106+
* @return $this
107+
*/
108+
public function onFatalException(callable $callable, ?string $name = null, ?PipeOrder $order = null): static
109+
{
110+
/**
111+
* For some reason, PHP is not destructing non-static Closures, or 'things' using non-static Closures, correctly, keeping unused objects intact.
112+
* Using a *static* Closure, or re-binding it to an empty, anonymous class/object is a workaround for the issue.
113+
* If we don't, things using the MiddlewarePipeline, in turn, won't destruct.
114+
* Concretely speaking, for Saloon, this means that the Connector will *not* get destructed, and thereby also not the underlying client.
115+
* Which in turn leaves open file handles until the process terminates.
116+
*
117+
* Do note that this is entirely about our *wrapping* Closure below.
118+
* The provided callable doesn't affect the MiddlewarePipeline.
119+
*/
120+
$this->fatalPipeline->pipe(static function (FatalRequestException $throwable) use ($callable): FatalRequestException {
121+
$callable($throwable);
122+
123+
return $throwable;
124+
}, $name, $order);
125+
126+
return $this;
127+
}
128+
95129
/**
96130
* Process the request pipeline.
97131
*/
@@ -108,6 +142,15 @@ public function executeResponsePipeline(Response $response): Response
108142
return $this->responsePipeline->process($response);
109143
}
110144

145+
/**
146+
* Process the fatal pipeline.
147+
* @throws \Saloon\Exceptions\Request\FatalRequestException
148+
*/
149+
public function executeFatalPipeline(FatalRequestException $throwable): void
150+
{
151+
$this->fatalPipeline->process($throwable);
152+
}
153+
111154
/**
112155
* Merge in another middleware pipeline.
113156
*
@@ -125,8 +168,14 @@ public function merge(MiddlewarePipeline $middlewarePipeline): static
125168
$middlewarePipeline->getResponsePipeline()->getPipes()
126169
);
127170

171+
$fatalPipes = array_merge(
172+
$this->getFatalPipeline()->getPipes(),
173+
$middlewarePipeline->getFatalPipeline()->getPipes()
174+
);
175+
128176
$this->requestPipeline->setPipes($requestPipes);
129177
$this->responsePipeline->setPipes($responsePipes);
178+
$this->fatalPipeline->setPipes($fatalPipes);
130179

131180
return $this;
132181
}
@@ -146,4 +195,12 @@ public function getResponsePipeline(): Pipeline
146195
{
147196
return $this->responsePipeline;
148197
}
198+
199+
/**
200+
* Get the fatal pipeline
201+
*/
202+
public function getFatalPipeline(): Pipeline
203+
{
204+
return $this->fatalPipeline;
205+
}
149206
}

0 commit comments

Comments
 (0)