Skip to content

Commit bc3909e

Browse files
authored
Merge pull request #144 from Sammyjo20/feature/v2-better-merging-pipeline
Feature | V2 Better Merging Pipeline
2 parents e345455 + c004f66 commit bc3909e

File tree

11 files changed

+178
-68
lines changed

11 files changed

+178
-68
lines changed

src/Contracts/Pipeline.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Saloon\Contracts;
6+
7+
interface Pipeline
8+
{
9+
/**
10+
* Add a pipe to the pipeline
11+
*
12+
* @param callable $callable
13+
* @param bool $prepend
14+
* @param string|null $name
15+
* @return \Saloon\Helpers\Pipeline
16+
* @throws \Saloon\Exceptions\DuplicatePipeNameException
17+
*/
18+
public function pipe(callable $callable, bool $prepend = false, ?string $name = null): static;
19+
20+
/**
21+
* Process the pipeline.
22+
*
23+
* @param mixed $payload
24+
* @return mixed
25+
*/
26+
public function process(mixed $payload): mixed;
27+
28+
/**
29+
* Set the pipes on the pipeline.
30+
*
31+
* @param array<\Saloon\Data\Pipe> $pipes
32+
* @return $this
33+
*/
34+
public function setPipes(array $pipes): static;
35+
36+
/**
37+
* Get all the pipes in the pipeline
38+
*
39+
* @return array<\Saloon\Data\Pipe>
40+
*/
41+
public function getPipes(): array;
42+
}

src/Contracts/Response.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -256,13 +256,6 @@ public function getSimulatedResponsePayload(): ?SimulatedResponsePayload;
256256
*/
257257
public function getSenderException(): ?Throwable;
258258

259-
/**
260-
* Get the raw response
261-
*
262-
* @return mixed
263-
*/
264-
public function getRawResponse(): mixed;
265-
266259
/**
267260
* Get the body of the response.
268261
*

src/Data/Pipe.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Saloon\Data;
6+
7+
class Pipe
8+
{
9+
/**
10+
* Constructor
11+
*
12+
* @param callable $callable
13+
* @param string|null $name
14+
*/
15+
public function __construct(
16+
readonly public mixed $callable,
17+
readonly public ?string $name = null,
18+
) {
19+
//
20+
}
21+
}

src/Helpers/MiddlewarePipeline.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,32 @@
77
use Saloon\Contracts\Response;
88
use Saloon\Contracts\PendingRequest;
99
use Saloon\Contracts\SimulatedResponsePayload;
10+
use Saloon\Contracts\Pipeline as PipelineContract;
1011
use Saloon\Contracts\MiddlewarePipeline as MiddlewarePipelineContract;
1112

1213
class MiddlewarePipeline implements MiddlewarePipelineContract
1314
{
1415
/**
1516
* Request Pipeline
1617
*
17-
* @var Pipeline
18+
* @var \Saloon\Contracts\Pipeline
1819
*/
19-
protected Pipeline $requestPipeline;
20+
protected PipelineContract $requestPipeline;
2021

2122
/**
2223
* Response Pipeline
2324
*
24-
* @var Pipeline
25+
* @var \Saloon\Contracts\Pipeline
2526
*/
26-
protected Pipeline $responsePipeline;
27+
protected PipelineContract $responsePipeline;
2728

2829
/**
2930
* Constructor
3031
*/
3132
public function __construct()
3233
{
33-
$this->requestPipeline = new Pipeline();
34-
$this->responsePipeline = new Pipeline();
34+
$this->requestPipeline = new Pipeline;
35+
$this->responsePipeline = new Pipeline;
3536
}
3637

3738
/**

src/Helpers/MockConfig.php

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

55
namespace Saloon\Helpers;
66

7-
class MockConfig
7+
final class MockConfig
88
{
99
/**
1010
* Default fixture path

src/Helpers/Pipeline.php

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,40 @@
44

55
namespace Saloon\Helpers;
66

7+
use Saloon\Data\Pipe;
78
use Saloon\Exceptions\DuplicatePipeNameException;
9+
use Saloon\Contracts\Pipeline as PipelineContract;
810

9-
class Pipeline
11+
class Pipeline implements PipelineContract
1012
{
1113
/**
1214
* The pipes in the pipeline.
1315
*
14-
* @var array
16+
* @var array<\Saloon\Data\Pipe>
1517
*/
1618
protected array $pipes = [];
1719

1820
/**
19-
* The named pipes that have been added.
21+
* Add a pipe to the pipeline
2022
*
21-
* @var array
22-
*/
23-
protected array $namedPipes = [];
24-
25-
/**
26-
* Add a pipe to the pipeline.
27-
*
28-
* @param callable $pipe
23+
* @param callable $callable
2924
* @param bool $prepend
3025
* @param string|null $name
3126
* @return $this
3227
* @throws \Saloon\Exceptions\DuplicatePipeNameException
3328
*/
34-
public function pipe(callable $pipe, bool $prepend = false, ?string $name = null): static
29+
public function pipe(callable $callable, bool $prepend = false, ?string $name = null): static
3530
{
36-
if ($prepend === true) {
37-
array_unshift($this->pipes, $pipe);
38-
} else {
39-
$this->pipes[] = $pipe;
40-
}
31+
$pipe = new Pipe($callable, $name);
4132

42-
if (! is_null($name)) {
43-
in_array($name, $this->namedPipes, true) ? throw new DuplicatePipeNameException($name) : $this->namedPipes[] = $name;
33+
if (is_string($name) && $this->pipeExists($name)) {
34+
throw new DuplicatePipeNameException($name);
4435
}
4536

37+
$prepend === true
38+
? array_unshift($this->pipes, $pipe)
39+
: $this->pipes[] = $pipe;
40+
4641
return $this;
4742
}
4843

@@ -55,7 +50,7 @@ public function pipe(callable $pipe, bool $prepend = false, ?string $name = null
5550
public function process(mixed $payload): mixed
5651
{
5752
foreach ($this->pipes as $pipe) {
58-
$payload = $pipe($payload);
53+
$payload = call_user_func($pipe->callable, $payload);
5954
}
6055

6156
return $payload;
@@ -66,21 +61,46 @@ public function process(mixed $payload): mixed
6661
*
6762
* @param array $pipes
6863
* @return $this
64+
* @throws \Saloon\Exceptions\DuplicatePipeNameException
6965
*/
7066
public function setPipes(array $pipes): static
7167
{
72-
$this->pipes = $pipes;
68+
$this->pipes = [];
69+
70+
// Loop through each of the pipes and manually add each pipe
71+
// so we can check if the name already exists.
72+
73+
foreach ($pipes as $pipe) {
74+
$this->pipe($pipe->callable, false, $pipe->name);
75+
}
7376

7477
return $this;
7578
}
7679

7780
/**
7881
* Get all the pipes in the pipeline
7982
*
80-
* @return array
83+
* @return array<\Saloon\Data\Pipe>
8184
*/
8285
public function getPipes(): array
8386
{
8487
return $this->pipes;
8588
}
89+
90+
/**
91+
* Check if a given pipe exists for a name
92+
*
93+
* @param string $name
94+
* @return bool
95+
*/
96+
protected function pipeExists(string $name): bool
97+
{
98+
foreach ($this->pipes as $pipe) {
99+
if ($pipe->name === $name) {
100+
return true;
101+
}
102+
}
103+
104+
return false;
105+
}
86106
}

src/Helpers/Storage.php

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ class Storage
2121
* Constructor
2222
*
2323
* @param string $baseDirectory
24-
* @throws DirectoryNotFoundException
24+
* @param bool $createMissingBaseDirectory
25+
* @throws \Saloon\Exceptions\DirectoryNotFoundException
26+
* @throws \Saloon\Exceptions\UnableToCreateDirectoryException
2527
*/
26-
public function __construct(string $baseDirectory)
28+
public function __construct(string $baseDirectory, bool $createMissingBaseDirectory = false)
2729
{
2830
if (! is_dir($baseDirectory)) {
29-
throw new DirectoryNotFoundException($baseDirectory);
31+
$createMissingBaseDirectory ? $this->createDirectory($baseDirectory) : throw new DirectoryNotFoundException($baseDirectory);
3032
}
3133

3234
$this->baseDirectory = $baseDirectory;
@@ -104,11 +106,7 @@ public function put(string $path, string $contents): static
104106
$directoryWithoutFilename = implode(DIRECTORY_SEPARATOR, explode(DIRECTORY_SEPARATOR, $fullPath, -1));
105107

106108
if (empty($directoryWithoutFilename) === false && is_dir($directoryWithoutFilename) === false) {
107-
$createdDirectory = mkdir($directoryWithoutFilename, 0777, true);
108-
109-
if ($createdDirectory === false && is_dir($directoryWithoutFilename) === false) {
110-
throw new UnableToCreateDirectoryException($directoryWithoutFilename);
111-
}
109+
$this->createDirectory($directoryWithoutFilename);
112110
}
113111

114112
$createdFile = file_put_contents($fullPath, $contents);
@@ -119,4 +117,22 @@ public function put(string $path, string $contents): static
119117

120118
return $this;
121119
}
120+
121+
/**
122+
* Create a directory
123+
*
124+
* @param string $directory
125+
* @return bool
126+
* @throws \Saloon\Exceptions\UnableToCreateDirectoryException
127+
*/
128+
public function createDirectory(string $directory): bool
129+
{
130+
$createdDirectory = mkdir($directory, 0777, true);
131+
132+
if ($createdDirectory === false && is_dir($directory) === false) {
133+
throw new UnableToCreateDirectoryException($directory);
134+
}
135+
136+
return true;
137+
}
122138
}

src/Http/Faking/Fixture.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Saloon\Helpers\MockConfig;
99
use Saloon\Data\RecordedResponse;
1010
use Saloon\Exceptions\FixtureMissingException;
11-
use Saloon\Exceptions\DirectoryNotFoundException;
1211

1312
class Fixture
1413
{
@@ -37,13 +36,14 @@ class Fixture
3736
* Constructor
3837
*
3938
* @param string $name
40-
* @param Storage|null $storage
41-
* @throws DirectoryNotFoundException
39+
* @param \Saloon\Helpers\Storage|null $storage
40+
* @throws \Saloon\Exceptions\DirectoryNotFoundException
41+
* @throws \Saloon\Exceptions\UnableToCreateDirectoryException
4242
*/
4343
public function __construct(string $name, Storage $storage = null)
4444
{
4545
$this->name = $name;
46-
$this->storage = $storage ?? new Storage(MockConfig::getFixturePath());
46+
$this->storage = $storage ?? new Storage(MockConfig::getFixturePath(), true);
4747
}
4848

4949
/**

src/Http/Response.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,6 @@ public function getRequest(): Request
8787
return $this->pendingRequest->getRequest();
8888
}
8989

90-
/**
91-
* Get the raw response
92-
*
93-
* @return mixed
94-
*/
95-
public function getRawResponse(): mixed
96-
{
97-
return $this->psrResponse;
98-
}
99-
10090
/**
10191
* Get the body of the response as string.
10292
*

tests/Unit/MiddlewarePipelineTest.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@
183183
})
184184
->onResponse(function (Response $response) {
185185
return $response->throw();
186-
});
186+
}, false, 'response');
187187

188188
expect($pipelineB->getRequestPipeline()->getPipes())->toBeEmpty();
189189
expect($pipelineB->getResponsePipeline()->getPipes())->toBeEmpty();
@@ -192,6 +192,21 @@
192192

193193
expect($pipelineB->getRequestPipeline()->getPipes())->toHaveCount(2);
194194
expect($pipelineB->getResponsePipeline()->getPipes())->toHaveCount(1);
195+
expect($pipelineA->getRequestPipeline()->getPipes())->toEqual($pipelineB->getRequestPipeline()->getPipes());
196+
expect($pipelineA->getResponsePipeline()->getPipes())->toEqual($pipelineB->getResponsePipeline()->getPipes());
197+
});
198+
199+
test('when merging a middleware pipeline together if two pipelines exist with the same pipe it throws an exception', function () {
200+
$pipelineA = new MiddlewarePipeline;
201+
$pipelineB = new MiddlewarePipeline;
202+
203+
$pipelineA->onRequest(fn () => null, false, 'howdy');
204+
$pipelineB->onRequest(fn () => null, false, 'howdy');
205+
206+
$this->expectException(DuplicatePipeNameException::class);
207+
$this->expectExceptionMessage('The "howdy" pipe already exists on the pipeline');
208+
209+
$pipelineA->merge($pipelineB);
195210
});
196211

197212
test('a request pipeline is run in order of pipes', function () {

0 commit comments

Comments
 (0)