Passed
Push — master ( 7dc569...e9ad93 )
by Mr
08:03
created

HttpPipelineProvisioner::routerFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 11
nc 1
nop 1
dl 0
loc 16
ccs 0
cts 7
cp 0
crap 2
rs 9.9
c 1
b 0
f 0
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
29
final class HttpPipelineProvisioner implements ProvisionerInterface
30
{
31
    public function provision(
32
        Injector $injector,
33
        ConfigProviderInterface $configProvider,
34
        ServiceDefinitionInterface $serviceDefinition
35
    ): void {
36
        $serviceClass = $serviceDefinition->getServiceClass();
37
        $settings = $serviceDefinition->getSettings();
38
39
        $injector
40
            ->define($serviceClass, [':settings' => $settings])
41
            ->share($serviceClass)
42
            ->alias(PipelineBuilderInterface::class, $serviceClass)
43
            // Content Negotiation
44
            ->define(ContentLanguage::class, [
45
                ':languages' => $configProvider->get('project.negotiation.languages', ['en'])
46
            ])
47
            ->define(ContentEncoding::class, [':encodings' => ['gzip', 'deflate']])
48
            ->delegate(ContentType::class, function () use ($configProvider): ContentType {
49
                return (new ContentType($configProvider->get('project.negotiation.content_types')))
50
                    ->charsets($configProvider->get('project.negotiation.charsets', ['UTF-8']))
51
                    ->nosniff($configProvider->get('project.negotiation.nosniff', true))
52
                    ->errorResponse();
53
            })
54
            // Cors
55
            ->share(AnalyzerInterface::class)
56
            ->alias(AnalyzerInterface::class, Analyzer::class)
57
            ->delegate(Analyzer::class, function () use ($configProvider): AnalyzerInterface {
58
                $corsSettings = (new Settings)
59
                    ->disableAddAllowedMethodsToPreFlightResponse()
60
                    ->disableAddAllowedHeadersToPreFlightResponse()
61
                    ->enableCheckHost()
62
                    ->setServerOrigin(
63
                        $configProvider->get('project.cors.scheme'),
64
                        $configProvider->get('project.cors.host'),
65
                        $configProvider->get('project.cors.port')
66
                    )->setAllowedOrigins(
67
                        $configProvider->get('project.cors.request.allowed_origins', [])
68
                    )->setAllowedHeaders(
69
                        $configProvider->get('project.cors.request.allowed_headers', [])
70
                    )->setAllowedMethods(
71
                        $configProvider->get('project.cors.request.allowed_methods', [])
72
                    )->setPreFlightCacheMaxAge(
73
                        $configProvider->get('project.cors.response.preflight_cache_max_age', 0)
74
                    )->setExposedHeaders(
75
                        $configProvider->get('project.cors.response.exposed_headers', [])
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
                return Analyzer::instance($corsSettings);
84
            })
85
            // Routing and request
86
            ->share(JsonPayload::class)
87
            ->delegate(JsonPayload::class, fn(): JsonPayload => (new JsonPayload)->depth(8)->override(true))
88
            ->share(UrlEncodePayload::class)
89
            ->delegate(UrlEncodePayload::class, fn(): UrlEncodePayload => (new UrlEncodePayload)->override(true))
90
            ->share(RoutingHandler::class)
91
            ->delegate(
92
                RoutingHandler::class,
93
                function (ContainerInterface $container) use ($configProvider): RoutingHandler {
94
                    return new RoutingHandler($this->routerFactory($configProvider), $container);
95
                }
96
            )
97
            ->share(RequestHandler::class)
98
            ->delegate(
99
                RequestHandler::class,
100
                function (ContainerInterface $container): RequestHandler {
101
                    return (new RequestHandler($container))->handlerAttribute(RoutingHandler::REQUEST_HANDLER);
102
                }
103
            );
104
    }
105
106
    private function routerFactory(ConfigProviderInterface $configProvider): RouterContainer
107
    {
108
        $appContext = $configProvider->get('app.context');
109
        $appEnv = $configProvider->get('app.env');
110
        $appConfigDir = $configProvider->get('app.config_dir');
111
        $router = new RouterContainer;
112
        (new RoutingConfigLoader($router, $configProvider))->load(
113
            array_merge([$appConfigDir], (array)$configProvider->get('crates.*.config_dir', [])),
114
            [
115
                'routing.php',
116
                "routing.$appContext.php",
117
                "routing.$appEnv.php",
118
                "routing.$appContext.$appEnv.php"
119
            ]
120
        );
121
        return $router;
122
    }
123
}
124