Test Failed
Pull Request — master (#1102)
by Aleksei
10:00
created

LogFactory::extractChannelAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 6
rs 10
ccs 0
cts 0
cp 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Monolog;
6
7
use Monolog\Handler\HandlerInterface;
8
use Monolog\Logger;
9
use Monolog\Processor\PsrLogMessageProcessor;
10
use Monolog\ResettableInterface;
11
use Psr\Container\ContainerExceptionInterface;
12
use Psr\Log\LoggerInterface;
13
use ReflectionAttribute;
14
use Spiral\Core\Container\Autowire;
15
use Spiral\Core\Container\InjectorInterface;
16
use Spiral\Core\FactoryInterface;
17
use Spiral\Logger\ListenerRegistryInterface;
18
use Spiral\Logger\LogsInterface;
19
use Spiral\Monolog\Bootloader\LoggerChannel;
20
use Spiral\Monolog\Config\MonologConfig;
21
use Spiral\Monolog\Exception\ConfigException;
22
23
/**
24
 * @implements InjectorInterface<Logger>
25
 */
26
final class LogFactory implements LogsInterface, InjectorInterface, ResettableInterface
27
{
28
    private ?LoggerInterface $default = null;
29 21
    private readonly HandlerInterface $eventHandler;
30
31
    public function __construct(
32
        private readonly MonologConfig $config,
33
        ListenerRegistryInterface $listenerRegistry,
34 21
        private readonly FactoryInterface $factory
35
    ) {
36
        $this->eventHandler = new EventHandler($listenerRegistry, $config->getEventLevel());
0 ignored issues
show
Bug introduced by
The property eventHandler is declared read-only in Spiral\Monolog\LogFactory.
Loading history...
37 21
    }
38
39 21
    public function getLogger(string $channel = null): LoggerInterface
40
    {
41 21
        $default = $this->config->getDefault();
42 7
43
        if ($channel === null || $channel === $default) {
44 4
            if ($this->default !== null) {
45
                // we should use only one default logger per system
46
                return $this->default;
47 7
            }
48 7
49 7
            return $this->default = new Logger(
50 7
                $default,
51 7
                $this->getHandlers($default),
52
                $this->getProcessors($default)
53
            );
54 16
        }
55 16
56 16
        return new Logger(
57 16
            $channel,
58 16
            $this->getHandlers($channel),
59
            $this->getProcessors($channel)
60
        );
61 2
    }
62
63
    public function createInjection(
64 2
        \ReflectionClass $class,
65
        \ReflectionParameter|null|string $context = null
66
    ): LoggerInterface {
67 1
        $channel = \is_object($context) ? $this->extractChannelAttribute($context) : null;
68
69 1
        // always return default logger as injection
70 1
        return $this->getLogger($channel);
71
    }
72
73
    public function reset(): void
74
    {
75
        if ($this->default instanceof ResettableInterface) {
76
            $this->default->reset();
0 ignored issues
show
Bug introduced by
The method reset() does not exist on Psr\Log\LoggerInterface. It seems like you code against a sub-type of Psr\Log\LoggerInterface such as Monolog\Logger. ( Ignorable by Annotation )

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

76
            $this->default->/** @scrutinizer ignore-call */ 
77
                            reset();
Loading history...
Bug introduced by
The method reset() does not exist on null. ( Ignorable by Annotation )

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

76
            $this->default->/** @scrutinizer ignore-call */ 
77
                            reset();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
77
        }
78
    }
79
80 21
    /**
81
     * Get list of channel specific handlers.
82
     *
83 21
     *
84
     * @throws ConfigException
85 21
     */
86 6
    protected function getHandlers(string $channel): array
87 2
    {
88 2
        // always include default handler
89
        $handlers = [];
90
91
        foreach ($this->config->getHandlers($channel) as $handler) {
92 4
            if (!$handler instanceof Autowire) {
93
                $handlers[] = $handler;
94
                continue;
95
            }
96
97
            try {
98 20
                $handlers[] = $handler->resolve($this->factory);
99
            } catch (ContainerExceptionInterface $e) {
100 20
                throw new ConfigException($e->getMessage(), $e->getCode(), $e);
101
            }
102
        }
103
104
        $handlers[] = $this->eventHandler;
105
106
        return $handlers;
107
    }
108 20
109
    /**
110 20
     * Get list of channel specific log processors.
111 20
     *
112 6
     * @return callable[]
113 3
     */
114 3
    protected function getProcessors(string $channel): array
115
    {
116
        $processors = [];
117
        foreach ($this->config->getProcessors($channel) as $processor) {
118 3
            if (!$processor instanceof Autowire) {
119
                $processors[] = $processor;
120
                continue;
121
            }
122
123
            try {
124 19
                $processors[] = $processor->resolve($this->factory);
125 13
            } catch (ContainerExceptionInterface $e) {
126
                throw new ConfigException($e->getMessage(), $e->getCode(), $e);
127
            }
128 19
        }
129
130
        if ($processors === []) {
131
            $processors[] = new PsrLogMessageProcessor();
132
        }
133
134
        return $processors;
135
    }
136
137
    /**
138
     * @return non-empty-string|null
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string|null at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string|null.
Loading history...
139
     */
140
    private function extractChannelAttribute(\ReflectionParameter $parameter): ?string
141
    {
142
        /** @var ReflectionAttribute<LoggerChannel>[] $attributes */
143
        $attributes = $parameter->getAttributes(LoggerChannel::class);
144
145
        return $attributes[0]?->newInstance()->name;
146
    }
147
}
148