Failed Conditions
Push — master ( 47a38a...a87e0d )
by Sébastien
02:33
created

AccessLogger::getBrowserInfo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 14
nc 2
nop 1
dl 0
loc 20
ccs 0
cts 18
cp 0
crap 6
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Infra\Log;
6
7
use App\Entity\AccessLog;
8
use DeviceDetector\DeviceDetector;
9
use Doctrine\ORM\EntityManager;
10
11
class AccessLogger
12
{
13
    public const TYPE_LOGIN_SUCCESS               = 'success';
14
    public const TYPE_LOGIN_FAILURE               = 'fail';
15
    public const TYPE_LOGIN_FAILURE_EXPIRY        = 'fail.expiry';
16
    public const TYPE_LOGIN_FAILURE_PAYMENT_ISSUE = 'fail.payment';
17
    public const TYPE_LOGIN_FAILURE_CREDENTIALS   = 'fail.credentials';
18
    public const TYPE_LOGIN_FAILURE_NO_ACCESS     = 'fail.no_access';
19
20
    public const SUPPORTED_TYPES = [
21
        self::TYPE_LOGIN_SUCCESS,
22
        self::TYPE_LOGIN_FAILURE,
23
        self::TYPE_LOGIN_FAILURE_CREDENTIALS,
24
        self::TYPE_LOGIN_FAILURE_EXPIRY,
25
        self::TYPE_LOGIN_FAILURE_PAYMENT_ISSUE,
26
        self::TYPE_LOGIN_FAILURE_NO_ACCESS,
27
    ];
28
29
    /**
30
     * @var EntityManager
31
     */
32
    private $em;
33
34
    /**
35
     * Device detector caches.
36
     *
37
     * @var array<string, DeviceDetector>
38
     */
39
    private $ddCache;
40
41
    /**
42
     * Whether user agent detection is enabled.
43
     *
44
     * @var bool
45
     */
46
    private $uaDetectionEnabled;
47
48
    /**
49
     * @param bool $uaDetectionEnabled Whether user agent detection is enabled
50
     */
51
    public function __construct(EntityManager $entityManager, $uaDetectionEnabled = true)
52
    {
53
        $this->em                 = $entityManager;
54
        $this->uaDetectionEnabled = $uaDetectionEnabled;
55
        $this->ddCache            = [];
56
    }
57
58
    /**
59
     * @throws \Throwable
60
     */
61
    public function log(string $type, string $email, ?string $language, ?string $ip, ?string $userAgent): void
62
    {
63
        $browserInfo                                                                              = $this->getBrowserInfo($this->uaDetectionEnabled ? $userAgent : null);
64
        ['os' => $os, 'browser' => $browser, 'version' => $browserVersion, 'type' => $deviceType] = $browserInfo;
65
        $accessLog                                                                                = new AccessLog($type, $email, $language, $ip, $userAgent, $browser, $browserVersion, $os, $deviceType);
66
        try {
67
            $this->em->persist($accessLog);
68
            $this->em->flush();
69
        } catch (\Throwable $e) {
70
            throw $e;
71
        }
72
    }
73
74
    /**
75
     * @return array<string, mixed>
76
     */
77
    public function getBrowserInfo(?string $userAgent): array
78
    {
79
        if ($userAgent === null) {
80
            return [
81
                'os'              => null,
82
                'browser'         => null,
83
                'version' 		      => null,
84
                'type'			         => null,
85
            ];
86
        }
87
88
        $dd = $this->getDeviceDetector($userAgent);
89
        $dd->skipBotDetection();
90
        $dd->parse();
91
92
        return [
93
            'os'      	 => $dd->getOs('short_name'),
94
            'browser'   => $dd->getClient('name'),
95
            'version'   => $dd->getClient('version'),
96
            'type'      => $dd->getDeviceName(),
97
        ];
98
    }
99
100
    /**
101
     * Basic in-memory caching, should be fine for AccessLogger in context.
102
     */
103
    private function getDeviceDetector(string $userAgent): DeviceDetector
104
    {
105
        $agentKey = md5($userAgent);
106
        if (!isset($this->ddCache[$agentKey])) {
107
            $this->ddCache[$agentKey] = new DeviceDetector($userAgent);
108
        }
109
110
        return $this->ddCache[$agentKey];
111
    }
112
}
113