Configuration::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 2
rs 10
1
<?php
2
3
namespace BenTools\MercurePHP\Configuration;
4
5
use Symfony\Component\Console\Input\InputInterface;
6
7
use function BenTools\MercurePHP\nullify;
8
9
final class Configuration
10
{
11
    public const ADDR = 'addr';
12
    public const TRANSPORT_URL = 'transport_url';
13
    public const STORAGE_URL = 'storage_url';
14
    public const METRICS_URL = 'metrics_url';
15
    public const CORS_ALLOWED_ORIGINS = 'cors_allowed_origins';
16
    public const PUBLISH_ALLOWED_ORIGINS = 'publish_allowed_origins';
17
    public const JWT_KEY = 'jwt_key';
18
    public const JWT_ALGORITHM = 'jwt_algorithm';
19
    public const PUBLISHER_JWT_KEY = 'publisher_jwt_key';
20
    public const PUBLISHER_JWT_ALGORITHM = 'publisher_jwt_algorithm';
21
    public const SUBSCRIBER_JWT_KEY = 'subscriber_jwt_key';
22
    public const SUBSCRIBER_JWT_ALGORITHM = 'subscriber_jwt_algorithm';
23
    public const ALLOW_ANONYMOUS = 'allow_anonymous';
24
25
    public const DEFAULT_ADDR = '127.0.0.1:3000';
26
    public const DEFAULT_TRANSPORT_URL = 'php://localhost?size=1000';
27
    public const DEFAULT_JWT_ALGORITHM = 'HS256';
28
    public const DEFAULT_CORS_ALLOWED_ORIGINS = '*';
29
    public const DEFAULT_PUBLISH_ALLOWED_ORIGINS = '*';
30
31
    private const DEFAULT_CONFIG = [
32
        self::ADDR => self::DEFAULT_ADDR,
33
        self::TRANSPORT_URL => self::DEFAULT_TRANSPORT_URL,
34
        self::STORAGE_URL => null,
35
        self::METRICS_URL => null,
36
        self::CORS_ALLOWED_ORIGINS => self::DEFAULT_CORS_ALLOWED_ORIGINS,
37
        self::PUBLISH_ALLOWED_ORIGINS => self::DEFAULT_PUBLISH_ALLOWED_ORIGINS,
38 413
        self::JWT_KEY => null,
39
        self::JWT_ALGORITHM => self::DEFAULT_JWT_ALGORITHM,
40 413
        self::PUBLISHER_JWT_KEY => null,
41 408
        self::PUBLISHER_JWT_ALGORITHM => null,
42
        self::SUBSCRIBER_JWT_KEY => null,
43 413
        self::SUBSCRIBER_JWT_ALGORITHM => null,
44
        self::ALLOW_ANONYMOUS => false,
45 413
    ];
46
47 413
    private array $config = self::DEFAULT_CONFIG;
48 413
49 1
    public function __construct(array $config = [])
50 1
    {
51
        foreach ($config as $key => $value) {
52
            $this->set($key, $value);
53
        }
54 412
    }
55
56
    private function export(): array
57 413
    {
58
        $config = \array_map(fn($value) => \is_string($value) && '' === \trim($value) ? null : $value, $this->config);
59 413
        if (null === $config[self::JWT_KEY] && null === $config[self::PUBLISHER_JWT_KEY]) {
60
            throw new \InvalidArgumentException(
61
                "One of \"jwt_key\" or \"publisher_jwt_key\" configuration parameter must be defined."
62 412
            );
63
        }
64 412
65 412
        return $config;
66
    }
67
68 412
    public function asArray(): array
69
    {
70
        return $this->export();
71 412
    }
72 412
73
    private function set(string $key, $value): void
74 4
    {
75
        $key = self::normalize($key);
76 4
        if (!\array_key_exists($key, self::DEFAULT_CONFIG)) {
77 4
            return;
78 4
        }
79
        if (null === $value && \is_bool(self::DEFAULT_CONFIG[$key])) {
80
            $value = self::DEFAULT_CONFIG[$key];
81 4
        }
82
        $this->config[$key] = $value;
83
    }
84 412
85
    public function overrideWith(array $values): self
86 412
    {
87
        $clone = clone $this;
88
        foreach ($values as $key => $value) {
89
            $clone->set($key, $value);
90
        }
91
92
        return $clone;
93
    }
94
95
    private static function normalize(string $key): string
96
    {
97
        return \strtolower(\strtr($key, ['-' => '_']));
98
    }
99
100
    public static function bootstrapFromCLI(InputInterface $input): self
101
    {
102
        return (new self())
103
            ->overrideWith($_SERVER)
104
            ->overrideWith(self::filterCLIInput($input));
105
    }
106
107
    private static function filterCLIInput(InputInterface $input): array
108
    {
109
        return \array_filter(
110
            $input->getOptions(),
111
            fn($value) => null !== nullify($value) && false !== $value
112
        );
113
    }
114
}
115