Test Failed
Push — master ( a85b44...a25a4c )
by Divine Niiquaye
11:17
created

MonologServiceProvider::translateLevel()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 23
rs 9.9
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of DivineNii opensource projects.
7
 *
8
 * PHP version 7.4 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 DivineNii (https://divinenii.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Rade\Provider;
19
20
use Biurad\Events\TraceableEventDispatcher;
21
use Monolog\ErrorHandler;
22
use Monolog\Handler;
23
use Monolog\Logger;
24
use Rade\API\BootableProviderInterface;
25
use Rade\API\EventListenerProviderInterface;
26
use Rade\Application;
27
use Rade\DI\Container;
28
use Rade\DI\ServiceProviderInterface;
29
use Rade\EventListener\LogListener;
30
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
31
use Symfony\Component\Config\Definition\ConfigurationInterface;
32
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
33
34
/**
35
 * Monolog Provider.
36
 *
37
 * @author Fabien Potencier <[email protected]>
38
 */
39
class MonologServiceProvider implements ConfigurationInterface, ServiceProviderInterface, BootableProviderInterface, EventListenerProviderInterface
40
{
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function getName(): string
45
    {
46
        return 'monolog';
47
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function getConfigTreeBuilder(): TreeBuilder
53
    {
54
        $treeBuilder = new TreeBuilder($this->getName());
55
56
        $treeBuilder->getRootNode()
57
            ->children()
58
                ->scalarNode('name')->defaultValue('app')->end()
59
                ->booleanNode('bubble')->defaultTrue()->end()
60
                ->enumNode('level')
61
                    ->values(
62
                        [
63
                            Logger::DEBUG,
64
                            Logger::INFO,
65
                            Logger::NOTICE,
66
                            Logger::ALERT,
67
                            Logger::WARNING,
68
                            Logger::ERROR,
69
                            Logger::CRITICAL,
70
                            Logger::EMERGENCY,
71
                        ]
72
                    )
73
                    ->defaultValue(Logger::DEBUG)
74
                ->end()
75
                ->scalarNode('permission')->defaultNull()->end()
76
                ->scalarNode('exception_logger_filter')->defaultNull()->end()
77
                ->scalarNode('logfile')->defaultNull()->end()
78
            ->end();
79
80
        return $treeBuilder;
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function register(Container $app): void
87
    {
88
        $config = $app->parameters['monolog'] ?? [];
89
90
        $app['monolog'] = function (Container $app) use ($config): Logger {
91
            $log     = new Logger($config['name']);
92
            $handler = new Handler\GroupHandler($app['monolog.handlers']);
93
94
            $log->pushHandler($handler);
95
96
            return $log;
97
        };
98
99
        $app->alias('logger', 'monolog');
100
101
        $app['monolog.formatter'] = new \Monolog\Formatter\LineFormatter();
102
        $app['monolog.handler']   = $defaultHandler = function (Container $app) use ($config): Handler\StreamHandler {
103
            $level = MonologServiceProvider::translateLevel($config['level']);
104
105
            if (null !== $config['logfile']) {
106
                $config['logfile'] = $app->parameters['project_dir'] . $config['logfile'];
107
            }
108
109
            $handler = new Handler\StreamHandler($config['logfile'], $level, $config['bubble'], $config['permission']);
110
            $handler->setFormatter($app['monolog.formatter']);
111
112
            return $handler;
113
        };
114
115
        $app['monolog.handlers'] = function (Container $app) use ($config, $defaultHandler) {
116
            $handlers = [];
117
118
            // enables the default handler if a logfile was set or the monolog.handler service was redefined
119
            if ($config['logfile'] || $defaultHandler !== $app->get('monolog.handler')) {
120
                $handlers[] = $app['monolog.handler'];
121
            }
122
123
            return $handlers;
124
        };
125
126
        if ($app->parameters['debug']) {
127
            $app->extend(
128
                'dispatcher',
129
                function (EventDispatcherInterface $dispatcher, Container $app): TraceableEventDispatcher {
130
                    return new TraceableEventDispatcher($dispatcher, $app['logger']);
131
                }
132
            );
133
        }
134
        $app['monolog.listener'] = $app->call(LogListener::class, [1 => $config['exception_logger_filter']]);
135
136
        unset($app->parameters['monolog']);
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142
    public function boot(Application $app): void
143
    {
144
        if (!$app->parameters['debug']) {
145
            ErrorHandler::register($app['monolog']);
146
        }
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function subscribe(Container $app, EventDispatcherInterface $dispatcher): void
153
    {
154
        $dispatcher->addSubscriber($app['monolog.listener']);
155
    }
156
157
    public static function translateLevel($name)
158
    {
159
        // level is already translated to logger constant, return as-is
160
        if (\is_int($name)) {
161
            return $name;
162
        }
163
164
        $psrLevel = Logger::toMonologLevel($name);
165
166
        if (\is_int($psrLevel)) {
0 ignored issues
show
introduced by
The condition is_int($psrLevel) is always true.
Loading history...
167
            return $psrLevel;
168
        }
169
170
        $levels = Logger::getLevels();
171
        $upper  = \strtoupper($name);
172
173
        if (!isset($levels[$upper])) {
174
            throw new \InvalidArgumentException(
175
                "Provided logging level '$name' does not exist. Must be a valid monolog logging level."
176
            );
177
        }
178
179
        return $levels[$upper];
180
    }
181
}
182