HttpPipelineProvisioner   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 66
c 4
b 0
f 0
dl 0
loc 94
ccs 0
cts 20
cp 0
rs 10
wmc 5

2 Methods

Rating   Name   Duplication   Size   Complexity  
A provision() 0 72 4
A routerFactory() 0 16 1
1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of the daikon-cqrs/boot project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Daikon\Boot\Service\Provisioner;
10
11
use Aura\Router\RouterContainer;
12
use Auryn\Injector;
13
use Daikon\Boot\Config\RoutingConfigLoader;
14
use Daikon\Boot\Middleware\PipelineBuilderInterface;
15
use Daikon\Boot\Middleware\RoutingHandler;
16
use Daikon\Boot\Service\ServiceDefinitionInterface;
17
use Daikon\Config\ConfigProviderInterface;
18
use Middlewares\ContentEncoding;
19
use Middlewares\ContentLanguage;
20
use Middlewares\ContentType;
21
use Middlewares\JsonPayload;
22
use Middlewares\RequestHandler;
23
use Middlewares\UrlEncodePayload;
24
use Neomerx\Cors\Analyzer;
25
use Neomerx\Cors\Contracts\AnalyzerInterface;
26
use Neomerx\Cors\Strategies\Settings;
27
use Psr\Container\ContainerInterface;
28
use Psr\Log\LoggerInterface;
29
30
final class HttpPipelineProvisioner implements ProvisionerInterface
31
{
32
    public function provision(
33
        Injector $injector,
34
        ConfigProviderInterface $configProvider,
35
        ServiceDefinitionInterface $serviceDefinition
36
    ): void {
37
        $serviceClass = $serviceDefinition->getServiceClass();
38
        $settings = $serviceDefinition->getSettings();
39
40
        $injector
41
            ->define($serviceClass, [':settings' => $settings])
42
            ->share($serviceClass)
43
            ->alias(PipelineBuilderInterface::class, $serviceClass)
44
            // Content Negotiation
45
            ->define(ContentLanguage::class, [
46
                ':languages' => $configProvider->get('project.negotiation.languages', ['en'])
47
            ])
48
            ->define(ContentEncoding::class, [':encodings' => ['gzip', 'deflate']])
49
            ->delegate(ContentType::class, function () use ($configProvider): ContentType {
50
                return (new ContentType($configProvider->get('project.negotiation.content_types')))
51
                    ->charsets($configProvider->get('project.negotiation.charsets', ['UTF-8']))
52
                    ->nosniff($configProvider->get('project.negotiation.nosniff', true))
53
                    ->errorResponse();
54
            })
55
            // Cors
56
            ->share(AnalyzerInterface::class)
57
            ->alias(AnalyzerInterface::class, Analyzer::class)
58
            ->delegate(Analyzer::class, function () use ($injector, $configProvider): AnalyzerInterface {
59
                $corsSettings = (new Settings)->init(
60
                    $configProvider->get('project.cors.scheme'),
61
                    $configProvider->get('project.cors.host'),
62
                    $configProvider->get('project.cors.port')
63
                )->setAllowedOrigins(
64
                    $configProvider->get('project.cors.request.allowed_origins', [])
65
                )->setAllowedHeaders(
66
                    $configProvider->get('project.cors.request.allowed_headers', [])
67
                )->setAllowedMethods(
68
                    $configProvider->get('project.cors.request.allowed_methods', [])
69
                )->setPreFlightCacheMaxAge(
70
                    $configProvider->get('project.cors.response.preflight_cache_max_age', 0)
71
                )->setExposedHeaders(
72
                    $configProvider->get('project.cors.response.exposed_headers', [])
73
                );
74
                if ($configProvider->get('project.cors.request.enable_check_host') === true) {
75
                    $corsSettings = $corsSettings->enableCheckHost();
76
                }
77
                if ($configProvider->get('project.cors.request.allowed_all_origins') === true) {
78
                    $corsSettings = $corsSettings->enableAllOriginsAllowed();
79
                }
80
                if ($configProvider->get('project.cors.request.allowed_credentials') === true) {
81
                    $corsSettings = $corsSettings->setCredentialsSupported();
82
                }
83
                $analyzer = Analyzer::instance($corsSettings);
84
                $analyzer->setLogger($injector->make(LoggerInterface::class));
85
                return $analyzer;
86
            })
87
            // Routing and request
88
            ->share(JsonPayload::class)
89
            ->delegate(JsonPayload::class, fn(): JsonPayload => (new JsonPayload)->depth(8)->override(true))
90
            ->share(UrlEncodePayload::class)
91
            ->delegate(UrlEncodePayload::class, fn(): UrlEncodePayload => (new UrlEncodePayload)->override(true))
92
            ->share(RoutingHandler::class)
93
            ->delegate(
94
                RoutingHandler::class,
95
                function (ContainerInterface $container) use ($configProvider): RoutingHandler {
96
                    return new RoutingHandler($this->routerFactory($configProvider), $container);
97
                }
98
            )
99
            ->share(RequestHandler::class)
100
            ->delegate(
101
                RequestHandler::class,
102
                function (ContainerInterface $container): RequestHandler {
103
                    return (new RequestHandler($container))->handlerAttribute(RoutingHandler::REQUEST_HANDLER);
104
                }
105
            );
106
    }
107
108
    private function routerFactory(ConfigProviderInterface $configProvider): RouterContainer
109
    {
110
        $appContext = $configProvider->get('app.context');
111
        $appEnv = $configProvider->get('app.env');
112
        $appConfigDir = $configProvider->get('app.config_dir');
113
        $router = new RouterContainer;
114
        (new RoutingConfigLoader($router, $configProvider))->load(
115
            array_merge([$appConfigDir], (array)$configProvider->get('crates.*.config_dir', [])),
116
            [
117
                'routing.php',
118
                "routing.$appContext.php",
119
                "routing.$appEnv.php",
120
                "routing.$appContext.$appEnv.php"
121
            ]
122
        );
123
        return $router;
124
    }
125
}
126