Passed
Push — master ( fabbdf...3d1055 )
by Aleksei
06:01 queued 12s
created

HttpBootloader::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 12
ccs 11
cts 11
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 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\LazyPipeline;
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 383
    public function __construct(
38
        private readonly ConfiguratorInterface $config,
39
        private readonly BinderInterface $binder,
40 383
    ) {}
41
42 383
    public function defineDependencies(): array
43
    {
44 383
        return [
45 383
            TelemetryBootloader::class,
46 383
        ];
47
    }
48
49 383
    public function defineSingletons(): array
50
    {
51 383
        $this->binder->bind(
52 383
            RequestInterface::class,
53 383
            new \Spiral\Core\Config\Proxy(
54 383
                interface: RequestInterface::class,
55 383
                fallbackFactory: static function (): never {
56 1
                    throw new ScopeException(
57 1
                        'Unable to receive current Server Request. '
58 1
                        . 'Try to define the service in the `http` scope or use the Poxy attribute.',
59 1
                    );
60 383
                },
61 383
            ),
62 383
        );
63
64 383
        $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

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