Passed
Push — master ( f0640d...d81e81 )
by Timothy
56s queued 11s
created

determineApplicableLogLevel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 9
cp 0
rs 9.552
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Abacaphiliac\Doctrine;
4
5
use InvalidArgumentException;
6
use Psr\Log\LogLevel;
7
use ReflectionClass;
8
use function asort;
9
use function array_keys;
10
use function array_search;
11
use function array_values;
12
use function print_r;
13
use function count;
14
15
final class LogLevelConfiguration
16
{
17
    /** @var array<string, int> */
18
    private $logLevelMapping = [];
19
20
    public function __construct(array $logLevelMapping)
21
    {
22
        foreach ($logLevelMapping as $logLevel => $durationThresholdInMilliseconds) {
23
            $this->addLogLevelThreshold($logLevel, $durationThresholdInMilliseconds);
24
        }
25
    }
26
27
    private function addLogLevelThreshold(string $logLevel, int $durationThresholdInMilliseconds) : void
28
    {
29
        $this->validateLogLevel($logLevel);
30
        $this->logLevelMapping[$logLevel] = $durationThresholdInMilliseconds;
31
    }
32
33
    private function validateLogLevel(string $logLevel): void
34
    {
35
        if (! $this->isAllowedLogLevel($logLevel)) {
36
            throw new InvalidArgumentException(sprintf(
37
                'invalid LogLevel detected: "%s", please choose from: "%s"',
38
                $logLevel,
39
                print_r($this->getAllowedLogLevels(), true)
40
            ));
41
        }
42
    }
43
    
44
    private function isAllowedLogLevel(string $logLevel): bool
45
    {
46
        return in_array($logLevel, $this->getAllowedLogLevels(), true);
47
    }
48
49
    private function getAllowedLogLevels(): array
50
    {
51
        static $allowedConstants;
52
53
        return $allowedConstants ?: $allowedConstants = (new ReflectionClass(LogLevel::class))->getConstants();
54
    }
55
56
    public function getApplicableLogLevel(float $durationInSeconds): ?string
57
    {
58
        return count($this->logLevelMapping) > 0 ? $this->determineApplicableLogLevel($durationInSeconds) : null;
59
    }
60
61
    private function determineApplicableLogLevel(float $durationInSeconds) : string
62
    {
63
        $durationInMilliseconds = $durationInSeconds * 1000;
64
65
        //Acquire a common / non-associative array with all the thresholds
66
        $durationThresholds = array_values($this->logLevelMapping);
67
68
        //Append the incoming query duration in milliseconds to the array of duration thresholds
69
        $durationThresholds[] = $durationInMilliseconds;
70
71
        //Sort the array from low to high: the provided duration will end up somewhere between the thresholds
72
        asort($durationThresholds, SORT_NUMERIC);
73
74
        //A re-index is required after sorting
75
        $durationThresholds = array_values($durationThresholds);
76
77
        //Determine at which position the duration ended up after sorting
78
        $key = array_search($durationInMilliseconds, $durationThresholds, true);
79
80
        $logLevels = array_keys($this->logLevelMapping);
81
82
        return $logLevels[$key - 1]; //Now take the "previous" key
83
    }
84
}
85