ProgressBarConsoleLogger   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Test Coverage

Coverage 94.74%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 32
c 1
b 0
f 0
dl 0
loc 95
ccs 36
cts 38
cp 0.9474
rs 10
wmc 13

6 Methods

Rating   Name   Duplication   Size   Complexity  
A logToProgressBar() 0 20 3
A __construct() 0 3 1
A replaceMessagePlaceholdersWithContextData() 0 12 5
A log() 0 10 2
A registerProgressBar() 0 5 1
A clearProgressLoggingFromContext() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the EnhancesConsoleLogging package.
7
 *
8
 * (c) Niels Nijens <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Nijens\EnhancesConsoleLogging\ProgressBar;
15
16
use Psr\Log\AbstractLogger;
17
use Psr\Log\LoggerInterface;
18
use Symfony\Component\Console\Helper\ProgressBar;
19
20
/**
21
 * Allows logged messages to be displayed with a {@see ProgressBar}.
22
 *
23
 * The context allows control of the progression of the progress bar with the following keys:
24
 * - {@see LogContext::PROGRESS_IDENTIFIER_KEY}: The identifier of the progress bar
25
 * - {@see LogContext::PROGRESS_INCREMENT_KEY}: Increments the max steps of the progress bar
26
 * - {@see LogContext::PROGRESS_ADVANCE_KEY}: Advances the progress bar
27
 *
28
 * @author Niels Nijens <[email protected]>
29
 */
30
class ProgressBarConsoleLogger extends AbstractLogger implements ProgressBarConsoleLoggerInterface
31
{
32
    /**
33
     * @var ProgressBar[]
34
     */
35
    private $progressBars = [];
36
37
    /**
38
     * @var LoggerInterface|null
39
     */
40
    private $logger;
41
42
    /**
43
     * Constructs a new {@see ProgressBarConsoleLogger} instance.
44
     */
45 7
    public function __construct(LoggerInterface $logger = null)
46
    {
47 7
        $this->logger = $logger;
48 7
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 6
    public function registerProgressBar(string $identifier, ProgressBar $progressBar): void
54
    {
55 6
        $progressBar->setMessage('');
56
57 6
        $this->progressBars[$identifier] = $progressBar;
58 6
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 6
    public function log($level, $message, array $context = [])
64
    {
65 6
        $this->logToProgressBar($level, $message, $context);
66 6
        $this->clearProgressLoggingFromContext($context);
67
68 6
        if ($this->logger === null) {
69
            return;
70
        }
71
72 6
        $this->logger->log($level, $message, $context);
73 6
    }
74
75
    /**
76
     * Logs the message to the {@see ProgressBar} provided in the context.
77
     */
78 6
    private function logToProgressBar(string $level, string $message, array $context): void
79
    {
80 6
        if (isset($context[self::PROGRESS_IDENTIFIER_KEY]) === false) {
81 1
            return;
82
        }
83
84 5
        if (isset($this->progressBars[$context[self::PROGRESS_IDENTIFIER_KEY]]) === false) {
85 2
            return;
86
        }
87
88 3
        $progressBar = $this->progressBars[$context[self::PROGRESS_IDENTIFIER_KEY]];
89 3
        $progressBar->setMessage(
90 3
            sprintf(
91 3
                '<%s>%s</>',
92
                $level,
93 3
                $this->replaceMessagePlaceholdersWithContextData($message, $context)
94
            )
95
        );
96 3
        $progressBar->setMaxSteps($progressBar->getMaxSteps() + ($context[self::PROGRESS_INCREMENT_KEY] ?? 0));
97 3
        $progressBar->advance($context[self::PROGRESS_ADVANCE_KEY] ?? 0);
98 3
    }
99
100
    /**
101
     * Replaces placeholders in the message with data from the context.
102
     */
103 3
    private function replaceMessagePlaceholdersWithContextData(string $message, array $context): string
104
    {
105 3
        $replace = [];
106 3
        foreach ($context as $key => $value) {
107 3
            if (is_array($value) || (is_object($value) && method_exists($value, '__toString') === false)) {
108
                continue;
109
            }
110
111 3
            $replace['{'.$key.'}'] = strval($value);
112
        }
113
114 3
        return strtr($message, $replace);
115
    }
116
117
    /**
118
     * Clears the progress logging keys from the context, so this isn't passed along to another logger.
119
     */
120 6
    private function clearProgressLoggingFromContext(array &$context): void
121
    {
122 6
        unset($context[self::PROGRESS_IDENTIFIER_KEY]);
123 6
        unset($context[self::PROGRESS_INCREMENT_KEY]);
124 6
        unset($context[self::PROGRESS_ADVANCE_KEY]);
125 6
    }
126
}
127