Passed
Push — master ( 67783c...f2b326 )
by Aleksei
11:31
created

HttpBootloader   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Test Coverage

Coverage 90.63%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 8
eloc 46
dl 0
loc 115
ccs 58
cts 64
cp 0.9063
rs 10
c 2
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A httpCore() 0 12 1
A addMiddleware() 0 3 1
A addInputBag() 0 3 1
A defineDependencies() 0 4 1
A init() 0 12 1
A defineSingletons() 0 47 2
A __construct() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Bootloader\Http;
6
7
use Psr\Container\ContainerInterface;
8
use Psr\Http\Message\ResponseFactoryInterface;
9
use Psr\Http\Message\ServerRequestInterface as RequestInterface;
10
use Psr\Http\Server\MiddlewareInterface;
11
use Psr\Http\Server\RequestHandlerInterface;
12
use Spiral\Boot\Bootloader\Bootloader;
13
use Spiral\Bootloader\Http\Exception\InvalidRequestScopeException;
14
use Spiral\Config\ConfiguratorInterface;
15
use Spiral\Config\Patch\Append;
16
use Spiral\Core\Attribute\Proxy;
17
use Spiral\Core\Attribute\Singleton;
18
use Spiral\Core\BinderInterface;
19
use Spiral\Core\Container;
20
use Spiral\Core\Container\Autowire;
21
use Spiral\Core\Exception\ScopeException;
22
use Spiral\Core\InvokerInterface;
23
use Spiral\Framework\Spiral;
24
use Spiral\Http\Config\HttpConfig;
25
use Spiral\Http\CurrentRequest;
26
use Spiral\Http\Http;
27
use Spiral\Http\Pipeline;
28
use Spiral\Telemetry\Bootloader\TelemetryBootloader;
29
use Spiral\Telemetry\TracerFactoryInterface;
30
31
/**
32
 * Configures Http dispatcher.
33
 */
34
#[Singleton]
35
final class HttpBootloader extends Bootloader
36
{
37 376
    public function __construct(
38
        private readonly ConfiguratorInterface $config,
39
        private readonly BinderInterface $binder,
40
    ) {
41 376
    }
42
43 376
    public function defineDependencies(): array
44
    {
45 376
        return [
46 376
            TelemetryBootloader::class,
47 376
        ];
48
    }
49
50 376
    public function defineSingletons(): array
51
    {
52 376
        $this->binder->bind(
53 376
            RequestInterface::class,
54 376
            new \Spiral\Core\Config\Proxy(
55 376
                interface: RequestInterface::class,
56 376
                fallbackFactory: static fn (ContainerInterface $c) => throw new ScopeException(
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

56
                fallbackFactory: static fn (/** @scrutinizer ignore-unused */ ContainerInterface $c) => throw new ScopeException(

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
57 376
                    'Unable to receive current Server Request. '
58 376
                    . 'Try to define the service in the `http` scope or use the Poxy attribute.',
59 376
                ),
60 376
            ),
61 376
        );
62
63 376
        $httpBinder = $this->binder->getBinder(Spiral::Http);
0 ignored issues
show
Bug introduced by
The method getBinder() does not exist on Spiral\Core\BinderInterface. It seems like you code against a sub-type of Spiral\Core\BinderInterface such as Spiral\Core\Container. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

63
        /** @scrutinizer ignore-call */ 
64
        $httpBinder = $this->binder->getBinder(Spiral::Http);
Loading history...
64
65 376
        $httpBinder->bindSingleton(Http::class, [self::class, 'httpCore']);
66 376
        $httpBinder->bindSingleton(CurrentRequest::class, CurrentRequest::class);
67 376
        $httpBinder->bind(
68 376
            RequestInterface::class,
69 376
            new \Spiral\Core\Config\Proxy(
70 376
                interface: RequestInterface::class,
71 376
                fallbackFactory: static fn (ContainerInterface $c): RequestInterface => $c
72 376
                    ->get(CurrentRequest::class)
73 376
                    ->get() ?? throw new InvalidRequestScopeException(
74 376
                        RequestInterface::class,
75 376
                        $c instanceof Container ? $c : null,
76 376
                    ),
77 376
            ),
78 376
        );
79
80
        /**
81
         * @deprecated since v3.12. Will be removed in v4.0.
82
         */
83 376
        $this->binder->bindSingleton(
84 376
            Http::class,
85
            function (InvokerInterface $invoker, #[Proxy] ContainerInterface $container): Http {
86
                @trigger_error(\sprintf(
87
                    'Using `%s` outside of the `%s` scope is deprecated and will be impossible in version 4.0.',
88
                    Http::class,
89
                    Spiral::Http->value
90
                ), \E_USER_DEPRECATED);
91
92
                return $invoker->invoke([self::class, 'httpCore'], ['container' => $container]);
93 376
            }
94 376
        );
95
96 376
        return [];
97
    }
98
99 376
    public function init(): void
100
    {
101 376
        $this->config->setDefaults(
102 376
            HttpConfig::CONFIG,
103 376
            [
104 376
                'basePath'   => '/',
105 376
                'headers'    => [
106 376
                    'Content-Type' => 'text/html; charset=UTF-8',
107 376
                ],
108 376
                'middleware' => [],
109 376
                'chunkSize' => null,
110 376
                'inputBags' => [],
111 376
            ]
112 376
        );
113
    }
114
115
    /**
116
     * Register new http middleware.
117
     *
118
     * @psalm-param MiddlewareInterface|Autowire|class-string<MiddlewareInterface> Middleware definition
119
     */
120 358
    public function addMiddleware(string|Autowire|MiddlewareInterface $middleware): void
121
    {
122 358
        $this->config->modify(HttpConfig::CONFIG, new Append('middleware', null, $middleware));
123
    }
124
125
    /**
126
     * @param non-empty-string $bag
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
127
     * @param array{"class": class-string, "source": string, "alias": string} $config
128
     */
129 1
    public function addInputBag(string $bag, array $config): void
130
    {
131 1
        $this->config->modify(HttpConfig::CONFIG, new Append('inputBags', $bag, $config));
132
    }
133
134
    /**
135
     * @deprecated since v3.12. Will be removed in v4.0 and replaced with callback.
136
     */
137 50
    protected function httpCore(
138
        HttpConfig $config,
139
        Pipeline $pipeline,
140
        RequestHandlerInterface $handler,
141
        ResponseFactoryInterface $responseFactory,
142
        ContainerInterface $container,
143
        TracerFactoryInterface $tracerFactory
144
    ): Http {
145 50
        $core = new Http($config, $pipeline, $responseFactory, $container, $tracerFactory);
146 50
        $core->setHandler($handler);
147
148 50
        return $core;
149
    }
150
}
151