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

JBZoo / Cli / 7685763438

28 Jan 2024 12:35PM UTC coverage: 80.746% (-3.1%) from 83.803%
7685763438

push

github

web-flow
Add support for PHP 8.3 and update Symfony dependencies to ^6.4 (#24)

* Add support for PHP 8.3 and update Symfony dependencies to ^6.4
* Fix default value handling in CliCommand

0 of 3 new or added lines in 1 file covered. (0.0%)

41 existing lines in 5 files now uncovered.

952 of 1179 relevant lines covered (80.75%)

234.54 hits per line

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

86.42
/src/OutputMods/AbstractOutputMode.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\CliHelper;
21
use JBZoo\Cli\OutLvl;
22
use JBZoo\Cli\ProgressBars\AbstractProgressBar;
23
use Monolog\Formatter\NormalizerFormatter;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Output\ConsoleOutputInterface;
26
use Symfony\Component\Console\Output\OutputInterface;
27

28
use function JBZoo\Utils\bool;
29
use function JBZoo\Utils\isStrEmpty;
30

31
abstract class AbstractOutputMode
32
{
33
    protected CliApplication $application;
34

35
    protected float $startTimer;
36
    protected float $prevTime;
37
    protected int   $prevMemory;
38

39
    protected string $timestampFormat = 'Y-m-d\TH:i:s.uP';
40

41
    protected InputInterface  $input;
42
    protected OutputInterface $output;
43

44
    protected bool  $catchMode      = false;
45
    protected array $caughtMessages = [];
46

47
    protected array $extraContext = [];
48

49
    private bool $outputHasErrors = false;
50

51
    abstract public static function getName(): string;
52

53
    abstract public static function getDescription(): string;
54

55
    abstract public function createProgressBar(): AbstractProgressBar;
56

57
    abstract protected function printMessage(
58
        string $message = '',
59
        string $verboseLevel = OutLvl::DEFAULT,
60
        array $context = [],
61
    ): void;
62

63
    public function __construct(InputInterface $input, OutputInterface $output, CliApplication $application)
64
    {
65
        $this->prevMemory = \memory_get_usage(false);
876✔
66
        $this->startTimer = \microtime(true);
876✔
67
        $this->prevTime   = $this->startTimer;
876✔
68

69
        $this->application = $application;
876✔
70

71
        $this->input  = $input;
876✔
72
        $this->output = $output;
876✔
73

74
        CliHelper::setInstance($this);
876✔
75
    }
76

77
    public function getStartTime(): float
78
    {
79
        return $this->startTimer;
642✔
80
    }
81

82
    public function getInput(): InputInterface
83
    {
84
        return $this->input;
876✔
85
    }
86

87
    public function getOutput(): OutputInterface
88
    {
89
        return $this->output;
642✔
90
    }
91

92
    public function getErrOutput(): OutputInterface
93
    {
94
        if ($this->isStdoutOnly()) {
642✔
95
            return $this->output;
48✔
96
        }
97

98
        return $this->output instanceof ConsoleOutputInterface ? $this->output->getErrorOutput() : $this->output;
594✔
99
    }
100

101
    /**
102
     * Alias to write new line in std output.
103
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
104
     */
105
    public function _(
106
        null|bool|float|int|iterable|string $messages = '',
107
        string $verboseLevel = OutLvl::DEFAULT,
108
        array $context = [],
109
    ): void {
110
        $message = $this->prepareMessages($messages, $verboseLevel);
876✔
111
        $context = $this->prepareContext($context);
876✔
112

113
        if ($message === null) {
876✔
114
            return;
582✔
115
        }
116

117
        if (
118
            $this->catchMode
876✔
119
            && !bool(\preg_match('/^Working on ".*"\./', $message)) // hack for system messages
876✔
120
        ) {
121
            $this->caughtMessages[] = $message;
36✔
122

123
            return;
36✔
124
        }
125

126
        $this->printMessage($message, $verboseLevel, $context);
876✔
127
    }
128

129
    public function isOutputHasErrors(): bool
130
    {
131
        return $this->outputHasErrors;
744✔
132
    }
133

134
    public function isStdoutOnly(): bool
135
    {
136
        return bool($this->input->getOption('stdout-only'));
612✔
137
    }
138

139
    public function isDisplayProfiling(): bool
140
    {
141
        return bool($this->input->getOption('profile'));
612✔
142
    }
143

144
    public function isDisplayTimestamp(): bool
145
    {
146
        return bool($this->input->getOption('timestamp'));
612✔
147
    }
148

149
    public function isInfoLevel(): bool
150
    {
151
        return $this->getOutput()->isVerbose();
×
152
    }
153

154
    public function isWarningLevel(): bool
155
    {
156
        return $this->getOutput()->isVeryVerbose();
×
157
    }
158

159
    public function isDebugLevel(): bool
160
    {
161
        return $this->getOutput()->isDebug();
×
162
    }
163

164
    public function isProgressBarDisabled(): bool
165
    {
166
        return bool($this->getInput()->getOption('no-progress'));
144✔
167
    }
168

169
    public function onExecBefore(): void
170
    {
171
        // empty
UNCOV
172
    }
×
173

174
    public function onExecException(\Exception $exception): void
175
    {
176
        $this->_($exception->getMessage(), OutLvl::ERROR);
×
177
    }
178

179
    public function onExecAfter(int $exitCode, ?string $outputLevel = null): void
180
    {
181
        $outputLevel ??= OutLvl::DEBUG;
×
182
        if ($this->isDisplayProfiling()) {
×
183
            $outputLevel = OutLvl::DEFAULT;
×
184
        }
185

186
        $this->_('Exit code: ' . $exitCode, $outputLevel);
×
187
    }
188

189
    public function catchModeStart(): void
190
    {
191
        \ob_start();
216✔
192
        $this->catchMode = true;
216✔
193
    }
194

195
    public function catchModeFinish(): array
196
    {
197
        $echoOutput = \ob_get_clean();
204✔
198
        if (!isStrEmpty($echoOutput)) {
204✔
199
            $this->caughtMessages[] = $echoOutput;
12✔
200
        }
201

202
        $this->catchMode = false;
204✔
203

204
        $caughtMessages = $this->caughtMessages;
204✔
205

206
        $this->caughtMessages = [];
204✔
207

208
        return $caughtMessages;
204✔
209
    }
210

211
    public function appendExtraContext(array $context): void
212
    {
213
        $this->extraContext = CliHelper::arrayMergeRecursiveDistinct($this->extraContext, $context);
18✔
214
    }
215

216
    public function getExtraContext(): array
217
    {
218
        return $this->extraContext;
876✔
219
    }
220

221
    public function setExtraContext(array $context): void
222
    {
223
        $this->extraContext = $context;
×
224
    }
225

226
    /**
227
     * @deprecated
228
     */
229
    public static function getInstance(): self
230
    {
231
        return CliHelper::getInstance();
×
232
    }
233

234
    /**
235
     * @SuppressWarnings(PHPMD.Superglobals)
236
     */
237
    protected function getProfileInfo(): array
238
    {
239
        $currentMemory = \memory_get_usage(false);
270✔
240
        $currentTime   = \microtime(true);
270✔
241

242
        $startTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? 0.0;
270✔
243

244
        $result = [
270✔
245
            'memory_usage_real' => \memory_get_usage(true),
270✔
246
            'memory_usage'      => $currentMemory,
270✔
247
            'memory_usage_diff' => $currentMemory - $this->prevMemory,
270✔
248
            'memory_peak_real'  => \memory_get_peak_usage(true),
270✔
249
            'memory_peak'       => \memory_get_peak_usage(false),
270✔
250
            'time_total_ms'     => \round(1000 * ($currentTime - $startTime), 3),
270✔
251
            'time_diff_ms'      => \round(1000 * ($currentTime - $this->prevTime), 3),
270✔
252
        ];
270✔
253

254
        $this->prevTime   = $currentTime;
270✔
255
        $this->prevMemory = $currentMemory;
270✔
256

257
        return $result;
270✔
258
    }
259

260
    protected function prepareMessages(null|bool|float|int|iterable|string $messages, string $verboseLevel): ?string
261
    {
262
        $verboseLevel = \strtolower(\trim($verboseLevel));
876✔
263

264
        if (\is_iterable($messages)) {
876✔
265
            foreach ($messages as $message) {
582✔
266
                $this->_($message, $verboseLevel);
582✔
267
            }
268

269
            return null;
582✔
270
        }
271

272
        if ($messages === null) {
876✔
273
            $messages = 'null';
12✔
274
        } elseif (\is_bool($messages)) {
876✔
275
            $messages = $messages ? 'true' : 'false';
12✔
276
        }
277

278
        $messages = (string)$messages;
876✔
279

280
        if (\str_contains($messages, "\n")) {
876✔
281
            $this->_(\explode("\n", $messages), $verboseLevel);
216✔
282

283
            return null;
216✔
284
        }
285

286
        return $messages;
876✔
287
    }
288

289
    protected function prepareContext(array $context): array
290
    {
291
        $resultContext = \array_merge($this->getExtraContext(), $context);
876✔
292

293
        return (array)(new NormalizerFormatter())->normalizeValue($resultContext);
876✔
294
    }
295

296
    protected function markOutputHasErrors(bool $hasError = true): void
297
    {
298
        $this->outputHasErrors = $hasError;
144✔
299
    }
300
}
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

© 2025 Coveralls, Inc