Passed
Push — logger ( 1ad97d )
by Arnaud
03:04
created

ConsoleLogger::printProgressBar()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 7
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 9
rs 10
1
<?php
2
/**
3
 * This file is part of the Cecil/Cecil package.
4
 *
5
 * Copyright (c) Arnaud Ligny <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Cecil\Logger;
12
13
use Psr\Log\InvalidArgumentException;
14
use Psr\Log\LogLevel;
15
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
16
use Symfony\Component\Console\Helper\ProgressBar;
17
use Symfony\Component\Console\Output\OutputInterface;
18
19
class ConsoleLogger extends PrintLogger
20
{
21
    const ERROR = 'error';
22
    const WARNING = 'comment';
23
    const NOTICE = 'info';
24
    const INFO = 'text';
25
26
    protected $output;
27
    protected $verbosityLevelMap = [
28
        LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
29
        LogLevel::ALERT     => OutputInterface::VERBOSITY_NORMAL,
30
        LogLevel::CRITICAL  => OutputInterface::VERBOSITY_NORMAL,
31
        LogLevel::ERROR     => OutputInterface::VERBOSITY_NORMAL,
32
        LogLevel::WARNING   => OutputInterface::VERBOSITY_NORMAL,
33
        LogLevel::NOTICE    => OutputInterface::VERBOSITY_VERBOSE,
34
        LogLevel::INFO      => OutputInterface::VERBOSITY_VERY_VERBOSE,
35
        LogLevel::DEBUG     => OutputInterface::VERBOSITY_DEBUG,
36
    ];
37
    protected $formatLevelMap = [
38
        LogLevel::EMERGENCY => self::ERROR,
39
        LogLevel::ALERT     => self::ERROR,
40
        LogLevel::CRITICAL  => self::ERROR,
41
        LogLevel::ERROR     => self::ERROR,
42
        LogLevel::WARNING   => self::INFO,
43
        LogLevel::NOTICE    => self::NOTICE,
44
        LogLevel::INFO      => self::INFO,
45
        LogLevel::DEBUG     => self::INFO,
46
    ];
47
48
    /** @var ProgressBar */
49
    protected $progressBar = null;
50
    /** @var int */
51
    private $progressBarMax;
52
53
    public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = [])
54
    {
55
        $this->output = $output;
56
        $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
57
        $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     *
63
     * @return void
64
     */
65
    public function log($level, $message, array $context = [])
66
    {
67
        $output = $this->output;
68
        $outputStyle = new OutputFormatterStyle('white');
69
        $output->getFormatter()->setStyle('text', $outputStyle);
70
71
        // can use progress bar
72
        if ($output->isDecorated()) {
73
            array_replace_recursive($this->verbosityLevelMap, [
74
                LogLevel::NOTICE    => OutputInterface::VERBOSITY_NORMAL,
75
                LogLevel::INFO      => OutputInterface::VERBOSITY_VERBOSE,
76
            ]);
77
        }
78
79
        if (!isset($this->verbosityLevelMap[$level])) {
80
            throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
81
        }
82
83
        // steps progress bar
84
        if ($output->isDecorated()) {
85
            if ($output->getVerbosity() == OutputInterface::VERBOSITY_NORMAL && array_key_exists('step', $context)) {
86
                $this->printProgressBar($context['step'][0], $context['step'][1]);
87
88
                return;
89
            }
90
        }
91
92
        $pattern = '<%1$s>%3$s</%1$s>';
93
        if (array_key_exists('progress', $context)) {
94
            $pattern = '<%1$s>('.$context['progress'][0].'/'.$context['progress'][1].') %3$s</%1$s>';
95
96
            // progress bar
97
            if ($output->isDecorated()) {
98
                if ($output->getVerbosity() == OutputInterface::VERBOSITY_VERBOSE) {
99
                    $this->printProgressBar($context['progress'][0], $context['progress'][1]);
100
101
                    return;
102
                }
103
            }
104
        }
105
106
        $output->writeln(
107
            sprintf($pattern, $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)),
108
            $this->verbosityLevelMap[$level]
109
        );
110
    }
111
112
    /**
113
     * Prints the Progress Bar.
114
     *
115
     * @param int $itemsCount
116
     * @param int $itemsMax
117
     *
118
     * @return void
119
     */
120
    protected function printProgressBar(int $itemsCount, int $itemsMax): void
121
    {
122
        $this->createProgressBar($itemsMax);
123
        $this->progressBar->clear();
124
        $this->progressBar->setProgress($itemsCount);
125
        $this->progressBar->display();
126
        if ($itemsCount == $itemsMax) {
127
            $this->progressBar->finish();
128
            $this->output->writeln('');
129
        }
130
    }
131
132
    /**
133
     * Creates the Progress bar.
134
     *
135
     * @param int $max
136
     *
137
     * @return void
138
     */
139
    private function createProgressBar(int $max): void
140
    {
141
        if ($this->progressBar === null || $max != $this->progressBarMax) {
142
            $this->progressBarMax = $max;
143
            $this->progressBar = new ProgressBar($this->output, $max);
144
            $this->progressBar->setOverwrite(true);
145
            $this->progressBar->setFormat('%percent:3s%% [%bar%] %current%/%max%');
146
            $this->progressBar->setBarCharacter('#');
147
            $this->progressBar->setEmptyBarCharacter(' ');
148
            $this->progressBar->setProgressCharacter('#');
149
            $this->progressBar->setRedrawFrequency(1);
150
            $this->progressBar->start();
151
        }
152
    }
153
}
154