Passed
Pull Request — master (#1102)
by Aleksei
11:46 queued 01:49
created

LogFactory::extractChannelAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
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\Attribute\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
    private readonly HandlerInterface $eventHandler;
30
31 22
    public function __construct(
32
        private readonly MonologConfig $config,
33
        ListenerRegistryInterface $listenerRegistry,
34
        private readonly FactoryInterface $factory
35
    ) {
36 22
        $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
    }
38
39 22
    public function getLogger(string $channel = null): LoggerInterface
40
    {
41 22
        $default = $this->config->getDefault();
42
43 22
        if ($channel === null || $channel === $default) {
44 7
            if ($this->default !== null) {
45
                // we should use only one default logger per system
46 4
                return $this->default;
47
            }
48
49 7
            return $this->default = new Logger(
50 7
                $default,
51 7
                $this->getHandlers($default),
52 7
                $this->getProcessors($default)
53 7
            );
54
        }
55
56 17
        return new Logger(
57 17
            $channel,
58 17
            $this->getHandlers($channel),
59 17
            $this->getProcessors($channel)
60 17
        );
61
    }
62
63 3
    public function createInjection(
64
        \ReflectionClass $class,
65
        \ReflectionParameter|null|string $context = null
66
    ): LoggerInterface {
67 3
        $channel = \is_object($context) ? $this->extractChannelAttribute($context) : null;
68
69
        // always return default logger as injection
70 3
        return $this->getLogger($channel);
71
    }
72
73 1
    public function reset(): void
74
    {
75 1
        if ($this->default instanceof ResettableInterface) {
76 1
            $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
    /**
81
     * Get list of channel specific handlers.
82
     *
83
     *
84
     * @throws ConfigException
85
     */
86 22
    protected function getHandlers(string $channel): array
87
    {
88
        // always include default handler
89 22
        $handlers = [];
90
91 22
        foreach ($this->config->getHandlers($channel) as $handler) {
92 6
            if (!$handler instanceof Autowire) {
93 2
                $handlers[] = $handler;
94 2
                continue;
95
            }
96
97
            try {
98 4
                $handlers[] = $handler->resolve($this->factory);
99
            } catch (ContainerExceptionInterface $e) {
100
                throw new ConfigException($e->getMessage(), $e->getCode(), $e);
101
            }
102
        }
103
104 21
        $handlers[] = $this->eventHandler;
105
106 21
        return $handlers;
107
    }
108
109
    /**
110
     * Get list of channel specific log processors.
111
     *
112
     * @return callable[]
113
     */
114 21
    protected function getProcessors(string $channel): array
115
    {
116 21
        $processors = [];
117 21
        foreach ($this->config->getProcessors($channel) as $processor) {
118 6
            if (!$processor instanceof Autowire) {
119 3
                $processors[] = $processor;
120 3
                continue;
121
            }
122
123
            try {
124 3
                $processors[] = $processor->resolve($this->factory);
125
            } catch (ContainerExceptionInterface $e) {
126
                throw new ConfigException($e->getMessage(), $e->getCode(), $e);
127
            }
128
        }
129
130 20
        if ($processors === []) {
131 14
            $processors[] = new PsrLogMessageProcessor();
132
        }
133
134 20
        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 1
    private function extractChannelAttribute(\ReflectionParameter $parameter): ?string
141
    {
142
        /** @var ReflectionAttribute<LoggerChannel>[] $attributes */
143 1
        $attributes = $parameter->getAttributes(LoggerChannel::class);
144
145 1
        return $attributes[0]?->newInstance()->name;
146
    }
147
}
148