DeamonLoggerExtraWebProcessor::addUserInfo()   B
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 13
ccs 8
cts 8
cp 1
rs 8.8333
cc 7
nc 4
nop 0
crap 7
1
<?php
2
3
namespace Deamon\LoggerExtraBundle\Processors\Monolog;
4
5
use Deamon\LoggerExtraBundle\Services\DeamonLoggerExtraContext;
6
use Monolog\LogRecord;
7
use Monolog\Processor\WebProcessor as BaseWebProcessor;
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Component\HttpFoundation\RequestStack;
10
use Symfony\Component\HttpKernel\Event\RequestEvent;
11
use Symfony\Component\HttpKernel\KernelEvents;
12
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
13
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
14
use Symfony\Component\Security\Core\User\UserInterface;
15
16
class DeamonLoggerExtraWebProcessor extends BaseWebProcessor
17
{
18
19
    private ?string $environment = null;
20
21
    private ?DeamonLoggerExtraContext $loggerExtraContext = null;
22
23
    private ?TokenStorageInterface $tokenStorage = null;
24
25
    private ?RequestStack $requestStack = null;
26
27
    private array $displayConfig;
28
29
    private ?string $channelPrefix;
30
31
    private ?string $userClass;
32
33
    private array $userMethods;
34
35
    private LogRecord $record;
36
37 9
    public function __construct(?array $config = null)
38
    {
39 9
        parent::__construct([]);
40
41 9
        $this->channelPrefix =$config['channel_prefix'] ?? null;
42
43 9
        $this->userMethods = $config['user_methods'] ?? [];
44 9
        $this->displayConfig = $config['display'] ?? [];
45 9
        $this->userClass = $config['user_class'] ?? null;
46
    }
47
48 9
    public function __invoke(LogRecord $record): LogRecord
49
    {
50 9
        $this->record = parent::__invoke($record);
51
52 9
        $this->addContextInfo();
53 9
        $this->addRequestInfo();
54 9
        $this->addUserInfo();
55
56 9
        return $this->record;
57
    }
58
59
    /**
60
     * Add extra info about the context of the generated log.
61
     */
62 9
    private function addContextInfo(): void
63
    {
64 9
        if (null !== $this->environment) {
65 2
            $this->addInfo('env', $this->environment);
66
        }
67
68 9
        if (null !== $this->loggerExtraContext) {
69 2
            $this->addInfo('locale', $this->loggerExtraContext->getLocale());
70 2
            if ($this->configShowExtraInfo('application_name')) {
71 2
                $this->record->extra['application'] = $this->loggerExtraContext->getApplicationName();
72
            }
73 2
            $applicationVersion = $this->loggerExtraContext->getApplicationVersion() ?? $this->channelPrefix;
74 2
            $this->addInfo('application_version', $applicationVersion);
75
        }
76
    }
77
78
    /**
79
     * Add extra info about the request generating the log.
80
     */
81 9
    private function addRequestInfo(): void
82
    {
83 9
        $request = $this->requestStack?->getCurrentRequest();
84 9
        if ($request instanceof Request) {
85 1
            $this->addInfo('url', $request->getRequestUri());
86 1
            $this->addInfo('route', $request->get('_route'));
87 1
            $this->addInfo('user_agent', $request->server->get('HTTP_USER_AGENT'));
88 1
            $this->addInfo('accept_encoding', $request->headers->get('Accept-Encoding'));
89 1
            $this->addInfo('client_ip', $request->getClientIp());
90
        }
91
    }
92
93
    /**
94
     * Add extra info on the user generating the log.
95
     */
96 9
    private function addUserInfo(): void
97
    {
98 9
        if (!$this->configShowExtraInfo('user') || empty($this->userClass)) {
99 5
            return;
100
        }
101
102 4
        if (!class_exists($this->userClass) && !interface_exists($this->userClass)) {
103 1
            return;
104
        }
105
106 3
        $token = $this->tokenStorage?->getToken();
107 3
        if ($this->isUserInstanceValid($token) && null !== $user = $token->getUser()) {
108 1
            $this->appendUserMethodInfo($user);
109
        }
110
    }
111
112
    /**
113
     * Append method result of user object.
114
     */
115 1
    private function appendUserMethodInfo(UserInterface $user): void
116
    {
117 1
        foreach ($this->userMethods as $name => $method) {
118 1
            if (method_exists($user, $method)) {
119 1
                $this->record->extra[$name] = $user->$method();
120
            }
121
        }
122
    }
123
124
    /**
125
     * Check if passed token is an instance of TokenInterface and an instance of config UserClass.
126
     */
127 3
    private function isUserInstanceValid(?TokenInterface $token): bool
128
    {
129 3
        return $token instanceof TokenInterface && $token->getUser() instanceof $this->userClass;
130
    }
131
132
    /**
133
     * Add the extra info if configured to.
134
     */
135 3
    private function addInfo(string $key, mixed $value): void
136
    {
137 3
        if ($this->configShowExtraInfo($key) && $value !== null) {
138 3
            $this->record->extra[$key] = $value;
139
        }
140
    }
141
142
    /**
143
     * Tells if the config to display the extra info is enabled or not.
144
     */
145 9
    private function configShowExtraInfo(string $extraInfo): bool
146
    {
147 9
        return isset($this->displayConfig[$extraInfo]) && $this->displayConfig[$extraInfo];
148
    }
149
150
    public function onKernelRequest(RequestEvent $event)
151
    {
152
        if ($event->isMainRequest()) {
153
            $this->serverData = $event->getRequest()->server->all();
154
            $this->serverData['REMOTE_ADDR'] = $event->getRequest()->getClientIp();
155
        }
156
    }
157
158
    public static function getSubscribedEvents()
159
    {
160
        return [
161
            KernelEvents::REQUEST => ['onKernelRequest', 4096],
162
        ];
163
    }
164
165 2
    public function setLoggerExtraContext(DeamonLoggerExtraContext $loggerExtraContext): void
166
    {
167 2
        $this->loggerExtraContext = $loggerExtraContext;
168
    }
169
170 2
    public function setEnvironment(string $environment): void
171
    {
172 2
        $this->environment = $environment;
173
    }
174
175 2
    public function setTokenStorage(TokenStorageInterface $tokenStorage): void
176
    {
177 2
        $this->tokenStorage = $tokenStorage;
178
    }
179
180 1
    public function setRequestStack(RequestStack $requestStack): void
181
    {
182 1
        $this->requestStack = $requestStack;
183
    }
184
}
185