CommonClassesStrategy::getPsr18Candidates()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 0
cts 14
cp 0
rs 9.7
c 0
b 0
f 0
cc 4
nc 5
nop 0
crap 20
1
<?php
2
3
namespace Http\Discovery\Strategy;
4
5
use GuzzleHttp\Promise\Promise;
6
use GuzzleHttp\Psr7\Request as GuzzleRequest;
7
use Http\Client\HttpAsyncClient;
8
use Http\Client\HttpClient;
9
use Http\Discovery\Exception\NotFoundException;
10
use Http\Discovery\MessageFactoryDiscovery;
11
use Http\Discovery\Psr17FactoryDiscovery;
12
use Http\Message\RequestFactory;
13
use Psr\Http\Message\RequestFactoryInterface as Psr17RequestFactory;
14
use Http\Message\MessageFactory;
15
use Http\Message\MessageFactory\GuzzleMessageFactory;
16
use Http\Message\StreamFactory;
17
use Http\Message\StreamFactory\GuzzleStreamFactory;
18
use Http\Message\UriFactory;
19
use Http\Message\UriFactory\GuzzleUriFactory;
20
use Http\Message\MessageFactory\DiactorosMessageFactory;
21
use Http\Message\StreamFactory\DiactorosStreamFactory;
22
use Http\Message\UriFactory\DiactorosUriFactory;
23
use Psr\Http\Client\ClientInterface as Psr18Client;
24
use Zend\Diactoros\Request as DiactorosRequest;
25
use Http\Message\MessageFactory\SlimMessageFactory;
26
use Http\Message\StreamFactory\SlimStreamFactory;
27
use Http\Message\UriFactory\SlimUriFactory;
28
use Slim\Http\Request as SlimRequest;
29
use GuzzleHttp\Client as GuzzleHttp;
30
use Http\Adapter\Guzzle7\Client as Guzzle7;
31
use Http\Adapter\Guzzle6\Client as Guzzle6;
32
use Http\Adapter\Guzzle5\Client as Guzzle5;
33
use Http\Client\Curl\Client as Curl;
34
use Http\Client\Socket\Client as Socket;
35
use Http\Adapter\React\Client as React;
36
use Http\Adapter\Buzz\Client as Buzz;
37
use Http\Adapter\Cake\Client as Cake;
38
use Http\Adapter\Zend\Client as Zend;
39
use Http\Adapter\Artax\Client as Artax;
40
use Symfony\Component\HttpClient\HttplugClient as SymfonyHttplug;
41
use Symfony\Component\HttpClient\Psr18Client as SymfonyPsr18;
42
use Nyholm\Psr7\Factory\HttplugFactory as NyholmHttplugFactory;
43
44
/**
45
 * @internal
46
 *
47
 * @author Tobias Nyholm <[email protected]>
48
 */
49
final class CommonClassesStrategy implements DiscoveryStrategy
50
{
51
    /**
52
     * @var array
53
     */
54
    private static $classes = [
55
        MessageFactory::class => [
56
            ['class' => NyholmHttplugFactory::class, 'condition' => [NyholmHttplugFactory::class]],
57
            ['class' => GuzzleMessageFactory::class, 'condition' => [GuzzleRequest::class, GuzzleMessageFactory::class]],
58
            ['class' => DiactorosMessageFactory::class, 'condition' => [DiactorosRequest::class, DiactorosMessageFactory::class]],
59
            ['class' => SlimMessageFactory::class, 'condition' => [SlimRequest::class, SlimMessageFactory::class]],
60
        ],
61
        StreamFactory::class => [
62
            ['class' => NyholmHttplugFactory::class, 'condition' => [NyholmHttplugFactory::class]],
63
            ['class' => GuzzleStreamFactory::class, 'condition' => [GuzzleRequest::class, GuzzleStreamFactory::class]],
64
            ['class' => DiactorosStreamFactory::class, 'condition' => [DiactorosRequest::class, DiactorosStreamFactory::class]],
65
            ['class' => SlimStreamFactory::class, 'condition' => [SlimRequest::class, SlimStreamFactory::class]],
66
        ],
67
        UriFactory::class => [
68
            ['class' => NyholmHttplugFactory::class, 'condition' => [NyholmHttplugFactory::class]],
69
            ['class' => GuzzleUriFactory::class, 'condition' => [GuzzleRequest::class, GuzzleUriFactory::class]],
70
            ['class' => DiactorosUriFactory::class, 'condition' => [DiactorosRequest::class, DiactorosUriFactory::class]],
71
            ['class' => SlimUriFactory::class, 'condition' => [SlimRequest::class, SlimUriFactory::class]],
72
        ],
73
        HttpAsyncClient::class => [
74
            ['class' => SymfonyHttplug::class, 'condition' => [SymfonyHttplug::class, Promise::class, RequestFactory::class, [self::class, 'isPsr17FactoryInstalled']]],
75
            ['class' => Guzzle7::class, 'condition' => Guzzle7::class],
76
            ['class' => Guzzle6::class, 'condition' => Guzzle6::class],
77
            ['class' => Curl::class, 'condition' => Curl::class],
78
            ['class' => React::class, 'condition' => React::class],
79
        ],
80
        HttpClient::class => [
81
            ['class' => SymfonyHttplug::class, 'condition' => [SymfonyHttplug::class, RequestFactory::class, [self::class, 'isPsr17FactoryInstalled']]],
82
            ['class' => Guzzle7::class, 'condition' => Guzzle7::class],
83
            ['class' => Guzzle6::class, 'condition' => Guzzle6::class],
84
            ['class' => Guzzle5::class, 'condition' => Guzzle5::class],
85
            ['class' => Curl::class, 'condition' => Curl::class],
86
            ['class' => Socket::class, 'condition' => Socket::class],
87
            ['class' => Buzz::class, 'condition' => Buzz::class],
88
            ['class' => React::class, 'condition' => React::class],
89
            ['class' => Cake::class, 'condition' => Cake::class],
90
            ['class' => Zend::class, 'condition' => Zend::class],
91
            ['class' => Artax::class, 'condition' => Artax::class],
92
            [
93
                'class' => [self::class, 'buzzInstantiate'],
94
                'condition' => [\Buzz\Client\FileGetContents::class, \Buzz\Message\ResponseBuilder::class],
95
            ],
96
        ],
97
        Psr18Client::class => [
98
            [
99
                'class' => [self::class, 'symfonyPsr18Instantiate'],
100
                'condition' => [SymfonyPsr18::class, Psr17RequestFactory::class],
101
            ],
102
            [
103
                'class' => GuzzleHttp::class,
104
                'condition' => [self::class, 'isGuzzleImplementingPsr18'],
105
            ],
106
            [
107
                'class' => [self::class, 'buzzInstantiate'],
108
                'condition' => [\Buzz\Client\FileGetContents::class, \Buzz\Message\ResponseBuilder::class],
109
            ],
110
        ],
111
    ];
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public static function getCandidates($type)
117
    {
118
        if (Psr18Client::class === $type) {
119
            return self::getPsr18Candidates();
120
        }
121
122
        return self::$classes[$type] ?? [];
123
    }
124
125
    /**
126
     * @return array The return value is always an array with zero or more elements. Each
127
     *               element is an array with two keys ['class' => string, 'condition' => mixed].
128
     */
129
    private static function getPsr18Candidates()
130
    {
131
        $candidates = self::$classes[Psr18Client::class];
132
133
        // HTTPlug 2.0 clients implements PSR18Client too.
134
        foreach (self::$classes[HttpClient::class] as $c) {
135
            try {
136
                if (is_subclass_of($c['class'], Psr18Client::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Psr\Http\Client\ClientInterface::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
137
                    $candidates[] = $c;
138
                }
139
            } catch (\Throwable $e) {
140
                trigger_error(sprintf('Got exception "%s (%s)" while checking if a PSR-18 Client is available', get_class($e), $e->getMessage()), E_USER_WARNING);
141
            }
142
        }
143
144
        return $candidates;
145
    }
146
147
    public static function buzzInstantiate()
148
    {
149
        return new \Buzz\Client\FileGetContents(MessageFactoryDiscovery::find());
150
    }
151
152
    public static function symfonyPsr18Instantiate()
153
    {
154
        return new SymfonyPsr18(null, Psr17FactoryDiscovery::findResponseFactory(), Psr17FactoryDiscovery::findStreamFactory());
155
    }
156
157
    public static function isGuzzleImplementingPsr18()
158
    {
159
        return defined('GuzzleHttp\ClientInterface::MAJOR_VERSION');
160
    }
161
162
    /**
163
     * Can be used as a condition.
164
     *
165
     * @return bool
166
     */
167
    public static function isPsr17FactoryInstalled()
168
    {
169
        try {
170
            Psr17FactoryDiscovery::findResponseFactory();
171
        } catch (NotFoundException $e) {
172
            return false;
173
        } catch (\Throwable $e) {
174
            trigger_error(sprintf('Got exception "%s (%s)" while checking if a PSR-17 ResponseFactory is available', get_class($e), $e->getMessage()), E_USER_WARNING);
175
176
            return false;
177
        }
178
179
        return true;
180
    }
181
}
182