Skip to content

Commit 0e6a80e

Browse files
authored
Merge pull request #158 from Taluu/builder
Add plugin client builder
2 parents d61dd27 + cbb22ef commit 0e6a80e

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

src/PluginClientBuilder.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Http\Client\Common;
6+
7+
use Http\Client\HttpAsyncClient;
8+
use Psr\Http\Client\ClientInterface;
9+
10+
/**
11+
* Build an instance of a PluginClient with a dynamic list of plugins.
12+
*
13+
* @author Baptiste Clavié <[email protected]>
14+
*/
15+
final class PluginClientBuilder
16+
{
17+
/** @var Plugin[][] List of plugins ordered by priority [priority => Plugin[]]). */
18+
private $plugins = [];
19+
20+
/** @var array Array of options to give to the plugin client */
21+
private $options = [];
22+
23+
/**
24+
* @param int $priority Priority of the plugin. The higher comes first.
25+
*/
26+
public function addPlugin(Plugin $plugin, int $priority = 0): self
27+
{
28+
$this->plugins[$priority][] = $plugin;
29+
30+
return $this;
31+
}
32+
33+
public function setOption(string $name, $value): self
34+
{
35+
$this->options[$name] = $value;
36+
37+
return $this;
38+
}
39+
40+
public function removeOption(string $name): self
41+
{
42+
unset($this->options[$name]);
43+
44+
return $this;
45+
}
46+
47+
/**
48+
* @param ClientInterface | HttpAsyncClient $client
49+
*/
50+
public function createClient($client): PluginClient
51+
{
52+
if (!$client instanceof ClientInterface && !$client instanceof HttpAsyncClient) {
53+
throw new \RuntimeException('You must provide a valid http client');
54+
}
55+
56+
$plugins = $this->plugins;
57+
58+
if (0 === count($plugins)) {
59+
$plugins[] = [];
60+
}
61+
62+
krsort($plugins);
63+
$plugins = array_merge(...$plugins);
64+
65+
return new PluginClient(
66+
$client,
67+
array_values($plugins),
68+
$this->options
69+
);
70+
}
71+
}

tests/PluginClientBuilderTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace tests\Http\Client\Common;
6+
7+
use Closure;
8+
use Http\Client\Common\Plugin;
9+
use Http\Client\Common\PluginClient;
10+
use Http\Client\Common\PluginClientBuilder;
11+
use Http\Client\HttpAsyncClient;
12+
use Http\Client\HttpClient;
13+
use PHPUnit\Framework\TestCase;
14+
15+
class PluginClientBuilderTest extends TestCase
16+
{
17+
/** @dataProvider clientProvider */
18+
public function testPriority(string $client): void
19+
{
20+
$builder = new PluginClientBuilder();
21+
22+
$plugins = [
23+
10 => $this->prophesize(Plugin::class)->reveal(),
24+
-10 => $this->prophesize(Plugin::class)->reveal(),
25+
0 => $this->prophesize(Plugin::class)->reveal(),
26+
];
27+
28+
foreach ($plugins as $priority => $plugin) {
29+
$builder->addPlugin($plugin, $priority);
30+
}
31+
32+
$client = $this->prophesize($client)->reveal();
33+
$client = $builder->createClient($client);
34+
35+
$closure = Closure::bind(
36+
function (): array {
37+
return $this->plugins;
38+
},
39+
$client,
40+
PluginClient::class
41+
);
42+
43+
$plugged = $closure();
44+
45+
$expected = $plugins;
46+
krsort($expected);
47+
$expected = array_values($expected);
48+
49+
$this->assertSame($expected, $plugged);
50+
}
51+
52+
/** @dataProvider clientProvider */
53+
public function testOptions(string $client): void
54+
{
55+
$builder = new PluginClientBuilder();
56+
$builder->setOption('max_restarts', 5);
57+
58+
$client = $this->prophesize($client)->reveal();
59+
$client = $builder->createClient($client);
60+
61+
$closure = Closure::bind(
62+
function (): array {
63+
return $this->options;
64+
},
65+
$client,
66+
PluginClient::class
67+
);
68+
69+
$options = $closure();
70+
71+
$this->assertArrayHasKey('max_restarts', $options);
72+
$this->assertSame(5, $options['max_restarts']);
73+
}
74+
75+
public function clientProvider(): iterable
76+
{
77+
yield 'sync\'d http client' => [HttpClient::class];
78+
yield 'async\'d http client' => [HttpAsyncClient::class];
79+
}
80+
}

0 commit comments

Comments
 (0)