Passed
Branch master (3adec6)
by Mihail
02:11
created

Module::configuration()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.9256

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 15
nc 8
nop 0
dl 0
loc 20
ccs 10
cts 15
cp 0.6667
crap 5.9256
rs 9.4555
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Koded\Framework;
4
5
use Koded\{DIContainer, DIModule};
6
use Koded\Framework\Auth\{AuthBackend, AuthProcessor, BearerAuthProcessor, SessionAuthBackend};
7
use Koded\Http\{ServerRequest, ServerResponse};
8
use Koded\Http\Interfaces\{Request, Response};
9
use Koded\I18n\{I18n, I18nCatalog};
10
use Koded\Logging\Log;
11
use Koded\Logging\Processors\Cli;
12
use Koded\Stdlib\{Config, Configuration, Immutable};
13
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
14
use Psr\Log\LoggerInterface;
15
use Psr\SimpleCache\CacheInterface;
16
use ReflectionClass;
17
use function dirname;
18
use function is_a;
19
use function is_readable;
20
use function Koded\Caching\simple_cache_factory;
21
use function putenv;
22
23
final class Module implements DIModule
24
{
25
    private const ENV_KEY = '__KODED_CONFIG';
26
27
    public function __construct(private Configuration|string $configuration) {}
28
29 24
    public function configure(DIContainer $container): void
30
    {
31 24
        $container->named('$errorSerializer', 'default_serialize_error');
32 24
        $container->bind(Request::class,         /* defer */);
33 24
        $container->bind(Response::class,        /* defer */);
34 24
        $container->bind(Configuration::class,   /* defer */);
35 24
        $container->bind(CacheInterface::class,  /* defer */);
36 24
        $container->bind(LoggerInterface::class, /* defer */);
37 24
        $container->bind(ServerRequestInterface::class, ServerRequest::class);
38 24
        $container->bind(ResponseInterface::class, ServerResponse::class);
39
        // Core instances
40 24
        $container->share($conf = $this->configuration());
41 24
        I18n::register(I18nCatalog::new($conf), true);
42 24
        $container->share(new Log(...$conf->get('logging', [])));
43 24
        $container->share(simple_cache_factory(...$conf->get('caching', [])));
44 24
        $container->share($container->new(Router::class));
45
        // Default authentication
46 24
        $container->bind(AuthBackend::class, SessionAuthBackend::class);
47 24
        $container->bind(AuthProcessor::class, BearerAuthProcessor::class);
48
    }
49
50 24
    private function configuration(): Configuration
51
    {
52 24
        $factory = new Config('', $this->defaultConfiguration());
53 24
        if (empty($this->configuration)) {
54 18
            goto load;
55
        }
56 6
        if (is_a($this->configuration, Configuration::class, true)) {
57 6
            $factory->fromObject($this->configuration);
58 6
            $factory->rootPath = dirname((new ReflectionClass($this->configuration))->getFileName());
59
        } elseif (is_readable($this->configuration)) {
60
            putenv(self::ENV_KEY . '=' . $this->configuration);
61
            $factory->fromEnvVariable(self::ENV_KEY);
62
            $factory->rootPath = dirname($this->configuration);
63
        }
64
        load:
65 24
        @$factory->fromEnvFile('.env');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fromEnvFile(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

65
        /** @scrutinizer ignore-unhandled */ @$factory->fromEnvFile('.env');

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
66 24
        foreach ($factory->get('autoloaders', []) as $autoloader) {
67
            include_once $autoloader;
68
        }
69 24
        return $factory;
70
    }
71
72 24
    private function defaultConfiguration(): Immutable
73
    {
74 24
        return new Immutable(
75 24
            [
76
                // I18n directives
77 24
                'translation.dir' => __DIR__ . '/locale',
78
79
                // CORS overrides (all values are scalar)
80 24
                'cors.disable' => false,
81 24
                'cors.origin' => '',
82 24
                'cors.methods' => '',
83 24
                'cors.headers' => '',
84 24
                'cors.expose' => '',
85 24
                'cors.maxAge' => 0,
86
87
                // Logging
88 24
                'logging' => [
89 24
                    [
90 24
                        [
91 24
                            'class' => Cli::class,
92 24
                            'format' => '[levelname] message',
93 24
                            'levels' => Log::INFO
94 24
                        ]
95 24
                    ],
96 24
                    'dateformat' => 'd-m-Y H:i:s'
97 24
                ],
98 24
            ]);
99
    }
100
}
101