• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JBZoo / Cli / 6112474169

02 Sep 2023 11:11PM UTC coverage: 83.848% (+0.6%) from 83.272%
6112474169

push

github

web-flow
Fixes in profiling output (#20)

71 of 71 new or added lines in 3 files covered. (100.0%)

950 of 1133 relevant lines covered (83.85%)

138.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.46
/src/OutputMods/Text.php
1
<?php
2

3
/**
4
 * JBZoo Toolbox - Cli.
5
 *
6
 * This file is part of the JBZoo Toolbox project.
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license    MIT
11
 * @copyright  Copyright (C) JBZoo.com, All rights reserved.
12
 * @see        https://github.com/JBZoo/Cli
13
 */
14

15
declare(strict_types=1);
16

17
namespace JBZoo\Cli\OutputMods;
18

19
use JBZoo\Cli\CliApplication;
20
use JBZoo\Cli\Exception;
21
use JBZoo\Cli\OutLvl;
22
use JBZoo\Cli\ProgressBars\AbstractProgressBar;
23
use JBZoo\Cli\ProgressBars\ProgressBarSymfony;
24
use JBZoo\Utils\FS;
25
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
26
use Symfony\Component\Console\Input\InputInterface;
27
use Symfony\Component\Console\Output\ConsoleOutput;
28
use Symfony\Component\Console\Output\OutputInterface;
29

30
use function JBZoo\Utils\bool;
31

32
class Text extends AbstractOutputMode
33
{
34
    public function __construct(InputInterface $input, OutputInterface $output, CliApplication $application)
35
    {
36
        parent::__construct($input, $output, $application);
428✔
37

38
        self::addOutputStyles($this->getOutput());
428✔
39
        self::addOutputStyles($this->getErrOutput());
428✔
40

41
        if ($this->output instanceof ConsoleOutput && $this->isStdoutOnly()) {
428✔
42
            $this->output->setErrorOutput($this->output);
32✔
43
        }
44
    }
45

46
    public function onExecBefore(): void
47
    {
48
        $this->_('Working Directory is <i>' . \getcwd() . '</i>', OutLvl::DEBUG);
428✔
49
    }
50

51
    public function onExecAfter(int $exitCode, ?string $outputLevel = null): void
52
    {
53
        $outputLevel ??= OutLvl::DEBUG;
428✔
54
        if ($this->isDisplayProfiling()) {
428✔
55
            $outputLevel = OutLvl::DEFAULT;
24✔
56
        }
57

58
        $totalTime = \number_format(\microtime(true) - $this->getStartTime(), 3);
428✔
59
        $curMemory = FS::format(\memory_get_usage(false));
428✔
60
        $maxMemory = FS::format(\memory_get_peak_usage(true));
428✔
61

62
        $this->_(
428✔
63
            \implode('; ', [
428✔
64
                "Memory Usage/Peak: <green>{$curMemory}</green>/<green>{$maxMemory}</green>",
428✔
65
                "Execution Time: <green>{$totalTime} sec</green>",
428✔
66
            ]),
214✔
67
            $outputLevel,
214✔
68
        );
214✔
69

70
        $this->_("Exit Code is \"{$exitCode}\"", $outputLevel);
428✔
71
    }
72

73
    public function onExecException(\Exception $exception): void
74
    {
75
        if (bool($this->getInput()->getOption('mute-errors'))) {
68✔
76
            $this->_($exception->getMessage(), OutLvl::EXCEPTION);
8✔
77
        }
78
    }
79

80
    public function createProgressBar(): AbstractProgressBar
81
    {
82
        return new ProgressBarSymfony($this);
92✔
83
    }
84

85
    public static function getName(): string
86
    {
87
        return 'text';
584✔
88
    }
89

90
    public static function getDescription(): string
91
    {
92
        return 'Default text output format, userfriendly and easy to read.';
584✔
93
    }
94

95
    public static function addOutputStyles(OutputInterface $output): void
96
    {
97
        $formatter    = $output->getFormatter();
428✔
98
        $defaultColor = 'default';
428✔
99

100
        $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', $defaultColor];
428✔
101

102
        foreach ($colors as $color) {
428✔
103
            $formatter->setStyle($color, new OutputFormatterStyle($color));
428✔
104
            $formatter->setStyle("{$color}-b", new OutputFormatterStyle($color, null, ['bold']));
428✔
105
            $formatter->setStyle("{$color}-u", new OutputFormatterStyle($color, null, ['underscore']));
428✔
106
            $formatter->setStyle("{$color}-r", new OutputFormatterStyle($color, null, ['reverse']));
428✔
107
            $formatter->setStyle("{$color}-bg", new OutputFormatterStyle(null, $color));
428✔
108
            $formatter->setStyle("{$color}-bl", new OutputFormatterStyle($color, null, ['blink']));
428✔
109
        }
110

111
        $formatter->setStyle('bl', new OutputFormatterStyle($defaultColor, null, ['blink']));
428✔
112
        $formatter->setStyle('b', new OutputFormatterStyle($defaultColor, null, ['bold']));
428✔
113
        $formatter->setStyle('u', new OutputFormatterStyle($defaultColor, null, ['underscore']));
428✔
114
        $formatter->setStyle('r', new OutputFormatterStyle(null, null, ['reverse']));
428✔
115
        $formatter->setStyle('bg', new OutputFormatterStyle('black', 'white'));
428✔
116

117
        // Aliases
118
        $formatter->setStyle('i', new OutputFormatterStyle('green')); // Alias for <info>
428✔
119
        $formatter->setStyle('c', new OutputFormatterStyle('yellow')); // Alias for <comment>
428✔
120
        $formatter->setStyle('q', new OutputFormatterStyle('black', 'cyan')); // Alias for <question>
428✔
121
        $formatter->setStyle('e', new OutputFormatterStyle('white', 'red')); // Alias for <error>
428✔
122

123
        $output->setFormatter($formatter);
428✔
124
    }
125

126
    /**
127
     * Alias to write new line in std output.
128
     */
129
    protected function printMessage(
130
        string $message = '',
131
        string $verboseLevel = OutLvl::DEFAULT,
132
        array $context = [],
133
    ): void {
134
        if (\count($context) > 0) {
428✔
135
            $message .= ' ' . \json_encode($context, \JSON_THROW_ON_ERROR);
104✔
136
        }
137

138
        $profilePrefix = '';
428✔
139

140
        if ($this->isDisplayTimestamp()) {
428✔
141
            $timestamp = (new \DateTimeImmutable())->format($this->timestampFormat);
24✔
142
            $profilePrefix .= "<green>[</green>{$timestamp}<green>]</green> ";
24✔
143
        }
144

145
        $executePrint  = false;
428✔
146
        $printCallback = null;
428✔
147
        $vNormal       = OutputInterface::VERBOSITY_NORMAL;
428✔
148

149
        if ($verboseLevel === OutLvl::DEFAULT) {
428✔
150
            $executePrint  = $this->showMessage($vNormal);
408✔
151
            $printCallback = function (string $profilePrefix) use ($message, $vNormal): void {
408✔
152
                $this->getOutput()->writeln($profilePrefix . $message, $vNormal);
400✔
153
            };
204✔
154
        } elseif ($verboseLevel === OutLvl::V) {
428✔
155
            $executePrint  = $this->showMessage(OutputInterface::VERBOSITY_VERBOSE);
96✔
156
            $printCallback = function (string $profilePrefix) use ($message): void {
96✔
157
                $this->getOutput()->writeln($profilePrefix . $message, OutputInterface::VERBOSITY_VERBOSE);
44✔
158
            };
48✔
159
        } elseif ($verboseLevel === OutLvl::VV) {
428✔
160
            $executePrint  = $this->showMessage(OutputInterface::VERBOSITY_VERY_VERBOSE);
112✔
161
            $printCallback = function (string $profilePrefix) use ($message): void {
112✔
162
                $this->getOutput()->writeln($profilePrefix . $message, OutputInterface::VERBOSITY_VERY_VERBOSE);
28✔
163
            };
56✔
164
        } elseif ($verboseLevel === OutLvl::VVV) {
428✔
165
            $executePrint  = $this->showMessage(OutputInterface::VERBOSITY_DEBUG);
428✔
166
            $printCallback = function (string $profilePrefix) use ($message): void {
428✔
167
                $this->getOutput()->writeln($profilePrefix . $message, OutputInterface::VERBOSITY_DEBUG);
8✔
168
            };
214✔
169
        } elseif ($verboseLevel === OutLvl::Q) {
428✔
170
            $executePrint  = $this->showMessage(OutputInterface::VERBOSITY_QUIET);
172✔
171
            $printCallback = function (string $profilePrefix) use ($message): void {
172✔
172
                $this->getOutput()->writeln(
172✔
173
                    $profilePrefix . $message,
172✔
174
                    OutputInterface::VERBOSITY_QUIET,
86✔
175
                ); // Show ALWAYS!
86✔
176
            };
86✔
177
        } elseif ($verboseLevel === OutLvl::LEGACY) {
428✔
178
            $this->_("<yellow>Legacy Output:</yellow> {$message}");
96✔
179
        } elseif ($verboseLevel === OutLvl::DEBUG) {
428✔
180
            $this->_("<magenta>Debug:</magenta> {$message}", OutLvl::VVV);
428✔
181
        } elseif ($verboseLevel === OutLvl::WARNING) {
112✔
182
            $this->_("<yellow>Warning:</yellow> {$message}", OutLvl::VV);
112✔
183
        } elseif ($verboseLevel === OutLvl::INFO) {
96✔
184
            $this->_("<blue>Info:</blue> {$message}", OutLvl::V);
96✔
185
        } elseif ($verboseLevel === OutLvl::E) {
96✔
186
            $executePrint  = $this->showMessage($vNormal);
96✔
187
            $printCallback = function (string $profilePrefix) use ($message, $vNormal): void {
96✔
188
                $this->markOutputHasErrors(true);
88✔
189
                $this->getErrOutput()->writeln($profilePrefix . $message, $vNormal);
88✔
190
            };
48✔
191
        } elseif ($verboseLevel === OutLvl::ERROR) {
96✔
192
            $executePrint  = $this->showMessage($vNormal);
96✔
193
            $printCallback = function (string $profilePrefix) use ($message, $vNormal): void {
96✔
194
                $this->markOutputHasErrors(true);
88✔
195
                $this->getErrOutput()->writeln("{$profilePrefix}<red-bg>Error:</red-bg> {$message}", $vNormal);
88✔
196
            };
48✔
197
        } elseif ($verboseLevel === OutLvl::EXCEPTION) {
96✔
198
            $executePrint  = $this->showMessage($vNormal);
96✔
199
            $printCallback = function (string $profilePrefix) use ($message, $vNormal): void {
96✔
200
                $this->markOutputHasErrors(true);
88✔
201
                $this->getErrOutput()->writeln(
88✔
202
                    "{$profilePrefix}<red-bg>Muted Exception:</red-bg> {$message}",
88✔
203
                    $vNormal,
44✔
204
                );
44✔
205
            };
48✔
206
        } else {
207
            throw new Exception("Undefined verbose level: \"{$verboseLevel}\"");
×
208
        }
209

210
        if ($executePrint && $printCallback !== null) {
428✔
211
            if ($this->isDisplayProfiling()) {
408✔
212
                $profile    = $this->getProfileInfo();
24✔
213
                $memoryDiff = FS::format($profile['memory_usage_diff']);
24✔
214
                $totalTime  = \number_format($profile['time_diff_ms'] / 1000, 3);
24✔
215
                $curMemory  = \str_pad($memoryDiff, 10, ' ', \STR_PAD_LEFT);
24✔
216
                $profilePrefix .= "<green>[</green>+{$totalTime}s<green>/</green>{$curMemory}<green>]</green> ";
24✔
217
            }
218
            $printCallback($profilePrefix);
408✔
219
        }
220
    }
221

222
    private function showMessage(int $selectedVerbosity): bool
223
    {
224
        $verbosities = OutputInterface::VERBOSITY_QUIET
428✔
225
            | OutputInterface::VERBOSITY_NORMAL
214✔
226
            | OutputInterface::VERBOSITY_VERBOSE
214✔
227
            | OutputInterface::VERBOSITY_VERY_VERBOSE
214✔
228
            | OutputInterface::VERBOSITY_DEBUG;
214✔
229

230
        $verbosity = ($verbosities & $selectedVerbosity) > 0
428✔
231
            ? $verbosities & $selectedVerbosity
428✔
232
            : OutputInterface::VERBOSITY_NORMAL;
×
233

234
        $curVerbose = $this->getOutput()->getVerbosity();
428✔
235

236
        return $verbosity <= $curVerbose;
428✔
237
    }
238
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc