Completed
Pull Request — master (#359)
by Maxence
41s
created
lib/Vendor/Psr/Http/Client/ClientInterface.php 2 patches
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -7,14 +7,14 @@
 block discarded – undo
7 7
 
8 8
 interface ClientInterface
9 9
 {
10
-    /**
11
-     * Sends a PSR-7 request and returns a PSR-7 response.
12
-     *
13
-     * @param RequestInterface $request
14
-     *
15
-     * @return ResponseInterface
16
-     *
17
-     * @throws \OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request.
18
-     */
19
-    public function sendRequest(RequestInterface $request): ResponseInterface;
10
+	/**
11
+	 * Sends a PSR-7 request and returns a PSR-7 response.
12
+	 *
13
+	 * @param RequestInterface $request
14
+	 *
15
+	 * @return ResponseInterface
16
+	 *
17
+	 * @throws \OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request.
18
+	 */
19
+	public function sendRequest(RequestInterface $request): ResponseInterface;
20 20
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -5,8 +5,7 @@
 block discarded – undo
5 5
 use OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface;
6 6
 use OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\ResponseInterface;
7 7
 
8
-interface ClientInterface
9
-{
8
+interface ClientInterface {
10 9
     /**
11 10
      * Sends a PSR-7 request and returns a PSR-7 response.
12 11
      *
Please login to merge, or discard this patch.
lib/Vendor/Psr/Http/Client/NetworkExceptionInterface.php 2 patches
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -13,12 +13,12 @@
 block discarded – undo
13 13
  */
14 14
 interface NetworkExceptionInterface extends ClientExceptionInterface
15 15
 {
16
-    /**
17
-     * Returns the request.
18
-     *
19
-     * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
20
-     *
21
-     * @return RequestInterface
22
-     */
23
-    public function getRequest(): RequestInterface;
16
+	/**
17
+	 * Returns the request.
18
+	 *
19
+	 * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
20
+	 *
21
+	 * @return RequestInterface
22
+	 */
23
+	public function getRequest(): RequestInterface;
24 24
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -11,8 +11,7 @@
 block discarded – undo
11 11
  *
12 12
  * Example: the target host name can not be resolved or the connection failed.
13 13
  */
14
-interface NetworkExceptionInterface extends ClientExceptionInterface
15
-{
14
+interface NetworkExceptionInterface extends ClientExceptionInterface {
16 15
     /**
17 16
      * Returns the request.
18 17
      *
Please login to merge, or discard this patch.
lib/Vendor/Http/Discovery/UriFactoryDiscovery.php 2 patches
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -14,21 +14,21 @@
 block discarded – undo
14 14
  */
15 15
 final class UriFactoryDiscovery extends ClassDiscovery
16 16
 {
17
-    /**
18
-     * Finds a URI Factory.
19
-     *
20
-     * @return UriFactory
21
-     *
22
-     * @throws Exception\NotFoundException
23
-     */
24
-    public static function find()
25
-    {
26
-        try {
27
-            $uriFactory = static::findOneByType(UriFactory::class);
28
-        } catch (DiscoveryFailedException $e) {
29
-            throw new NotFoundException('No uri factories found. To use Guzzle, Diactoros or Slim Framework factories install php-http/message and the chosen message implementation.', 0, $e);
30
-        }
17
+	/**
18
+	 * Finds a URI Factory.
19
+	 *
20
+	 * @return UriFactory
21
+	 *
22
+	 * @throws Exception\NotFoundException
23
+	 */
24
+	public static function find()
25
+	{
26
+		try {
27
+			$uriFactory = static::findOneByType(UriFactory::class);
28
+		} catch (DiscoveryFailedException $e) {
29
+			throw new NotFoundException('No uri factories found. To use Guzzle, Diactoros or Slim Framework factories install php-http/message and the chosen message implementation.', 0, $e);
30
+		}
31 31
 
32
-        return static::instantiateClass($uriFactory);
33
-    }
32
+		return static::instantiateClass($uriFactory);
33
+	}
34 34
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -12,8 +12,7 @@
 block discarded – undo
12 12
  *
13 13
  * @deprecated This will be removed in 2.0. Consider using Psr17FactoryDiscovery.
14 14
  */
15
-final class UriFactoryDiscovery extends ClassDiscovery
16
-{
15
+final class UriFactoryDiscovery extends ClassDiscovery {
17 16
     /**
18 17
      * Finds a URI Factory.
19 18
      *
Please login to merge, or discard this patch.
lib/Vendor/Http/Discovery/HttpAsyncClientDiscovery.php 2 patches
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -12,21 +12,21 @@
 block discarded – undo
12 12
  */
13 13
 final class HttpAsyncClientDiscovery extends ClassDiscovery
14 14
 {
15
-    /**
16
-     * Finds an HTTP Async Client.
17
-     *
18
-     * @return HttpAsyncClient
19
-     *
20
-     * @throws Exception\NotFoundException
21
-     */
22
-    public static function find()
23
-    {
24
-        try {
25
-            $asyncClient = static::findOneByType(HttpAsyncClient::class);
26
-        } catch (DiscoveryFailedException $e) {
27
-            throw new NotFoundException('No HTTPlug async clients found. Make sure to install a package providing "php-http/async-client-implementation". Example: "php-http/guzzle6-adapter".', 0, $e);
28
-        }
15
+	/**
16
+	 * Finds an HTTP Async Client.
17
+	 *
18
+	 * @return HttpAsyncClient
19
+	 *
20
+	 * @throws Exception\NotFoundException
21
+	 */
22
+	public static function find()
23
+	{
24
+		try {
25
+			$asyncClient = static::findOneByType(HttpAsyncClient::class);
26
+		} catch (DiscoveryFailedException $e) {
27
+			throw new NotFoundException('No HTTPlug async clients found. Make sure to install a package providing "php-http/async-client-implementation". Example: "php-http/guzzle6-adapter".', 0, $e);
28
+		}
29 29
 
30
-        return static::instantiateClass($asyncClient);
31
-    }
30
+		return static::instantiateClass($asyncClient);
31
+	}
32 32
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -10,8 +10,7 @@
 block discarded – undo
10 10
  *
11 11
  * @author Joel Wurtz <[email protected]>
12 12
  */
13
-final class HttpAsyncClientDiscovery extends ClassDiscovery
14
-{
13
+final class HttpAsyncClientDiscovery extends ClassDiscovery {
15 14
     /**
16 15
      * Finds an HTTP Async Client.
17 16
      *
Please login to merge, or discard this patch.
lib/Vendor/Http/Discovery/Composer/Plugin.php 2 patches
Indentation   +408 added lines, -408 removed lines patch added patch discarded remove patch
@@ -38,370 +38,370 @@  discard block
 block discarded – undo
38 38
  */
39 39
 class Plugin implements PluginInterface, EventSubscriberInterface
40 40
 {
41
-    /**
42
-     * Describes, for every supported virtual implementation, which packages
43
-     * provide said implementation and which extra dependencies each package
44
-     * requires to provide the implementation.
45
-     */
46
-    private const PROVIDE_RULES = [
47
-        'php-http/async-client-implementation' => [
48
-            'symfony/http-client:>=6.3' => ['guzzlehttp/promises', 'psr/http-factory-implementation', 'php-http/httplug'],
49
-            'symfony/http-client' => ['guzzlehttp/promises', 'php-http/message-factory', 'psr/http-factory-implementation', 'php-http/httplug'],
50
-            'php-http/guzzle7-adapter' => [],
51
-            'php-http/guzzle6-adapter' => [],
52
-            'php-http/curl-client' => [],
53
-            'php-http/react-adapter' => [],
54
-        ],
55
-        'php-http/client-implementation' => [
56
-            'symfony/http-client:>=6.3' => ['psr/http-factory-implementation', 'php-http/httplug'],
57
-            'symfony/http-client' => ['php-http/message-factory', 'psr/http-factory-implementation', 'php-http/httplug'],
58
-            'php-http/guzzle7-adapter' => [],
59
-            'php-http/guzzle6-adapter' => [],
60
-            'php-http/cakephp-adapter' => [],
61
-            'php-http/curl-client' => [],
62
-            'php-http/react-adapter' => [],
63
-            'php-http/buzz-adapter' => [],
64
-            'php-http/artax-adapter' => [],
65
-            'kriswallsmith/buzz:^1' => [],
66
-        ],
67
-        'psr/http-client-implementation' => [
68
-            'symfony/http-client' => ['psr/http-factory-implementation', 'psr/http-client'],
69
-            'guzzlehttp/guzzle' => [],
70
-            'kriswallsmith/buzz:^1' => [],
71
-        ],
72
-        'psr/http-message-implementation' => [
73
-            'php-http/discovery' => ['psr/http-factory-implementation'],
74
-        ],
75
-        'psr/http-factory-implementation' => [
76
-            'nyholm/psr7' => [],
77
-            'guzzlehttp/psr7:>=2' => [],
78
-            'slim/psr7' => [],
79
-            'laminas/laminas-diactoros' => [],
80
-            'phalcon/cphalcon:^4' => [],
81
-            'http-interop/http-factory-guzzle' => [],
82
-            'http-interop/http-factory-diactoros' => [],
83
-            'http-interop/http-factory-slim' => [],
84
-            'httpsoft/http-message' => [],
85
-        ],
86
-    ];
87
-
88
-    /**
89
-     * Describes which package should be preferred on the left side
90
-     * depending on which one is already installed on the right side.
91
-     */
92
-    private const STICKYNESS_RULES = [
93
-        'symfony/http-client' => 'symfony/framework-bundle',
94
-        'php-http/guzzle7-adapter' => 'guzzlehttp/guzzle:^7',
95
-        'php-http/guzzle6-adapter' => 'guzzlehttp/guzzle:^6',
96
-        'php-http/guzzle5-adapter' => 'guzzlehttp/guzzle:^5',
97
-        'php-http/cakephp-adapter' => 'cakephp/cakephp',
98
-        'php-http/react-adapter' => 'react/event-loop',
99
-        'php-http/buzz-adapter' => 'kriswallsmith/buzz:^0.15.1',
100
-        'php-http/artax-adapter' => 'amphp/artax:^3',
101
-        'http-interop/http-factory-guzzle' => 'guzzlehttp/psr7:^1',
102
-        'http-interop/http-factory-slim' => 'slim/slim:^3',
103
-    ];
104
-
105
-    private const INTERFACE_MAP = [
106
-        'php-http/async-client-implementation' => [
107
-            'Http\Client\HttpAsyncClient',
108
-        ],
109
-        'php-http/client-implementation' => [
110
-            'Http\Client\HttpClient',
111
-        ],
112
-        'psr/http-client-implementation' => [
113
-            'Psr\Http\Client\ClientInterface',
114
-        ],
115
-        'psr/http-factory-implementation' => [
116
-            'Psr\Http\Message\RequestFactoryInterface',
117
-            'Psr\Http\Message\ResponseFactoryInterface',
118
-            'Psr\Http\Message\ServerRequestFactoryInterface',
119
-            'Psr\Http\Message\StreamFactoryInterface',
120
-            'Psr\Http\Message\UploadedFileFactoryInterface',
121
-            'Psr\Http\Message\UriFactoryInterface',
122
-        ],
123
-    ];
124
-
125
-    public static function getSubscribedEvents(): array
126
-    {
127
-        return [
128
-            ScriptEvents::PRE_AUTOLOAD_DUMP => 'preAutoloadDump',
129
-            ScriptEvents::POST_UPDATE_CMD => 'postUpdate',
130
-        ];
131
-    }
132
-
133
-    public function activate(Composer $composer, IOInterface $io): void
134
-    {
135
-    }
136
-
137
-    public function deactivate(Composer $composer, IOInterface $io)
138
-    {
139
-    }
140
-
141
-    public function uninstall(Composer $composer, IOInterface $io)
142
-    {
143
-    }
144
-
145
-    public function postUpdate(Event $event)
146
-    {
147
-        $composer = $event->getComposer();
148
-        $repo = $composer->getRepositoryManager()->getLocalRepository();
149
-        $requires = [
150
-            $composer->getPackage()->getRequires(),
151
-            $composer->getPackage()->getDevRequires(),
152
-        ];
153
-        $pinnedAbstractions = [];
154
-        $pinned = $composer->getPackage()->getExtra()['discovery'] ?? [];
155
-        foreach (self::INTERFACE_MAP as $abstraction => $interfaces) {
156
-            foreach (isset($pinned[$abstraction]) ? [] : $interfaces as $interface) {
157
-                if (!isset($pinned[$interface])) {
158
-                    continue 2;
159
-                }
160
-            }
161
-            $pinnedAbstractions[$abstraction] = true;
162
-        }
163
-
164
-        $missingRequires = $this->getMissingRequires($repo, $requires, 'project' === $composer->getPackage()->getType(), $pinnedAbstractions);
165
-        $missingRequires = [
166
-            'require' => array_fill_keys(array_merge([], ...array_values($missingRequires[0])), '*'),
167
-            'require-dev' => array_fill_keys(array_merge([], ...array_values($missingRequires[1])), '*'),
168
-            'remove' => array_fill_keys(array_merge([], ...array_values($missingRequires[2])), '*'),
169
-        ];
170
-
171
-        if (!$missingRequires = array_filter($missingRequires)) {
172
-            return;
173
-        }
174
-
175
-        $composerJsonContents = file_get_contents(Factory::getComposerFile());
176
-        $this->updateComposerJson($missingRequires, $composer->getConfig()->get('sort-packages'));
177
-
178
-        $installer = null;
179
-        // Find the composer installer, hack borrowed from symfony/flex
180
-        foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT) as $trace) {
181
-            if (isset($trace['object']) && $trace['object'] instanceof Installer) {
182
-                $installer = $trace['object'];
183
-                break;
184
-            }
185
-        }
186
-
187
-        if (!$installer) {
188
-            return;
189
-        }
190
-
191
-        $event->stopPropagation();
192
-
193
-        $dispatcher = $composer->getEventDispatcher();
194
-        $disableScripts = !method_exists($dispatcher, 'setRunScripts') || !((array) $dispatcher)["\0*\0runScripts"];
195
-        $composer = Factory::create($event->getIO(), null, false, $disableScripts);
196
-
197
-        /** @var Installer $installer */
198
-        $installer = clone $installer;
199
-        if (method_exists($installer, 'setAudit')) {
200
-            $trace['object']->setAudit(false);
201
-        }
202
-        // we need a clone of the installer to preserve its configuration state but with our own service objects
203
-        $installer->__construct(
204
-            $event->getIO(),
205
-            $composer->getConfig(),
206
-            $composer->getPackage(),
207
-            $composer->getDownloadManager(),
208
-            $composer->getRepositoryManager(),
209
-            $composer->getLocker(),
210
-            $composer->getInstallationManager(),
211
-            $composer->getEventDispatcher(),
212
-            $composer->getAutoloadGenerator()
213
-        );
214
-        if (method_exists($installer, 'setPlatformRequirementFilter')) {
215
-            $installer->setPlatformRequirementFilter(((array) $trace['object'])["\0*\0platformRequirementFilter"]);
216
-        }
217
-
218
-        if (0 !== $installer->run()) {
219
-            file_put_contents(Factory::getComposerFile(), $composerJsonContents);
220
-
221
-            return;
222
-        }
223
-
224
-        $versionSelector = new VersionSelector(ClassDiscovery::safeClassExists(RepositorySet::class) ? new RepositorySet() : new Pool());
225
-        $updateComposerJson = false;
226
-
227
-        foreach ($composer->getRepositoryManager()->getLocalRepository()->getPackages() as $package) {
228
-            foreach (['require', 'require-dev'] as $key) {
229
-                if (!isset($missingRequires[$key][$package->getName()])) {
230
-                    continue;
231
-                }
232
-                $updateComposerJson = true;
233
-                $missingRequires[$key][$package->getName()] = $versionSelector->findRecommendedRequireVersion($package);
234
-            }
235
-        }
236
-
237
-        if ($updateComposerJson) {
238
-            $this->updateComposerJson($missingRequires, $composer->getConfig()->get('sort-packages'));
239
-            $this->updateComposerLock($composer, $event->getIO());
240
-        }
241
-    }
242
-
243
-    public function getMissingRequires(InstalledRepositoryInterface $repo, array $requires, bool $isProject, array $pinnedAbstractions): array
244
-    {
245
-        $allPackages = [];
246
-        $devPackages = method_exists($repo, 'getDevPackageNames') ? array_fill_keys($repo->getDevPackageNames(), true) : [];
247
-
248
-        // One must require "php-http/discovery"
249
-        // to opt-in for auto-installation of virtual package implementations
250
-        if (!isset($requires[0]['php-http/discovery'])) {
251
-            $requires = [[], []];
252
-        }
253
-
254
-        foreach ($repo->getPackages() as $package) {
255
-            $allPackages[$package->getName()] = true;
256
-
257
-            if (1 < \count($names = $package->getNames(false))) {
258
-                $allPackages += array_fill_keys($names, false);
259
-
260
-                if (isset($devPackages[$package->getName()])) {
261
-                    $devPackages += $names;
262
-                }
263
-            }
264
-
265
-            if (isset($package->getRequires()['php-http/discovery'])) {
266
-                $requires[(int) isset($devPackages[$package->getName()])] += $package->getRequires();
267
-            }
268
-        }
269
-
270
-        $missingRequires = [[], [], []];
271
-        $versionParser = new VersionParser();
272
-
273
-        if (ClassDiscovery::safeClassExists(\Phalcon\Http\Message\RequestFactory::class, false)) {
274
-            $missingRequires[0]['psr/http-factory-implementation'] = [];
275
-            $missingRequires[1]['psr/http-factory-implementation'] = [];
276
-        }
277
-
278
-        foreach ($requires as $dev => $rules) {
279
-            $abstractions = [];
280
-            $rules = array_intersect_key(self::PROVIDE_RULES, $rules);
281
-
282
-            while ($rules) {
283
-                $abstraction = key($rules);
284
-
285
-                if (isset($pinnedAbstractions[$abstraction])) {
286
-                    unset($rules[$abstraction]);
287
-                    continue;
288
-                }
289
-
290
-                $abstractions[] = $abstraction;
291
-
292
-                foreach (array_shift($rules) as $candidate => $deps) {
293
-                    [$candidate, $version] = explode(':', $candidate, 2) + [1 => null];
294
-
295
-                    if (!isset($allPackages[$candidate])) {
296
-                        continue;
297
-                    }
298
-                    if (null !== $version && !$repo->findPackage($candidate, $versionParser->parseConstraints($version))) {
299
-                        continue;
300
-                    }
301
-                    if ($isProject && !$dev && isset($devPackages[$candidate])) {
302
-                        $missingRequires[0][$abstraction] = [$candidate];
303
-                        $missingRequires[2][$abstraction] = [$candidate];
304
-                    } else {
305
-                        $missingRequires[$dev][$abstraction] = [];
306
-                    }
307
-
308
-                    foreach ($deps as $dep) {
309
-                        if (isset(self::PROVIDE_RULES[$dep])) {
310
-                            $rules[$dep] = self::PROVIDE_RULES[$dep];
311
-                        } elseif (!isset($allPackages[$dep])) {
312
-                            $missingRequires[$dev][$abstraction][] = $dep;
313
-                        } elseif ($isProject && !$dev && isset($devPackages[$dep])) {
314
-                            $missingRequires[0][$abstraction][] = $dep;
315
-                            $missingRequires[2][$abstraction][] = $dep;
316
-                        }
317
-                    }
318
-                    break;
319
-                }
320
-            }
321
-
322
-            while ($abstractions) {
323
-                $abstraction = array_shift($abstractions);
324
-
325
-                if (isset($missingRequires[$dev][$abstraction])) {
326
-                    continue;
327
-                }
328
-                $candidates = self::PROVIDE_RULES[$abstraction];
329
-
330
-                foreach ($candidates as $candidate => $deps) {
331
-                    [$candidate, $version] = explode(':', $candidate, 2) + [1 => null];
332
-
333
-                    if (null !== $version && !$repo->findPackage($candidate, $versionParser->parseConstraints($version))) {
334
-                        continue;
335
-                    }
336
-                    if (isset($allPackages[$candidate]) && (!$isProject || $dev || !isset($devPackages[$candidate]))) {
337
-                        continue 2;
338
-                    }
339
-                }
340
-
341
-                foreach (array_intersect_key(self::STICKYNESS_RULES, $candidates) as $candidate => $stickyRule) {
342
-                    [$stickyName, $stickyVersion] = explode(':', $stickyRule, 2) + [1 => null];
343
-                    if (!isset($allPackages[$stickyName]) || ($isProject && !$dev && isset($devPackages[$stickyName]))) {
344
-                        continue;
345
-                    }
346
-                    if (null !== $stickyVersion && !$repo->findPackage($stickyName, $versionParser->parseConstraints($stickyVersion))) {
347
-                        continue;
348
-                    }
349
-
350
-                    $candidates = [$candidate => $candidates[$candidate]];
351
-                    break;
352
-                }
353
-
354
-                $dep = key($candidates);
355
-                [$dep] = explode(':', $dep, 2);
356
-                $missingRequires[$dev][$abstraction] = [$dep];
357
-
358
-                if ($isProject && !$dev && isset($devPackages[$dep])) {
359
-                    $missingRequires[2][$abstraction][] = $dep;
360
-                }
361
-            }
362
-        }
363
-
364
-        $missingRequires[1] = array_diff_key($missingRequires[1], $missingRequires[0]);
365
-
366
-        return $missingRequires;
367
-    }
368
-
369
-    public function preAutoloadDump(Event $event)
370
-    {
371
-        $filesystem = new Filesystem();
372
-        // Double realpath() on purpose, see https://bugs.php.net/72738
373
-        $vendorDir = $filesystem->normalizePath(realpath(realpath($event->getComposer()->getConfig()->get('vendor-dir'))));
374
-        $filesystem->ensureDirectoryExists($vendorDir.'/composer');
375
-        $pinned = $event->getComposer()->getPackage()->getExtra()['discovery'] ?? [];
376
-        $candidates = [];
377
-
378
-        $allInterfaces = array_merge(...array_values(self::INTERFACE_MAP));
379
-        foreach ($pinned as $abstraction => $class) {
380
-            if (isset(self::INTERFACE_MAP[$abstraction])) {
381
-                $interfaces = self::INTERFACE_MAP[$abstraction];
382
-            } elseif (false !== $k = array_search($abstraction, $allInterfaces, true)) {
383
-                $interfaces = [$allInterfaces[$k]];
384
-            } else {
385
-                throw new \UnexpectedValueException(sprintf('Invalid "extra.discovery" pinned in composer.json: "%s" is not one of ["%s"].', $abstraction, implode('", "', array_keys(self::INTERFACE_MAP))));
386
-            }
387
-
388
-            foreach ($interfaces as $interface) {
389
-                $candidates[] = sprintf("case %s: return [['class' => %s]];\n", var_export($interface, true), var_export($class, true));
390
-            }
391
-        }
392
-
393
-        $file = $vendorDir.'/composer/GeneratedDiscoveryStrategy.php';
394
-
395
-        if (!$candidates) {
396
-            if (file_exists($file)) {
397
-                unlink($file);
398
-            }
399
-
400
-            return;
401
-        }
402
-
403
-        $candidates = implode('            ', $candidates);
404
-        $code = <<<EOPHP
41
+	/**
42
+	 * Describes, for every supported virtual implementation, which packages
43
+	 * provide said implementation and which extra dependencies each package
44
+	 * requires to provide the implementation.
45
+	 */
46
+	private const PROVIDE_RULES = [
47
+		'php-http/async-client-implementation' => [
48
+			'symfony/http-client:>=6.3' => ['guzzlehttp/promises', 'psr/http-factory-implementation', 'php-http/httplug'],
49
+			'symfony/http-client' => ['guzzlehttp/promises', 'php-http/message-factory', 'psr/http-factory-implementation', 'php-http/httplug'],
50
+			'php-http/guzzle7-adapter' => [],
51
+			'php-http/guzzle6-adapter' => [],
52
+			'php-http/curl-client' => [],
53
+			'php-http/react-adapter' => [],
54
+		],
55
+		'php-http/client-implementation' => [
56
+			'symfony/http-client:>=6.3' => ['psr/http-factory-implementation', 'php-http/httplug'],
57
+			'symfony/http-client' => ['php-http/message-factory', 'psr/http-factory-implementation', 'php-http/httplug'],
58
+			'php-http/guzzle7-adapter' => [],
59
+			'php-http/guzzle6-adapter' => [],
60
+			'php-http/cakephp-adapter' => [],
61
+			'php-http/curl-client' => [],
62
+			'php-http/react-adapter' => [],
63
+			'php-http/buzz-adapter' => [],
64
+			'php-http/artax-adapter' => [],
65
+			'kriswallsmith/buzz:^1' => [],
66
+		],
67
+		'psr/http-client-implementation' => [
68
+			'symfony/http-client' => ['psr/http-factory-implementation', 'psr/http-client'],
69
+			'guzzlehttp/guzzle' => [],
70
+			'kriswallsmith/buzz:^1' => [],
71
+		],
72
+		'psr/http-message-implementation' => [
73
+			'php-http/discovery' => ['psr/http-factory-implementation'],
74
+		],
75
+		'psr/http-factory-implementation' => [
76
+			'nyholm/psr7' => [],
77
+			'guzzlehttp/psr7:>=2' => [],
78
+			'slim/psr7' => [],
79
+			'laminas/laminas-diactoros' => [],
80
+			'phalcon/cphalcon:^4' => [],
81
+			'http-interop/http-factory-guzzle' => [],
82
+			'http-interop/http-factory-diactoros' => [],
83
+			'http-interop/http-factory-slim' => [],
84
+			'httpsoft/http-message' => [],
85
+		],
86
+	];
87
+
88
+	/**
89
+	 * Describes which package should be preferred on the left side
90
+	 * depending on which one is already installed on the right side.
91
+	 */
92
+	private const STICKYNESS_RULES = [
93
+		'symfony/http-client' => 'symfony/framework-bundle',
94
+		'php-http/guzzle7-adapter' => 'guzzlehttp/guzzle:^7',
95
+		'php-http/guzzle6-adapter' => 'guzzlehttp/guzzle:^6',
96
+		'php-http/guzzle5-adapter' => 'guzzlehttp/guzzle:^5',
97
+		'php-http/cakephp-adapter' => 'cakephp/cakephp',
98
+		'php-http/react-adapter' => 'react/event-loop',
99
+		'php-http/buzz-adapter' => 'kriswallsmith/buzz:^0.15.1',
100
+		'php-http/artax-adapter' => 'amphp/artax:^3',
101
+		'http-interop/http-factory-guzzle' => 'guzzlehttp/psr7:^1',
102
+		'http-interop/http-factory-slim' => 'slim/slim:^3',
103
+	];
104
+
105
+	private const INTERFACE_MAP = [
106
+		'php-http/async-client-implementation' => [
107
+			'Http\Client\HttpAsyncClient',
108
+		],
109
+		'php-http/client-implementation' => [
110
+			'Http\Client\HttpClient',
111
+		],
112
+		'psr/http-client-implementation' => [
113
+			'Psr\Http\Client\ClientInterface',
114
+		],
115
+		'psr/http-factory-implementation' => [
116
+			'Psr\Http\Message\RequestFactoryInterface',
117
+			'Psr\Http\Message\ResponseFactoryInterface',
118
+			'Psr\Http\Message\ServerRequestFactoryInterface',
119
+			'Psr\Http\Message\StreamFactoryInterface',
120
+			'Psr\Http\Message\UploadedFileFactoryInterface',
121
+			'Psr\Http\Message\UriFactoryInterface',
122
+		],
123
+	];
124
+
125
+	public static function getSubscribedEvents(): array
126
+	{
127
+		return [
128
+			ScriptEvents::PRE_AUTOLOAD_DUMP => 'preAutoloadDump',
129
+			ScriptEvents::POST_UPDATE_CMD => 'postUpdate',
130
+		];
131
+	}
132
+
133
+	public function activate(Composer $composer, IOInterface $io): void
134
+	{
135
+	}
136
+
137
+	public function deactivate(Composer $composer, IOInterface $io)
138
+	{
139
+	}
140
+
141
+	public function uninstall(Composer $composer, IOInterface $io)
142
+	{
143
+	}
144
+
145
+	public function postUpdate(Event $event)
146
+	{
147
+		$composer = $event->getComposer();
148
+		$repo = $composer->getRepositoryManager()->getLocalRepository();
149
+		$requires = [
150
+			$composer->getPackage()->getRequires(),
151
+			$composer->getPackage()->getDevRequires(),
152
+		];
153
+		$pinnedAbstractions = [];
154
+		$pinned = $composer->getPackage()->getExtra()['discovery'] ?? [];
155
+		foreach (self::INTERFACE_MAP as $abstraction => $interfaces) {
156
+			foreach (isset($pinned[$abstraction]) ? [] : $interfaces as $interface) {
157
+				if (!isset($pinned[$interface])) {
158
+					continue 2;
159
+				}
160
+			}
161
+			$pinnedAbstractions[$abstraction] = true;
162
+		}
163
+
164
+		$missingRequires = $this->getMissingRequires($repo, $requires, 'project' === $composer->getPackage()->getType(), $pinnedAbstractions);
165
+		$missingRequires = [
166
+			'require' => array_fill_keys(array_merge([], ...array_values($missingRequires[0])), '*'),
167
+			'require-dev' => array_fill_keys(array_merge([], ...array_values($missingRequires[1])), '*'),
168
+			'remove' => array_fill_keys(array_merge([], ...array_values($missingRequires[2])), '*'),
169
+		];
170
+
171
+		if (!$missingRequires = array_filter($missingRequires)) {
172
+			return;
173
+		}
174
+
175
+		$composerJsonContents = file_get_contents(Factory::getComposerFile());
176
+		$this->updateComposerJson($missingRequires, $composer->getConfig()->get('sort-packages'));
177
+
178
+		$installer = null;
179
+		// Find the composer installer, hack borrowed from symfony/flex
180
+		foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT) as $trace) {
181
+			if (isset($trace['object']) && $trace['object'] instanceof Installer) {
182
+				$installer = $trace['object'];
183
+				break;
184
+			}
185
+		}
186
+
187
+		if (!$installer) {
188
+			return;
189
+		}
190
+
191
+		$event->stopPropagation();
192
+
193
+		$dispatcher = $composer->getEventDispatcher();
194
+		$disableScripts = !method_exists($dispatcher, 'setRunScripts') || !((array) $dispatcher)["\0*\0runScripts"];
195
+		$composer = Factory::create($event->getIO(), null, false, $disableScripts);
196
+
197
+		/** @var Installer $installer */
198
+		$installer = clone $installer;
199
+		if (method_exists($installer, 'setAudit')) {
200
+			$trace['object']->setAudit(false);
201
+		}
202
+		// we need a clone of the installer to preserve its configuration state but with our own service objects
203
+		$installer->__construct(
204
+			$event->getIO(),
205
+			$composer->getConfig(),
206
+			$composer->getPackage(),
207
+			$composer->getDownloadManager(),
208
+			$composer->getRepositoryManager(),
209
+			$composer->getLocker(),
210
+			$composer->getInstallationManager(),
211
+			$composer->getEventDispatcher(),
212
+			$composer->getAutoloadGenerator()
213
+		);
214
+		if (method_exists($installer, 'setPlatformRequirementFilter')) {
215
+			$installer->setPlatformRequirementFilter(((array) $trace['object'])["\0*\0platformRequirementFilter"]);
216
+		}
217
+
218
+		if (0 !== $installer->run()) {
219
+			file_put_contents(Factory::getComposerFile(), $composerJsonContents);
220
+
221
+			return;
222
+		}
223
+
224
+		$versionSelector = new VersionSelector(ClassDiscovery::safeClassExists(RepositorySet::class) ? new RepositorySet() : new Pool());
225
+		$updateComposerJson = false;
226
+
227
+		foreach ($composer->getRepositoryManager()->getLocalRepository()->getPackages() as $package) {
228
+			foreach (['require', 'require-dev'] as $key) {
229
+				if (!isset($missingRequires[$key][$package->getName()])) {
230
+					continue;
231
+				}
232
+				$updateComposerJson = true;
233
+				$missingRequires[$key][$package->getName()] = $versionSelector->findRecommendedRequireVersion($package);
234
+			}
235
+		}
236
+
237
+		if ($updateComposerJson) {
238
+			$this->updateComposerJson($missingRequires, $composer->getConfig()->get('sort-packages'));
239
+			$this->updateComposerLock($composer, $event->getIO());
240
+		}
241
+	}
242
+
243
+	public function getMissingRequires(InstalledRepositoryInterface $repo, array $requires, bool $isProject, array $pinnedAbstractions): array
244
+	{
245
+		$allPackages = [];
246
+		$devPackages = method_exists($repo, 'getDevPackageNames') ? array_fill_keys($repo->getDevPackageNames(), true) : [];
247
+
248
+		// One must require "php-http/discovery"
249
+		// to opt-in for auto-installation of virtual package implementations
250
+		if (!isset($requires[0]['php-http/discovery'])) {
251
+			$requires = [[], []];
252
+		}
253
+
254
+		foreach ($repo->getPackages() as $package) {
255
+			$allPackages[$package->getName()] = true;
256
+
257
+			if (1 < \count($names = $package->getNames(false))) {
258
+				$allPackages += array_fill_keys($names, false);
259
+
260
+				if (isset($devPackages[$package->getName()])) {
261
+					$devPackages += $names;
262
+				}
263
+			}
264
+
265
+			if (isset($package->getRequires()['php-http/discovery'])) {
266
+				$requires[(int) isset($devPackages[$package->getName()])] += $package->getRequires();
267
+			}
268
+		}
269
+
270
+		$missingRequires = [[], [], []];
271
+		$versionParser = new VersionParser();
272
+
273
+		if (ClassDiscovery::safeClassExists(\Phalcon\Http\Message\RequestFactory::class, false)) {
274
+			$missingRequires[0]['psr/http-factory-implementation'] = [];
275
+			$missingRequires[1]['psr/http-factory-implementation'] = [];
276
+		}
277
+
278
+		foreach ($requires as $dev => $rules) {
279
+			$abstractions = [];
280
+			$rules = array_intersect_key(self::PROVIDE_RULES, $rules);
281
+
282
+			while ($rules) {
283
+				$abstraction = key($rules);
284
+
285
+				if (isset($pinnedAbstractions[$abstraction])) {
286
+					unset($rules[$abstraction]);
287
+					continue;
288
+				}
289
+
290
+				$abstractions[] = $abstraction;
291
+
292
+				foreach (array_shift($rules) as $candidate => $deps) {
293
+					[$candidate, $version] = explode(':', $candidate, 2) + [1 => null];
294
+
295
+					if (!isset($allPackages[$candidate])) {
296
+						continue;
297
+					}
298
+					if (null !== $version && !$repo->findPackage($candidate, $versionParser->parseConstraints($version))) {
299
+						continue;
300
+					}
301
+					if ($isProject && !$dev && isset($devPackages[$candidate])) {
302
+						$missingRequires[0][$abstraction] = [$candidate];
303
+						$missingRequires[2][$abstraction] = [$candidate];
304
+					} else {
305
+						$missingRequires[$dev][$abstraction] = [];
306
+					}
307
+
308
+					foreach ($deps as $dep) {
309
+						if (isset(self::PROVIDE_RULES[$dep])) {
310
+							$rules[$dep] = self::PROVIDE_RULES[$dep];
311
+						} elseif (!isset($allPackages[$dep])) {
312
+							$missingRequires[$dev][$abstraction][] = $dep;
313
+						} elseif ($isProject && !$dev && isset($devPackages[$dep])) {
314
+							$missingRequires[0][$abstraction][] = $dep;
315
+							$missingRequires[2][$abstraction][] = $dep;
316
+						}
317
+					}
318
+					break;
319
+				}
320
+			}
321
+
322
+			while ($abstractions) {
323
+				$abstraction = array_shift($abstractions);
324
+
325
+				if (isset($missingRequires[$dev][$abstraction])) {
326
+					continue;
327
+				}
328
+				$candidates = self::PROVIDE_RULES[$abstraction];
329
+
330
+				foreach ($candidates as $candidate => $deps) {
331
+					[$candidate, $version] = explode(':', $candidate, 2) + [1 => null];
332
+
333
+					if (null !== $version && !$repo->findPackage($candidate, $versionParser->parseConstraints($version))) {
334
+						continue;
335
+					}
336
+					if (isset($allPackages[$candidate]) && (!$isProject || $dev || !isset($devPackages[$candidate]))) {
337
+						continue 2;
338
+					}
339
+				}
340
+
341
+				foreach (array_intersect_key(self::STICKYNESS_RULES, $candidates) as $candidate => $stickyRule) {
342
+					[$stickyName, $stickyVersion] = explode(':', $stickyRule, 2) + [1 => null];
343
+					if (!isset($allPackages[$stickyName]) || ($isProject && !$dev && isset($devPackages[$stickyName]))) {
344
+						continue;
345
+					}
346
+					if (null !== $stickyVersion && !$repo->findPackage($stickyName, $versionParser->parseConstraints($stickyVersion))) {
347
+						continue;
348
+					}
349
+
350
+					$candidates = [$candidate => $candidates[$candidate]];
351
+					break;
352
+				}
353
+
354
+				$dep = key($candidates);
355
+				[$dep] = explode(':', $dep, 2);
356
+				$missingRequires[$dev][$abstraction] = [$dep];
357
+
358
+				if ($isProject && !$dev && isset($devPackages[$dep])) {
359
+					$missingRequires[2][$abstraction][] = $dep;
360
+				}
361
+			}
362
+		}
363
+
364
+		$missingRequires[1] = array_diff_key($missingRequires[1], $missingRequires[0]);
365
+
366
+		return $missingRequires;
367
+	}
368
+
369
+	public function preAutoloadDump(Event $event)
370
+	{
371
+		$filesystem = new Filesystem();
372
+		// Double realpath() on purpose, see https://bugs.php.net/72738
373
+		$vendorDir = $filesystem->normalizePath(realpath(realpath($event->getComposer()->getConfig()->get('vendor-dir'))));
374
+		$filesystem->ensureDirectoryExists($vendorDir.'/composer');
375
+		$pinned = $event->getComposer()->getPackage()->getExtra()['discovery'] ?? [];
376
+		$candidates = [];
377
+
378
+		$allInterfaces = array_merge(...array_values(self::INTERFACE_MAP));
379
+		foreach ($pinned as $abstraction => $class) {
380
+			if (isset(self::INTERFACE_MAP[$abstraction])) {
381
+				$interfaces = self::INTERFACE_MAP[$abstraction];
382
+			} elseif (false !== $k = array_search($abstraction, $allInterfaces, true)) {
383
+				$interfaces = [$allInterfaces[$k]];
384
+			} else {
385
+				throw new \UnexpectedValueException(sprintf('Invalid "extra.discovery" pinned in composer.json: "%s" is not one of ["%s"].', $abstraction, implode('", "', array_keys(self::INTERFACE_MAP))));
386
+			}
387
+
388
+			foreach ($interfaces as $interface) {
389
+				$candidates[] = sprintf("case %s: return [['class' => %s]];\n", var_export($interface, true), var_export($class, true));
390
+			}
391
+		}
392
+
393
+		$file = $vendorDir.'/composer/GeneratedDiscoveryStrategy.php';
394
+
395
+		if (!$candidates) {
396
+			if (file_exists($file)) {
397
+				unlink($file);
398
+			}
399
+
400
+			return;
401
+		}
402
+
403
+		$candidates = implode('            ', $candidates);
404
+		$code = <<<EOPHP
405 405
 <?php
406 406
 
407 407
 namespace OCA\FullTextSearch_Elasticsearch\Vendor\Http\Discovery\Strategy;
@@ -418,48 +418,48 @@  discard block
 block discarded – undo
418 418
 }
419 419
 
420 420
 EOPHP
421
-        ;
422
-
423
-        if (!file_exists($file) || $code !== file_get_contents($file)) {
424
-            file_put_contents($file, $code);
425
-        }
426
-
427
-        $rootPackage = $event->getComposer()->getPackage();
428
-        $autoload = $rootPackage->getAutoload();
429
-        $autoload['classmap'][] = $vendorDir.'/composer/GeneratedDiscoveryStrategy.php';
430
-        $rootPackage->setAutoload($autoload);
431
-    }
432
-
433
-    private function updateComposerJson(array $missingRequires, bool $sortPackages)
434
-    {
435
-        $file = Factory::getComposerFile();
436
-        $contents = file_get_contents($file);
437
-
438
-        $manipulator = new JsonManipulator($contents);
439
-
440
-        foreach ($missingRequires as $key => $packages) {
441
-            foreach ($packages as $package => $constraint) {
442
-                if ('remove' === $key) {
443
-                    $manipulator->removeSubNode('require-dev', $package);
444
-                } else {
445
-                    $manipulator->addLink($key, $package, $constraint, $sortPackages);
446
-                }
447
-            }
448
-        }
449
-
450
-        file_put_contents($file, $manipulator->getContents());
451
-    }
452
-
453
-    private function updateComposerLock(Composer $composer, IOInterface $io)
454
-    {
455
-        $lock = substr(Factory::getComposerFile(), 0, -4).'lock';
456
-        $composerJson = file_get_contents(Factory::getComposerFile());
457
-        $lockFile = new JsonFile($lock, null, $io);
458
-        $locker = ClassDiscovery::safeClassExists(RepositorySet::class)
459
-            ? new Locker($io, $lockFile, $composer->getInstallationManager(), $composerJson)
460
-            : new Locker($io, $lockFile, $composer->getRepositoryManager(), $composer->getInstallationManager(), $composerJson);
461
-        $lockData = $locker->getLockData();
462
-        $lockData['content-hash'] = Locker::getContentHash($composerJson);
463
-        $lockFile->write($lockData);
464
-    }
421
+		;
422
+
423
+		if (!file_exists($file) || $code !== file_get_contents($file)) {
424
+			file_put_contents($file, $code);
425
+		}
426
+
427
+		$rootPackage = $event->getComposer()->getPackage();
428
+		$autoload = $rootPackage->getAutoload();
429
+		$autoload['classmap'][] = $vendorDir.'/composer/GeneratedDiscoveryStrategy.php';
430
+		$rootPackage->setAutoload($autoload);
431
+	}
432
+
433
+	private function updateComposerJson(array $missingRequires, bool $sortPackages)
434
+	{
435
+		$file = Factory::getComposerFile();
436
+		$contents = file_get_contents($file);
437
+
438
+		$manipulator = new JsonManipulator($contents);
439
+
440
+		foreach ($missingRequires as $key => $packages) {
441
+			foreach ($packages as $package => $constraint) {
442
+				if ('remove' === $key) {
443
+					$manipulator->removeSubNode('require-dev', $package);
444
+				} else {
445
+					$manipulator->addLink($key, $package, $constraint, $sortPackages);
446
+				}
447
+			}
448
+		}
449
+
450
+		file_put_contents($file, $manipulator->getContents());
451
+	}
452
+
453
+	private function updateComposerLock(Composer $composer, IOInterface $io)
454
+	{
455
+		$lock = substr(Factory::getComposerFile(), 0, -4).'lock';
456
+		$composerJson = file_get_contents(Factory::getComposerFile());
457
+		$lockFile = new JsonFile($lock, null, $io);
458
+		$locker = ClassDiscovery::safeClassExists(RepositorySet::class)
459
+			? new Locker($io, $lockFile, $composer->getInstallationManager(), $composerJson)
460
+			: new Locker($io, $lockFile, $composer->getRepositoryManager(), $composer->getInstallationManager(), $composerJson);
461
+		$lockData = $locker->getLockData();
462
+		$lockData['content-hash'] = Locker::getContentHash($composerJson);
463
+		$lockFile->write($lockData);
464
+	}
465 465
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
         $event->stopPropagation();
192 192
 
193 193
         $dispatcher = $composer->getEventDispatcher();
194
-        $disableScripts = !method_exists($dispatcher, 'setRunScripts') || !((array) $dispatcher)["\0*\0runScripts"];
194
+        $disableScripts = !method_exists($dispatcher, 'setRunScripts') || !((array)$dispatcher)["\0*\0runScripts"];
195 195
         $composer = Factory::create($event->getIO(), null, false, $disableScripts);
196 196
 
197 197
         /** @var Installer $installer */
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
             $composer->getAutoloadGenerator()
213 213
         );
214 214
         if (method_exists($installer, 'setPlatformRequirementFilter')) {
215
-            $installer->setPlatformRequirementFilter(((array) $trace['object'])["\0*\0platformRequirementFilter"]);
215
+            $installer->setPlatformRequirementFilter(((array)$trace['object'])["\0*\0platformRequirementFilter"]);
216 216
         }
217 217
 
218 218
         if (0 !== $installer->run()) {
@@ -263,7 +263,7 @@  discard block
 block discarded – undo
263 263
             }
264 264
 
265 265
             if (isset($package->getRequires()['php-http/discovery'])) {
266
-                $requires[(int) isset($devPackages[$package->getName()])] += $package->getRequires();
266
+                $requires[(int)isset($devPackages[$package->getName()])] += $package->getRequires();
267 267
             }
268 268
         }
269 269
 
Please login to merge, or discard this patch.
lib/Vendor/Http/Discovery/ClassDiscovery.php 3 patches
Indentation   +235 added lines, -235 removed lines patch added patch discarded remove patch
@@ -17,239 +17,239 @@
 block discarded – undo
17 17
  */
18 18
 abstract class ClassDiscovery
19 19
 {
20
-    /**
21
-     * A list of strategies to find classes.
22
-     *
23
-     * @var DiscoveryStrategy[]
24
-     */
25
-    private static $strategies = [
26
-        Strategy\GeneratedDiscoveryStrategy::class,
27
-        Strategy\CommonClassesStrategy::class,
28
-        Strategy\CommonPsr17ClassesStrategy::class,
29
-        Strategy\PuliBetaStrategy::class,
30
-    ];
31
-
32
-    private static $deprecatedStrategies = [
33
-        Strategy\PuliBetaStrategy::class => true,
34
-    ];
35
-
36
-    /**
37
-     * Discovery cache to make the second time we use discovery faster.
38
-     *
39
-     * @var array
40
-     */
41
-    private static $cache = [];
42
-
43
-    /**
44
-     * Finds a class.
45
-     *
46
-     * @param string $type
47
-     *
48
-     * @return string|\Closure
49
-     *
50
-     * @throws DiscoveryFailedException
51
-     */
52
-    protected static function findOneByType($type)
53
-    {
54
-        // Look in the cache
55
-        if (null !== ($class = self::getFromCache($type))) {
56
-            return $class;
57
-        }
58
-
59
-        static $skipStrategy;
60
-        $skipStrategy ?? $skipStrategy = self::safeClassExists(Strategy\GeneratedDiscoveryStrategy::class) ? false : Strategy\GeneratedDiscoveryStrategy::class;
61
-
62
-        $exceptions = [];
63
-        foreach (self::$strategies as $strategy) {
64
-            if ($skipStrategy === $strategy) {
65
-                continue;
66
-            }
67
-
68
-            try {
69
-                $candidates = $strategy::getCandidates($type);
70
-            } catch (StrategyUnavailableException $e) {
71
-                if (!isset(self::$deprecatedStrategies[$strategy])) {
72
-                    $exceptions[] = $e;
73
-                }
74
-
75
-                continue;
76
-            }
77
-
78
-            foreach ($candidates as $candidate) {
79
-                if (isset($candidate['condition'])) {
80
-                    if (!self::evaluateCondition($candidate['condition'])) {
81
-                        continue;
82
-                    }
83
-                }
84
-
85
-                // save the result for later use
86
-                self::storeInCache($type, $candidate);
87
-
88
-                return $candidate['class'];
89
-            }
90
-
91
-            $exceptions[] = new NoCandidateFoundException($strategy, $candidates);
92
-        }
93
-
94
-        throw DiscoveryFailedException::create($exceptions);
95
-    }
96
-
97
-    /**
98
-     * Get a value from cache.
99
-     *
100
-     * @param string $type
101
-     *
102
-     * @return string|null
103
-     */
104
-    private static function getFromCache($type)
105
-    {
106
-        if (!isset(self::$cache[$type])) {
107
-            return;
108
-        }
109
-
110
-        $candidate = self::$cache[$type];
111
-        if (isset($candidate['condition'])) {
112
-            if (!self::evaluateCondition($candidate['condition'])) {
113
-                return;
114
-            }
115
-        }
116
-
117
-        return $candidate['class'];
118
-    }
119
-
120
-    /**
121
-     * Store a value in cache.
122
-     *
123
-     * @param string $type
124
-     * @param string $class
125
-     */
126
-    private static function storeInCache($type, $class)
127
-    {
128
-        self::$cache[$type] = $class;
129
-    }
130
-
131
-    /**
132
-     * Set new strategies and clear the cache.
133
-     *
134
-     * @param string[] $strategies list of fully qualified class names that implement DiscoveryStrategy
135
-     */
136
-    public static function setStrategies(array $strategies)
137
-    {
138
-        self::$strategies = $strategies;
139
-        self::clearCache();
140
-    }
141
-
142
-    /**
143
-     * Returns the currently configured discovery strategies as fully qualified class names.
144
-     *
145
-     * @return string[]
146
-     */
147
-    public static function getStrategies(): iterable
148
-    {
149
-        return self::$strategies;
150
-    }
151
-
152
-    /**
153
-     * Append a strategy at the end of the strategy queue.
154
-     *
155
-     * @param string $strategy Fully qualified class name of a DiscoveryStrategy
156
-     */
157
-    public static function appendStrategy($strategy)
158
-    {
159
-        self::$strategies[] = $strategy;
160
-        self::clearCache();
161
-    }
162
-
163
-    /**
164
-     * Prepend a strategy at the beginning of the strategy queue.
165
-     *
166
-     * @param string $strategy Fully qualified class name to a DiscoveryStrategy
167
-     */
168
-    public static function prependStrategy($strategy)
169
-    {
170
-        array_unshift(self::$strategies, $strategy);
171
-        self::clearCache();
172
-    }
173
-
174
-    public static function clearCache()
175
-    {
176
-        self::$cache = [];
177
-    }
178
-
179
-    /**
180
-     * Evaluates conditions to boolean.
181
-     *
182
-     * @return bool
183
-     */
184
-    protected static function evaluateCondition($condition)
185
-    {
186
-        if (is_string($condition)) {
187
-            // Should be extended for functions, extensions???
188
-            return self::safeClassExists($condition);
189
-        }
190
-        if (is_callable($condition)) {
191
-            return (bool) $condition();
192
-        }
193
-        if (is_bool($condition)) {
194
-            return $condition;
195
-        }
196
-        if (is_array($condition)) {
197
-            foreach ($condition as $c) {
198
-                if (false === static::evaluateCondition($c)) {
199
-                    // Immediately stop execution if the condition is false
200
-                    return false;
201
-                }
202
-            }
203
-
204
-            return true;
205
-        }
206
-
207
-        return false;
208
-    }
209
-
210
-    /**
211
-     * Get an instance of the $class.
212
-     *
213
-     * @param string|\Closure $class a FQCN of a class or a closure that instantiate the class
214
-     *
215
-     * @return object
216
-     *
217
-     * @throws ClassInstantiationFailedException
218
-     */
219
-    protected static function instantiateClass($class)
220
-    {
221
-        try {
222
-            if (is_string($class)) {
223
-                return new $class();
224
-            }
225
-
226
-            if (is_callable($class)) {
227
-                return $class();
228
-            }
229
-        } catch (\Exception $e) {
230
-            throw new ClassInstantiationFailedException('Unexpected exception when instantiating class.', 0, $e);
231
-        }
232
-
233
-        throw new ClassInstantiationFailedException('Could not instantiate class because parameter is neither a callable nor a string');
234
-    }
235
-
236
-    /**
237
-     * We need a "safe" version of PHP's "class_exists" because Magento has a bug
238
-     * (or they call it a "feature"). Magento is throwing an exception if you do class_exists()
239
-     * on a class that ends with "Factory" and if that file does not exits.
240
-     *
241
-     * This function catches all potential exceptions and makes sure to always return a boolean.
242
-     *
243
-     * @param string $class
244
-     *
245
-     * @return bool
246
-     */
247
-    public static function safeClassExists($class)
248
-    {
249
-        try {
250
-            return class_exists($class) || interface_exists($class);
251
-        } catch (\Exception $e) {
252
-            return false;
253
-        }
254
-    }
20
+	/**
21
+	 * A list of strategies to find classes.
22
+	 *
23
+	 * @var DiscoveryStrategy[]
24
+	 */
25
+	private static $strategies = [
26
+		Strategy\GeneratedDiscoveryStrategy::class,
27
+		Strategy\CommonClassesStrategy::class,
28
+		Strategy\CommonPsr17ClassesStrategy::class,
29
+		Strategy\PuliBetaStrategy::class,
30
+	];
31
+
32
+	private static $deprecatedStrategies = [
33
+		Strategy\PuliBetaStrategy::class => true,
34
+	];
35
+
36
+	/**
37
+	 * Discovery cache to make the second time we use discovery faster.
38
+	 *
39
+	 * @var array
40
+	 */
41
+	private static $cache = [];
42
+
43
+	/**
44
+	 * Finds a class.
45
+	 *
46
+	 * @param string $type
47
+	 *
48
+	 * @return string|\Closure
49
+	 *
50
+	 * @throws DiscoveryFailedException
51
+	 */
52
+	protected static function findOneByType($type)
53
+	{
54
+		// Look in the cache
55
+		if (null !== ($class = self::getFromCache($type))) {
56
+			return $class;
57
+		}
58
+
59
+		static $skipStrategy;
60
+		$skipStrategy ?? $skipStrategy = self::safeClassExists(Strategy\GeneratedDiscoveryStrategy::class) ? false : Strategy\GeneratedDiscoveryStrategy::class;
61
+
62
+		$exceptions = [];
63
+		foreach (self::$strategies as $strategy) {
64
+			if ($skipStrategy === $strategy) {
65
+				continue;
66
+			}
67
+
68
+			try {
69
+				$candidates = $strategy::getCandidates($type);
70
+			} catch (StrategyUnavailableException $e) {
71
+				if (!isset(self::$deprecatedStrategies[$strategy])) {
72
+					$exceptions[] = $e;
73
+				}
74
+
75
+				continue;
76
+			}
77
+
78
+			foreach ($candidates as $candidate) {
79
+				if (isset($candidate['condition'])) {
80
+					if (!self::evaluateCondition($candidate['condition'])) {
81
+						continue;
82
+					}
83
+				}
84
+
85
+				// save the result for later use
86
+				self::storeInCache($type, $candidate);
87
+
88
+				return $candidate['class'];
89
+			}
90
+
91
+			$exceptions[] = new NoCandidateFoundException($strategy, $candidates);
92
+		}
93
+
94
+		throw DiscoveryFailedException::create($exceptions);
95
+	}
96
+
97
+	/**
98
+	 * Get a value from cache.
99
+	 *
100
+	 * @param string $type
101
+	 *
102
+	 * @return string|null
103
+	 */
104
+	private static function getFromCache($type)
105
+	{
106
+		if (!isset(self::$cache[$type])) {
107
+			return;
108
+		}
109
+
110
+		$candidate = self::$cache[$type];
111
+		if (isset($candidate['condition'])) {
112
+			if (!self::evaluateCondition($candidate['condition'])) {
113
+				return;
114
+			}
115
+		}
116
+
117
+		return $candidate['class'];
118
+	}
119
+
120
+	/**
121
+	 * Store a value in cache.
122
+	 *
123
+	 * @param string $type
124
+	 * @param string $class
125
+	 */
126
+	private static function storeInCache($type, $class)
127
+	{
128
+		self::$cache[$type] = $class;
129
+	}
130
+
131
+	/**
132
+	 * Set new strategies and clear the cache.
133
+	 *
134
+	 * @param string[] $strategies list of fully qualified class names that implement DiscoveryStrategy
135
+	 */
136
+	public static function setStrategies(array $strategies)
137
+	{
138
+		self::$strategies = $strategies;
139
+		self::clearCache();
140
+	}
141
+
142
+	/**
143
+	 * Returns the currently configured discovery strategies as fully qualified class names.
144
+	 *
145
+	 * @return string[]
146
+	 */
147
+	public static function getStrategies(): iterable
148
+	{
149
+		return self::$strategies;
150
+	}
151
+
152
+	/**
153
+	 * Append a strategy at the end of the strategy queue.
154
+	 *
155
+	 * @param string $strategy Fully qualified class name of a DiscoveryStrategy
156
+	 */
157
+	public static function appendStrategy($strategy)
158
+	{
159
+		self::$strategies[] = $strategy;
160
+		self::clearCache();
161
+	}
162
+
163
+	/**
164
+	 * Prepend a strategy at the beginning of the strategy queue.
165
+	 *
166
+	 * @param string $strategy Fully qualified class name to a DiscoveryStrategy
167
+	 */
168
+	public static function prependStrategy($strategy)
169
+	{
170
+		array_unshift(self::$strategies, $strategy);
171
+		self::clearCache();
172
+	}
173
+
174
+	public static function clearCache()
175
+	{
176
+		self::$cache = [];
177
+	}
178
+
179
+	/**
180
+	 * Evaluates conditions to boolean.
181
+	 *
182
+	 * @return bool
183
+	 */
184
+	protected static function evaluateCondition($condition)
185
+	{
186
+		if (is_string($condition)) {
187
+			// Should be extended for functions, extensions???
188
+			return self::safeClassExists($condition);
189
+		}
190
+		if (is_callable($condition)) {
191
+			return (bool) $condition();
192
+		}
193
+		if (is_bool($condition)) {
194
+			return $condition;
195
+		}
196
+		if (is_array($condition)) {
197
+			foreach ($condition as $c) {
198
+				if (false === static::evaluateCondition($c)) {
199
+					// Immediately stop execution if the condition is false
200
+					return false;
201
+				}
202
+			}
203
+
204
+			return true;
205
+		}
206
+
207
+		return false;
208
+	}
209
+
210
+	/**
211
+	 * Get an instance of the $class.
212
+	 *
213
+	 * @param string|\Closure $class a FQCN of a class or a closure that instantiate the class
214
+	 *
215
+	 * @return object
216
+	 *
217
+	 * @throws ClassInstantiationFailedException
218
+	 */
219
+	protected static function instantiateClass($class)
220
+	{
221
+		try {
222
+			if (is_string($class)) {
223
+				return new $class();
224
+			}
225
+
226
+			if (is_callable($class)) {
227
+				return $class();
228
+			}
229
+		} catch (\Exception $e) {
230
+			throw new ClassInstantiationFailedException('Unexpected exception when instantiating class.', 0, $e);
231
+		}
232
+
233
+		throw new ClassInstantiationFailedException('Could not instantiate class because parameter is neither a callable nor a string');
234
+	}
235
+
236
+	/**
237
+	 * We need a "safe" version of PHP's "class_exists" because Magento has a bug
238
+	 * (or they call it a "feature"). Magento is throwing an exception if you do class_exists()
239
+	 * on a class that ends with "Factory" and if that file does not exits.
240
+	 *
241
+	 * This function catches all potential exceptions and makes sure to always return a boolean.
242
+	 *
243
+	 * @param string $class
244
+	 *
245
+	 * @return bool
246
+	 */
247
+	public static function safeClassExists($class)
248
+	{
249
+		try {
250
+			return class_exists($class) || interface_exists($class);
251
+		} catch (\Exception $e) {
252
+			return false;
253
+		}
254
+	}
255 255
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -188,7 +188,7 @@
 block discarded – undo
188 188
             return self::safeClassExists($condition);
189 189
         }
190 190
         if (is_callable($condition)) {
191
-            return (bool) $condition();
191
+            return (bool)$condition();
192 192
         }
193 193
         if (is_bool($condition)) {
194 194
             return $condition;
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -15,8 +15,7 @@
 block discarded – undo
15 15
  * @author Márk Sági-Kazár <[email protected]>
16 16
  * @author Tobias Nyholm <[email protected]>
17 17
  */
18
-abstract class ClassDiscovery
19
-{
18
+abstract class ClassDiscovery {
20 19
     /**
21 20
      * A list of strategies to find classes.
22 21
      *
Please login to merge, or discard this patch.
lib/Vendor/Http/Discovery/Psr17Factory.php 1 patch
Indentation   +259 added lines, -259 removed lines patch added patch discarded remove patch
@@ -41,263 +41,263 @@
 block discarded – undo
41 41
  */
42 42
 class Psr17Factory implements RequestFactoryInterface, ResponseFactoryInterface, ServerRequestFactoryInterface, StreamFactoryInterface, UploadedFileFactoryInterface, UriFactoryInterface
43 43
 {
44
-    private $requestFactory;
45
-    private $responseFactory;
46
-    private $serverRequestFactory;
47
-    private $streamFactory;
48
-    private $uploadedFileFactory;
49
-    private $uriFactory;
50
-
51
-    public function __construct(
52
-        ?RequestFactoryInterface $requestFactory = null,
53
-        ?ResponseFactoryInterface $responseFactory = null,
54
-        ?ServerRequestFactoryInterface $serverRequestFactory = null,
55
-        ?StreamFactoryInterface $streamFactory = null,
56
-        ?UploadedFileFactoryInterface $uploadedFileFactory = null,
57
-        ?UriFactoryInterface $uriFactory = null
58
-    ) {
59
-        $this->requestFactory = $requestFactory;
60
-        $this->responseFactory = $responseFactory;
61
-        $this->serverRequestFactory = $serverRequestFactory;
62
-        $this->streamFactory = $streamFactory;
63
-        $this->uploadedFileFactory = $uploadedFileFactory;
64
-        $this->uriFactory = $uriFactory;
65
-
66
-        $this->setFactory($requestFactory);
67
-        $this->setFactory($responseFactory);
68
-        $this->setFactory($serverRequestFactory);
69
-        $this->setFactory($streamFactory);
70
-        $this->setFactory($uploadedFileFactory);
71
-        $this->setFactory($uriFactory);
72
-    }
73
-
74
-    /**
75
-     * @param UriInterface|string $uri
76
-     */
77
-    public function createRequest(string $method, $uri): RequestInterface
78
-    {
79
-        $factory = $this->requestFactory ?? $this->setFactory(Psr17FactoryDiscovery::findRequestFactory());
80
-
81
-        return $factory->createRequest(...\func_get_args());
82
-    }
83
-
84
-    public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
85
-    {
86
-        $factory = $this->responseFactory ?? $this->setFactory(Psr17FactoryDiscovery::findResponseFactory());
87
-
88
-        return $factory->createResponse(...\func_get_args());
89
-    }
90
-
91
-    /**
92
-     * @param UriInterface|string $uri
93
-     */
94
-    public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
95
-    {
96
-        $factory = $this->serverRequestFactory ?? $this->setFactory(Psr17FactoryDiscovery::findServerRequestFactory());
97
-
98
-        return $factory->createServerRequest(...\func_get_args());
99
-    }
100
-
101
-    public function createServerRequestFromGlobals(?array $server = null, ?array $get = null, ?array $post = null, ?array $cookie = null, ?array $files = null, ?StreamInterface $body = null): ServerRequestInterface
102
-    {
103
-        $server = $server ?? $_SERVER;
104
-        $request = $this->createServerRequest($server['REQUEST_METHOD'] ?? 'GET', $this->createUriFromGlobals($server), $server);
105
-
106
-        return $this->buildServerRequestFromGlobals($request, $server, $files ?? $_FILES)
107
-            ->withQueryParams($get ?? $_GET)
108
-            ->withParsedBody($post ?? $_POST)
109
-            ->withCookieParams($cookie ?? $_COOKIE)
110
-            ->withBody($body ?? $this->createStreamFromFile('php://input', 'r+'));
111
-    }
112
-
113
-    public function createStream(string $content = ''): StreamInterface
114
-    {
115
-        $factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
116
-
117
-        return $factory->createStream($content);
118
-    }
119
-
120
-    public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface
121
-    {
122
-        $factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
123
-
124
-        return $factory->createStreamFromFile($filename, $mode);
125
-    }
126
-
127
-    /**
128
-     * @param resource $resource
129
-     */
130
-    public function createStreamFromResource($resource): StreamInterface
131
-    {
132
-        $factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
133
-
134
-        return $factory->createStreamFromResource($resource);
135
-    }
136
-
137
-    public function createUploadedFile(StreamInterface $stream, ?int $size = null, int $error = \UPLOAD_ERR_OK, ?string $clientFilename = null, ?string $clientMediaType = null): UploadedFileInterface
138
-    {
139
-        $factory = $this->uploadedFileFactory ?? $this->setFactory(Psr17FactoryDiscovery::findUploadedFileFactory());
140
-
141
-        return $factory->createUploadedFile(...\func_get_args());
142
-    }
143
-
144
-    public function createUri(string $uri = ''): UriInterface
145
-    {
146
-        $factory = $this->uriFactory ?? $this->setFactory(Psr17FactoryDiscovery::findUriFactory());
147
-
148
-        return $factory->createUri(...\func_get_args());
149
-    }
150
-
151
-    public function createUriFromGlobals(?array $server = null): UriInterface
152
-    {
153
-        return $this->buildUriFromGlobals($this->createUri(''), $server ?? $_SERVER);
154
-    }
155
-
156
-    private function setFactory($factory)
157
-    {
158
-        if (!$this->requestFactory && $factory instanceof RequestFactoryInterface) {
159
-            $this->requestFactory = $factory;
160
-        }
161
-        if (!$this->responseFactory && $factory instanceof ResponseFactoryInterface) {
162
-            $this->responseFactory = $factory;
163
-        }
164
-        if (!$this->serverRequestFactory && $factory instanceof ServerRequestFactoryInterface) {
165
-            $this->serverRequestFactory = $factory;
166
-        }
167
-        if (!$this->streamFactory && $factory instanceof StreamFactoryInterface) {
168
-            $this->streamFactory = $factory;
169
-        }
170
-        if (!$this->uploadedFileFactory && $factory instanceof UploadedFileFactoryInterface) {
171
-            $this->uploadedFileFactory = $factory;
172
-        }
173
-        if (!$this->uriFactory && $factory instanceof UriFactoryInterface) {
174
-            $this->uriFactory = $factory;
175
-        }
176
-
177
-        return $factory;
178
-    }
179
-
180
-    private function buildServerRequestFromGlobals(ServerRequestInterface $request, array $server, array $files): ServerRequestInterface
181
-    {
182
-        $request = $request
183
-            ->withProtocolVersion(isset($server['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $server['SERVER_PROTOCOL']) : '1.1')
184
-            ->withUploadedFiles($this->normalizeFiles($files));
185
-
186
-        $headers = [];
187
-        foreach ($server as $k => $v) {
188
-            if (0 === strpos($k, 'HTTP_')) {
189
-                $k = substr($k, 5);
190
-            } elseif (!\in_array($k, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) {
191
-                continue;
192
-            }
193
-            $k = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $k))));
194
-
195
-            $headers[$k] = $v;
196
-        }
197
-
198
-        if (!isset($headers['Authorization'])) {
199
-            if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
200
-                $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
201
-            } elseif (isset($_SERVER['PHP_AUTH_USER'])) {
202
-                $headers['Authorization'] = 'Basic '.base64_encode($_SERVER['PHP_AUTH_USER'].':'.($_SERVER['PHP_AUTH_PW'] ?? ''));
203
-            } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
204
-                $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
205
-            }
206
-        }
207
-
208
-        foreach ($headers as $k => $v) {
209
-            try {
210
-                $request = $request->withHeader($k, $v);
211
-            } catch (\InvalidArgumentException $e) {
212
-                // ignore invalid headers
213
-            }
214
-        }
215
-
216
-        return $request;
217
-    }
218
-
219
-    private function buildUriFromGlobals(UriInterface $uri, array $server): UriInterface
220
-    {
221
-        $uri = $uri->withScheme(!empty($server['HTTPS']) && 'off' !== strtolower($server['HTTPS']) ? 'https' : 'http');
222
-
223
-        $hasPort = false;
224
-        if (isset($server['HTTP_HOST'])) {
225
-            $parts = parse_url('http://'.$server['HTTP_HOST']);
226
-
227
-            $uri = $uri->withHost($parts['host'] ?? 'localhost');
228
-
229
-            if ($parts['port'] ?? false) {
230
-                $hasPort = true;
231
-                $uri = $uri->withPort($parts['port']);
232
-            }
233
-        } else {
234
-            $uri = $uri->withHost($server['SERVER_NAME'] ?? $server['SERVER_ADDR'] ?? 'localhost');
235
-        }
236
-
237
-        if (!$hasPort && isset($server['SERVER_PORT'])) {
238
-            $uri = $uri->withPort($server['SERVER_PORT']);
239
-        }
240
-
241
-        $hasQuery = false;
242
-        if (isset($server['REQUEST_URI'])) {
243
-            $requestUriParts = explode('?', $server['REQUEST_URI'], 2);
244
-            $uri = $uri->withPath($requestUriParts[0]);
245
-            if (isset($requestUriParts[1])) {
246
-                $hasQuery = true;
247
-                $uri = $uri->withQuery($requestUriParts[1]);
248
-            }
249
-        }
250
-
251
-        if (!$hasQuery && isset($server['QUERY_STRING'])) {
252
-            $uri = $uri->withQuery($server['QUERY_STRING']);
253
-        }
254
-
255
-        return $uri;
256
-    }
257
-
258
-    private function normalizeFiles(array $files): array
259
-    {
260
-        foreach ($files as $k => $v) {
261
-            if ($v instanceof UploadedFileInterface) {
262
-                continue;
263
-            }
264
-            if (!\is_array($v)) {
265
-                unset($files[$k]);
266
-            } elseif (!isset($v['tmp_name'])) {
267
-                $files[$k] = $this->normalizeFiles($v);
268
-            } else {
269
-                $files[$k] = $this->createUploadedFileFromSpec($v);
270
-            }
271
-        }
272
-
273
-        return $files;
274
-    }
275
-
276
-    /**
277
-     * Create and return an UploadedFile instance from a $_FILES specification.
278
-     *
279
-     * @param array $value $_FILES struct
280
-     *
281
-     * @return UploadedFileInterface|UploadedFileInterface[]
282
-     */
283
-    private function createUploadedFileFromSpec(array $value)
284
-    {
285
-        if (!is_array($tmpName = $value['tmp_name'])) {
286
-            $file = is_file($tmpName) ? $this->createStreamFromFile($tmpName, 'r') : $this->createStream();
287
-
288
-            return $this->createUploadedFile($file, $value['size'], $value['error'], $value['name'], $value['type']);
289
-        }
290
-
291
-        foreach ($tmpName as $k => $v) {
292
-            $tmpName[$k] = $this->createUploadedFileFromSpec([
293
-                'tmp_name' => $v,
294
-                'size' => $value['size'][$k] ?? null,
295
-                'error' => $value['error'][$k] ?? null,
296
-                'name' => $value['name'][$k] ?? null,
297
-                'type' => $value['type'][$k] ?? null,
298
-            ]);
299
-        }
300
-
301
-        return $tmpName;
302
-    }
44
+	private $requestFactory;
45
+	private $responseFactory;
46
+	private $serverRequestFactory;
47
+	private $streamFactory;
48
+	private $uploadedFileFactory;
49
+	private $uriFactory;
50
+
51
+	public function __construct(
52
+		?RequestFactoryInterface $requestFactory = null,
53
+		?ResponseFactoryInterface $responseFactory = null,
54
+		?ServerRequestFactoryInterface $serverRequestFactory = null,
55
+		?StreamFactoryInterface $streamFactory = null,
56
+		?UploadedFileFactoryInterface $uploadedFileFactory = null,
57
+		?UriFactoryInterface $uriFactory = null
58
+	) {
59
+		$this->requestFactory = $requestFactory;
60
+		$this->responseFactory = $responseFactory;
61
+		$this->serverRequestFactory = $serverRequestFactory;
62
+		$this->streamFactory = $streamFactory;
63
+		$this->uploadedFileFactory = $uploadedFileFactory;
64
+		$this->uriFactory = $uriFactory;
65
+
66
+		$this->setFactory($requestFactory);
67
+		$this->setFactory($responseFactory);
68
+		$this->setFactory($serverRequestFactory);
69
+		$this->setFactory($streamFactory);
70
+		$this->setFactory($uploadedFileFactory);
71
+		$this->setFactory($uriFactory);
72
+	}
73
+
74
+	/**
75
+	 * @param UriInterface|string $uri
76
+	 */
77
+	public function createRequest(string $method, $uri): RequestInterface
78
+	{
79
+		$factory = $this->requestFactory ?? $this->setFactory(Psr17FactoryDiscovery::findRequestFactory());
80
+
81
+		return $factory->createRequest(...\func_get_args());
82
+	}
83
+
84
+	public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
85
+	{
86
+		$factory = $this->responseFactory ?? $this->setFactory(Psr17FactoryDiscovery::findResponseFactory());
87
+
88
+		return $factory->createResponse(...\func_get_args());
89
+	}
90
+
91
+	/**
92
+	 * @param UriInterface|string $uri
93
+	 */
94
+	public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
95
+	{
96
+		$factory = $this->serverRequestFactory ?? $this->setFactory(Psr17FactoryDiscovery::findServerRequestFactory());
97
+
98
+		return $factory->createServerRequest(...\func_get_args());
99
+	}
100
+
101
+	public function createServerRequestFromGlobals(?array $server = null, ?array $get = null, ?array $post = null, ?array $cookie = null, ?array $files = null, ?StreamInterface $body = null): ServerRequestInterface
102
+	{
103
+		$server = $server ?? $_SERVER;
104
+		$request = $this->createServerRequest($server['REQUEST_METHOD'] ?? 'GET', $this->createUriFromGlobals($server), $server);
105
+
106
+		return $this->buildServerRequestFromGlobals($request, $server, $files ?? $_FILES)
107
+			->withQueryParams($get ?? $_GET)
108
+			->withParsedBody($post ?? $_POST)
109
+			->withCookieParams($cookie ?? $_COOKIE)
110
+			->withBody($body ?? $this->createStreamFromFile('php://input', 'r+'));
111
+	}
112
+
113
+	public function createStream(string $content = ''): StreamInterface
114
+	{
115
+		$factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
116
+
117
+		return $factory->createStream($content);
118
+	}
119
+
120
+	public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface
121
+	{
122
+		$factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
123
+
124
+		return $factory->createStreamFromFile($filename, $mode);
125
+	}
126
+
127
+	/**
128
+	 * @param resource $resource
129
+	 */
130
+	public function createStreamFromResource($resource): StreamInterface
131
+	{
132
+		$factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
133
+
134
+		return $factory->createStreamFromResource($resource);
135
+	}
136
+
137
+	public function createUploadedFile(StreamInterface $stream, ?int $size = null, int $error = \UPLOAD_ERR_OK, ?string $clientFilename = null, ?string $clientMediaType = null): UploadedFileInterface
138
+	{
139
+		$factory = $this->uploadedFileFactory ?? $this->setFactory(Psr17FactoryDiscovery::findUploadedFileFactory());
140
+
141
+		return $factory->createUploadedFile(...\func_get_args());
142
+	}
143
+
144
+	public function createUri(string $uri = ''): UriInterface
145
+	{
146
+		$factory = $this->uriFactory ?? $this->setFactory(Psr17FactoryDiscovery::findUriFactory());
147
+
148
+		return $factory->createUri(...\func_get_args());
149
+	}
150
+
151
+	public function createUriFromGlobals(?array $server = null): UriInterface
152
+	{
153
+		return $this->buildUriFromGlobals($this->createUri(''), $server ?? $_SERVER);
154
+	}
155
+
156
+	private function setFactory($factory)
157
+	{
158
+		if (!$this->requestFactory && $factory instanceof RequestFactoryInterface) {
159
+			$this->requestFactory = $factory;
160
+		}
161
+		if (!$this->responseFactory && $factory instanceof ResponseFactoryInterface) {
162
+			$this->responseFactory = $factory;
163
+		}
164
+		if (!$this->serverRequestFactory && $factory instanceof ServerRequestFactoryInterface) {
165
+			$this->serverRequestFactory = $factory;
166
+		}
167
+		if (!$this->streamFactory && $factory instanceof StreamFactoryInterface) {
168
+			$this->streamFactory = $factory;
169
+		}
170
+		if (!$this->uploadedFileFactory && $factory instanceof UploadedFileFactoryInterface) {
171
+			$this->uploadedFileFactory = $factory;
172
+		}
173
+		if (!$this->uriFactory && $factory instanceof UriFactoryInterface) {
174
+			$this->uriFactory = $factory;
175
+		}
176
+
177
+		return $factory;
178
+	}
179
+
180
+	private function buildServerRequestFromGlobals(ServerRequestInterface $request, array $server, array $files): ServerRequestInterface
181
+	{
182
+		$request = $request
183
+			->withProtocolVersion(isset($server['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $server['SERVER_PROTOCOL']) : '1.1')
184
+			->withUploadedFiles($this->normalizeFiles($files));
185
+
186
+		$headers = [];
187
+		foreach ($server as $k => $v) {
188
+			if (0 === strpos($k, 'HTTP_')) {
189
+				$k = substr($k, 5);
190
+			} elseif (!\in_array($k, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) {
191
+				continue;
192
+			}
193
+			$k = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $k))));
194
+
195
+			$headers[$k] = $v;
196
+		}
197
+
198
+		if (!isset($headers['Authorization'])) {
199
+			if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
200
+				$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
201
+			} elseif (isset($_SERVER['PHP_AUTH_USER'])) {
202
+				$headers['Authorization'] = 'Basic '.base64_encode($_SERVER['PHP_AUTH_USER'].':'.($_SERVER['PHP_AUTH_PW'] ?? ''));
203
+			} elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
204
+				$headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
205
+			}
206
+		}
207
+
208
+		foreach ($headers as $k => $v) {
209
+			try {
210
+				$request = $request->withHeader($k, $v);
211
+			} catch (\InvalidArgumentException $e) {
212
+				// ignore invalid headers
213
+			}
214
+		}
215
+
216
+		return $request;
217
+	}
218
+
219
+	private function buildUriFromGlobals(UriInterface $uri, array $server): UriInterface
220
+	{
221
+		$uri = $uri->withScheme(!empty($server['HTTPS']) && 'off' !== strtolower($server['HTTPS']) ? 'https' : 'http');
222
+
223
+		$hasPort = false;
224
+		if (isset($server['HTTP_HOST'])) {
225
+			$parts = parse_url('http://'.$server['HTTP_HOST']);
226
+
227
+			$uri = $uri->withHost($parts['host'] ?? 'localhost');
228
+
229
+			if ($parts['port'] ?? false) {
230
+				$hasPort = true;
231
+				$uri = $uri->withPort($parts['port']);
232
+			}
233
+		} else {
234
+			$uri = $uri->withHost($server['SERVER_NAME'] ?? $server['SERVER_ADDR'] ?? 'localhost');
235
+		}
236
+
237
+		if (!$hasPort && isset($server['SERVER_PORT'])) {
238
+			$uri = $uri->withPort($server['SERVER_PORT']);
239
+		}
240
+
241
+		$hasQuery = false;
242
+		if (isset($server['REQUEST_URI'])) {
243
+			$requestUriParts = explode('?', $server['REQUEST_URI'], 2);
244
+			$uri = $uri->withPath($requestUriParts[0]);
245
+			if (isset($requestUriParts[1])) {
246
+				$hasQuery = true;
247
+				$uri = $uri->withQuery($requestUriParts[1]);
248
+			}
249
+		}
250
+
251
+		if (!$hasQuery && isset($server['QUERY_STRING'])) {
252
+			$uri = $uri->withQuery($server['QUERY_STRING']);
253
+		}
254
+
255
+		return $uri;
256
+	}
257
+
258
+	private function normalizeFiles(array $files): array
259
+	{
260
+		foreach ($files as $k => $v) {
261
+			if ($v instanceof UploadedFileInterface) {
262
+				continue;
263
+			}
264
+			if (!\is_array($v)) {
265
+				unset($files[$k]);
266
+			} elseif (!isset($v['tmp_name'])) {
267
+				$files[$k] = $this->normalizeFiles($v);
268
+			} else {
269
+				$files[$k] = $this->createUploadedFileFromSpec($v);
270
+			}
271
+		}
272
+
273
+		return $files;
274
+	}
275
+
276
+	/**
277
+	 * Create and return an UploadedFile instance from a $_FILES specification.
278
+	 *
279
+	 * @param array $value $_FILES struct
280
+	 *
281
+	 * @return UploadedFileInterface|UploadedFileInterface[]
282
+	 */
283
+	private function createUploadedFileFromSpec(array $value)
284
+	{
285
+		if (!is_array($tmpName = $value['tmp_name'])) {
286
+			$file = is_file($tmpName) ? $this->createStreamFromFile($tmpName, 'r') : $this->createStream();
287
+
288
+			return $this->createUploadedFile($file, $value['size'], $value['error'], $value['name'], $value['type']);
289
+		}
290
+
291
+		foreach ($tmpName as $k => $v) {
292
+			$tmpName[$k] = $this->createUploadedFileFromSpec([
293
+				'tmp_name' => $v,
294
+				'size' => $value['size'][$k] ?? null,
295
+				'error' => $value['error'][$k] ?? null,
296
+				'name' => $value['name'][$k] ?? null,
297
+				'type' => $value['type'][$k] ?? null,
298
+			]);
299
+		}
300
+
301
+		return $tmpName;
302
+	}
303 303
 }
Please login to merge, or discard this patch.
lib/Vendor/Http/Discovery/HttpClientDiscovery.php 2 patches
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -14,21 +14,21 @@
 block discarded – undo
14 14
  */
15 15
 final class HttpClientDiscovery extends ClassDiscovery
16 16
 {
17
-    /**
18
-     * Finds an HTTP Client.
19
-     *
20
-     * @return HttpClient
21
-     *
22
-     * @throws Exception\NotFoundException
23
-     */
24
-    public static function find()
25
-    {
26
-        try {
27
-            $client = static::findOneByType(HttpClient::class);
28
-        } catch (DiscoveryFailedException $e) {
29
-            throw new NotFoundException('No HTTPlug clients found. Make sure to install a package providing "php-http/client-implementation". Example: "php-http/guzzle6-adapter".', 0, $e);
30
-        }
17
+	/**
18
+	 * Finds an HTTP Client.
19
+	 *
20
+	 * @return HttpClient
21
+	 *
22
+	 * @throws Exception\NotFoundException
23
+	 */
24
+	public static function find()
25
+	{
26
+		try {
27
+			$client = static::findOneByType(HttpClient::class);
28
+		} catch (DiscoveryFailedException $e) {
29
+			throw new NotFoundException('No HTTPlug clients found. Make sure to install a package providing "php-http/client-implementation". Example: "php-http/guzzle6-adapter".', 0, $e);
30
+		}
31 31
 
32
-        return static::instantiateClass($client);
33
-    }
32
+		return static::instantiateClass($client);
33
+	}
34 34
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -12,8 +12,7 @@
 block discarded – undo
12 12
  *
13 13
  * @deprecated This will be removed in 2.0. Consider using Psr18ClientDiscovery.
14 14
  */
15
-final class HttpClientDiscovery extends ClassDiscovery
16
-{
15
+final class HttpClientDiscovery extends ClassDiscovery {
17 16
     /**
18 17
      * Finds an HTTP Client.
19 18
      *
Please login to merge, or discard this patch.
lib/Vendor/Http/Discovery/Psr18ClientDiscovery.php 2 patches
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -13,21 +13,21 @@
 block discarded – undo
13 13
  */
14 14
 final class Psr18ClientDiscovery extends ClassDiscovery
15 15
 {
16
-    /**
17
-     * Finds a PSR-18 HTTP Client.
18
-     *
19
-     * @return ClientInterface
20
-     *
21
-     * @throws RealNotFoundException
22
-     */
23
-    public static function find()
24
-    {
25
-        try {
26
-            $client = static::findOneByType(ClientInterface::class);
27
-        } catch (DiscoveryFailedException $e) {
28
-            throw new RealNotFoundException('No PSR-18 clients found. Make sure to install a package providing "psr/http-client-implementation". Example: "php-http/guzzle7-adapter".', 0, $e);
29
-        }
16
+	/**
17
+	 * Finds a PSR-18 HTTP Client.
18
+	 *
19
+	 * @return ClientInterface
20
+	 *
21
+	 * @throws RealNotFoundException
22
+	 */
23
+	public static function find()
24
+	{
25
+		try {
26
+			$client = static::findOneByType(ClientInterface::class);
27
+		} catch (DiscoveryFailedException $e) {
28
+			throw new RealNotFoundException('No PSR-18 clients found. Make sure to install a package providing "psr/http-client-implementation". Example: "php-http/guzzle7-adapter".', 0, $e);
29
+		}
30 30
 
31
-        return static::instantiateClass($client);
32
-    }
31
+		return static::instantiateClass($client);
32
+	}
33 33
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -11,8 +11,7 @@
 block discarded – undo
11 11
  *
12 12
  * @author Tobias Nyholm <[email protected]>
13 13
  */
14
-final class Psr18ClientDiscovery extends ClassDiscovery
15
-{
14
+final class Psr18ClientDiscovery extends ClassDiscovery {
16 15
     /**
17 16
      * Finds a PSR-18 HTTP Client.
18 17
      *
Please login to merge, or discard this patch.