Completed
Push — master ( a9b395...9b107f )
by Sebastian
10:30
created

PrinterCli::onCheckFailed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2
Metric Value
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 1
crap 2
1
<?php
2
namespace phpbu\App\Result;
3
4
use InvalidArgumentException;
5
use phpbu\App\Event;
6
use phpbu\App\Listener;
7
use phpbu\App\Result;
8
use phpbu\App\Util;
9
use phpbu\App\Version;
10
use PHP_Timer;
11
use SebastianBergmann\Environment\Console;
12
13
/**
14
 * Default app output.
15
 *
16
 * Heavily 'inspired' by Sebastian Bergmann's phpunit PHPUnit_TextUI_ResultPrinter.
17
 *
18
 * @package    phpbu
19
 * @subpackage Result
20
 * @author     Sebastian Feldmann <[email protected]>
21
 * @copyright  Sebastian Feldmann <[email protected]>
22
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
23
 * @link       http://phpbu.de/
24
 * @since      Class available since Release 1.0.0
25
 */
26
class PrinterCli implements Listener
27
{
28
    /**
29
     * Verbose output
30
     *
31
     * @var boolean
32
     */
33
    protected $verbose;
34
35
    /**
36
     * Output with colors
37
     *
38
     * @var boolean
39
     */
40
    protected $colors;
41
42
    /**
43
     * Is debug active
44
     *
45
     * @var boolean
46
     */
47
    protected $debug;
48
49
    /**
50
     * Amount of executed backups
51
     *
52
     * @var integer
53
     */
54
    private $numBackups = 0;
55
56
    /**
57
     * Amount of executed checks
58
     *
59
     * @var integer
60
     */
61
    private $numChecks = 0;
62
63
    /**
64
     * Amount of executed crypts
65
     *
66
     * @var integer
67
     */
68
    private $numCrypts = 0;
69
70
    /**
71
     * Amount of executed Syncs
72
     *
73
     * @var integer
74
     */
75
    private $numSyncs = 0;
76
77
    /**
78
     * Amount of executed Cleanups
79
     *
80
     * @var integer
81
     */
82
    private $numCleanups = 0;
83
84
    /**
85
     * Returns an array of event names this subscriber wants to listen to.
86
     *
87
     * The array keys are event names and the value can be:
88
     *
89
     *  * The method name to call (priority defaults to 0)
90
     *  * An array composed of the method name to call and the priority
91
     *  * An array of arrays composed of the method names to call and respective
92
     *    priorities, or 0 if unset
93
     *
94
     * @return array The event names to listen to
95
     */
96
    public static function getSubscribedEvents()
97
    {
98
        return array(
99
            'phpbu.debug'           => 'onDebug',
100
            'phpbu.app_start'       => 'onPhpbuStart',
101
            'phpbu.backup_start'    => 'onBackupStart',
102
            'phpbu.backup_failed'   => 'onBackupFailed',
103
            'phpbu.backup_end'      => 'onBackupEnd',
104
            'phpbu.check_start'     => 'onCheckStart',
105
            'phpbu.check_failed'    => 'onCheckFailed',
106
            'phpbu.check_end'       => 'onCheckEnd',
107
            'phpbu.crypt_start'     => 'onCryptStart',
108
            'phpbu.crypt_skipped'   => 'onCryptSkipped',
109
            'phpbu.crypt_failed'    => 'onCryptFailed',
110
            'phpbu.crypt_end'       => 'onCryptEnd',
111
            'phpbu.sync_start'      => 'onSyncStart',
112
            'phpbu.sync_skipped'    => 'onSyncSkipped',
113 2
            'phpbu.sync_failed'     => 'onSyncFailed',
114
            'phpbu.sync_end'        => 'onSyncEnd',
115
            'phpbu.cleanup_start'   => 'onCleanupStart',
116 2
            'phpbu.cleanup_skipped' => 'onCleanupSkipped',
117 2
            'phpbu.cleanup_failed'  => 'onCleanupFailed',
118 2
            'phpbu.cleanup_end'     => 'onCleanupEnd',
119 2
            'phpbu.app_end'         => 'onPhpbuEnd',
120 2
        );
121 2
    }
122 2
123 2
    /**
124 2
     * Constructor
125 2
     *
126 2
     * @param  boolean $verbose
127 2
     * @param  boolean $colors
128 2
     * @param  boolean $debug
129 2
     * @throws \InvalidArgumentException
130 2
     */
131 2
    public function __construct($verbose = false, $colors = false, $debug = false)
132 2
    {
133 2
        if (!is_bool($verbose)) {
134 2
            throw new InvalidArgumentException('Expected $verbose to be of type boolean');
135 2
        }
136 2
        if (!is_bool($colors)) {
137 2
            throw new InvalidArgumentException('Expected $colors to be of type boolean');
138
        }
139
        if (!is_bool($debug)) {
140
            throw new InvalidArgumentException('Expected $debug to be of type boolean');
141
        }
142
143
        $this->debug   = $debug;
144
        $this->verbose = $verbose;
145
        $console       = new Console;
146
        $this->colors  = $colors && $console->hasColorSupport();
147
    }
148 30
149
    /**
150 30
     * phpbu start event.
151 29
     *
152 29
     * @param \phpbu\App\Event\App\Start $event
153 1
     */
154
    public function onPhpbuStart(Event\App\Start $event)
155
    {
156 29
        $configuration = $event->getConfiguration();
157 28
        $this->write(
158 28
            Version::getVersionString() . PHP_EOL .
159 28
            PHP_EOL .
160 1
            'Configuration read from ' . $configuration->getFilename() . PHP_EOL .
161
            PHP_EOL
162
        );
163 28
    }
164 27
165 27
    /**
166 1
     * Backup start event.
167
     *
168 27
     * @param \phpbu\App\Event\Backup\Start $event
169
     */
170
    public function onBackupStart(Event\Backup\Start $event)
171
    {
172
        $backup = $event->getConfiguration();
173
        $this->numBackups++;
174
        if ($this->debug) {
175 1
            $this->writeWithAsterisk('backup: [' . $backup->getSource()->type . '] ');
176
        }
177 1
    }
178 1
179 1
    /**
180 1
     * Backup failed event.
181 1
     *
182
     * @param \phpbu\App\Event\Backup\Failed $event
183 1
     */
184 1
    public function onBackupFailed(Event\Backup\Failed $event)
185
    {
186
        if ($this->debug) {
187
            $this->writeWithColor('fg-white, bg-red, bold', 'failed' . PHP_EOL);
188
        }
189
    }
190
191 3
    /**
192
     * Backup end event.
193 3
     *
194 3
     * @param \phpbu\App\Event\Backup\End $event
195 3
     */
196 2
    public function onBackupEnd(Event\Backup\End $event)
197 2
    {
198 3
        if ($this->debug) {
199
            $this->writeWithColor('fg-black, bg-green', 'ok' . PHP_EOL);
200
        }
201
    }
202
203
    /**
204
     * Check start event.
205 1
     *
206
     * @param \phpbu\App\Event\Check\Start $event
207 1
     */
208 1
    public function onCheckStart(Event\Check\Start $event)
209 1
    {
210
        $check = $event->getConfiguration();
211 1
        $this->numChecks++;
212 1
        if ($this->debug) {
213 1
            $this->writeWithAsterisk('check: [' . $check->type . '] ');
214
        }
215
    }
216
217
    /**
218
     * Check failed event.
219
     *
220 2
     * @param \phpbu\App\Event\Check\Failed $event
221
     */
222 2
    public function onCheckFailed(Event\Check\Failed $event)
223 1
    {
224 1
        if ($this->debug) {
225 2
            $this->writeWithColor('fg-white, bg-red, bold', 'failed' . PHP_EOL);
226
        }
227
    }
228
229
    /**
230
     * Check end event.
231
     *
232 3
     * @param \phpbu\App\Event\Check\End $event
233
     */
234 3
    public function onCheckEnd(Event\Check\End $event)
235 3
    {
236 3
        if ($this->debug) {
237 2
            $this->writeWithColor('fg-black, bg-green', 'ok' . PHP_EOL);
238 2
        }
239 3
    }
240
241
    /**
242
     * Crypt start event.
243
     *
244
     * @param \phpbu\App\Event\Crypt\Start $event
245
     */
246 1
    public function onCryptStart(Event\Crypt\Start $event)
247
    {
248 1
        $crypt = $event->getConfiguration();
249 1
        $this->numCrypts++;
250 1
        if ($this->debug) {
251
            $this->writeWithAsterisk('crypt: [' . $crypt->type . '] ');
252 1
        }
253 1
    }
254 1
255
    /**
256
     * Crypt skipped event.
257
     *
258
     * @param \phpbu\App\Event\Crypt\Skipped $event
259
     */
260
    public function onCryptSkipped(Event\Crypt\Skipped $event)
261 2
    {
262
        if ($this->debug) {
263 2
            $this->writeWithColor('fg-black, bg-yellow', 'skipped' . PHP_EOL);
264 1
        }
265 1
    }
266 2
267
    /**
268
     * Crypt failed event.
269
     *
270
     * @param \phpbu\App\Event\Crypt\Failed $event
271
     */
272
    public function onCryptFailed(Event\Crypt\Failed $event)
273 4
    {
274
        if ($this->debug) {
275 4
            $this->writeWithColor('fg-white, bg-red, bold', 'failed' . PHP_EOL);
276 4
        }
277 4
    }
278 3
279 3
    /**
280 4
     * Crypt end event.
281
     *
282
     * @param \phpbu\App\Event\Crypt\End $event
283
     */
284
    public function onCryptEnd(Event\Crypt\End $event)
285
    {
286
        if ($this->debug) {
287 1
            $this->writeWithColor('fg-black, bg-green', 'ok' . PHP_EOL);
288
        }
289 1
    }
290 1
291 1
    /**
292
     * Sync start event.
293 1
     *
294 1
     * @param \phpbu\App\Event\Sync\Start $event
295 1
     */
296
    public function onSyncStart(Event\Sync\Start $event)
297
    {
298
        $sync = $event->getConfiguration();
299
        $this->numSyncs++;
300
        if ($this->debug) {
301
            $this->writeWithAsterisk('sync: [' . $sync->type . '] ');
302 1
        }
303
    }
304 1
305 1
    /**
306 1
     * Sync skipped event.
307
     *
308 1
     * @param \phpbu\App\Event\Sync\Skipped $event
309 1
     */
310 1
    public function onSyncSkipped(Event\Sync\Skipped $event)
311
    {
312
        if ($this->debug) {
313
            $this->writeWithColor('fg-black, bg-yellow', 'skipped' . PHP_EOL);
314
        }
315
    }
316
317 2
    /**
318
     * Sync failed event.
319 2
     *
320 1
     * @param \phpbu\App\Event\Sync\Failed $event
321 1
     */
322 2
    public function onSyncFailed(Event\Sync\Failed $event)
323
    {
324
        if ($this->debug) {
325
            $this->writeWithColor('fg-white, bg-red, bold', 'failed' . PHP_EOL);
326
        }
327
    }
328
329 4
    /**
330
     * Sync end event.
331 4
     *
332 4
     * @param \phpbu\App\Event\Sync\End $event
333 4
     */
334 3
    public function onSyncEnd(Event\Sync\End $event)
335 3
    {
336 4
        if ($this->debug) {
337
            $this->writeWithColor('fg-black, bg-green', 'ok' . PHP_EOL);
338
        }
339
    }
340
341
    /**
342
     * Cleanup start event.
343 1
     *
344
     * @param \phpbu\App\Event\Cleanup\Start $event
345 1
     */
346 1
    public function onCleanupStart(Event\Cleanup\Start $event)
347 1
    {
348
        $cleanup = $event->getConfiguration();
349 1
        $this->numCleanups++;
350 1
        if ($this->debug) {
351 1
            $this->writeWithAsterisk('cleanup: [' . $cleanup->type . '] ');
352
        }
353
    }
354
355
    /**
356
     * Cleanup skipped event.
357
     *
358 1
     * @param \phpbu\App\Event\Cleanup\Skipped $event
359
     */
360 1
    public function onCleanupSkipped(Event\Cleanup\Skipped $event)
361 1
    {
362 1
        if ($this->debug) {
363
            $this->writeWithColor('fg-black, bg-yellow', 'skipped' . PHP_EOL);
364 1
        }
365 1
    }
366 1
367
    /**
368
     * Cleanup failed event.
369
     *
370
     * @param \phpbu\App\Event\Cleanup\Failed $event
371
     */
372
    public function onCleanupFailed(Event\Cleanup\Failed $event)
373 2
    {
374
        if ($this->debug) {
375 2
            $this->writeWithColor('fg-white, bg-red, bold', 'failed' . PHP_EOL);
376 1
        }
377 1
    }
378 2
379
    /**
380
     * Cleanup end event.
381
     *
382
     * @param \phpbu\App\Event\Cleanup\End $event
383
     */
384
    public function onCleanupEnd(Event\Cleanup\End $event)
385 4
    {
386
        if ($this->debug) {
387 4
            $this->writeWithColor('fg-black, bg-green', 'ok' . PHP_EOL);
388 4
        }
389 4
    }
390 3
391 3
    /**
392 4
     * Debugging.
393
     *
394
     * @param \phpbu\App\Event\Debug $event
395
     */
396
    public function onDebug(Event\Debug $event)
397
    {
398
        if ($this->debug) {
399 1
            $this->write(wordwrap($event->getMessage(), 70, PHP_EOL, true) . PHP_EOL);
400
        }
401 1
    }
402 1
403 1
    /**
404
     * phpbu end event.
405 1
     *
406 1
     * @param \phpbu\App\Event\App\End $event
407 1
     */
408
    public function onPhpbuEnd(Event\App\End $event)
409
    {
410
        $result = $event->getResult();
411
        $this->printResult($result);
412
    }
413
414 1
    /**
415
     * Prints a result summary.
416 1
     *
417 1
     * @param \phpbu\App\Result $result
418 1
     */
419
    public function printResult(Result $result)
420 1
    {
421 1
        $this->printHeader();
422 1
        $this->printErrors($result);
423
424
        if ($this->verbose) {
425
            foreach ($result->getBackups() as $backup) {
426
                $this->printBackupVerbose($backup);
427
            }
428
        }
429 2
        $this->printFooter($result);
430
    }
431 2
432 1
    /**
433 1
     * Prints the result header with memory usage info.
434 2
     */
435
    protected function printHeader()
436
    {
437
        $this->write(PHP_Timer::resourceUsage() . PHP_EOL . PHP_EOL);
438
    }
439
440
    /**
441 1
     * Print error information.
442
     *
443 1
     * @param \phpbu\App\Result $result
444 1
     */
445 1
    protected function printErrors(Result $result)
446 1
    {
447
        /* @var $e \Exception */
448
        foreach ($result->getErrors() as $e) {
449
            $this->write(
450
                sprintf(
451
                    "Exception '%s' with message '%s'\nin %s:%d\n\n",
452
                    get_class($e),
453 1
                    $e->getMessage(),
454
                    $e->getFile(),
455 1
                    $e->getLine()
456 1
                )
457 1
            );
458
        }
459
    }
460
461
    /**
462
     * Prints verbose backup information.
463
     *
464 5
     * @param \phpbu\App\Result\Backup $backup
465
     */
466 5
    protected function printBackupVerbose(Result\Backup $backup)
467 5
    {
468
        $this->write(sprintf('backup %s: ', $backup->getName()));
469 5
        if ($backup->allOk()) {
470 3
            $this->writeWithColor(
471 3
                'fg-black, bg-green',
472 3
                'OK'
473 3
            );
474 5
        } elseif ($backup->okButSkipsOrFails()) {
475 5
                $this->writeWithColor(
476
                    'fg-black, bg-yellow',
477
                    'OK, but skipped or failed Crypts, Syncs or Cleanups!'
478
                );
479
        } else {
480 5
            $this->writeWithColor(
481
                'fg-white, bg-red, bold',
482 5
                'FAILED'
483 5
            );
484
        }
485
        $chExecuted = str_pad($backup->checkCount(), 8, ' ', STR_PAD_LEFT);
486
        $chFailed   = str_pad($backup->checkCountFailed(), 6, ' ', STR_PAD_LEFT);
487
        $crExecuted = str_pad($backup->cryptCount(), 8, ' ', STR_PAD_LEFT);
488
        $crSkipped  = str_pad($backup->cryptCountSkipped(), 7, ' ', STR_PAD_LEFT);
489
        $crFailed   = str_pad($backup->cryptCountFailed(), 6, ' ', STR_PAD_LEFT);
490 5
        $syExecuted = str_pad($backup->syncCount(), 8, ' ', STR_PAD_LEFT);
491
        $sySkipped  = str_pad($backup->syncCountSkipped(), 7, ' ', STR_PAD_LEFT);
492
        $syFailed   = str_pad($backup->syncCountFailed(), 6, ' ', STR_PAD_LEFT);
493 5
        $clExecuted = str_pad($backup->cleanupCount(), 8, ' ', STR_PAD_LEFT);
494 1
        $clSkipped  = str_pad($backup->cleanupCountSkipped(), 7, ' ', STR_PAD_LEFT);
495 1
        $clFailed   = str_pad($backup->cleanupCountFailed(), 6, ' ', STR_PAD_LEFT);
496 1
497 1
        $out = PHP_EOL . '          | executed | skipped | failed |' . PHP_EOL
498 1
            . '----------+----------+---------+--------+' . PHP_EOL
499 1
            . ' checks   | ' . $chExecuted . ' |         | ' . $chFailed . ' |' . PHP_EOL
500 1
            . ' crypts   | ' . $crExecuted . ' | ' . $crSkipped . ' | ' . $crFailed . ' |' . PHP_EOL
501 1
            . ' syncs    | ' . $syExecuted . ' | ' . $sySkipped . ' | ' . $syFailed . ' |' . PHP_EOL
502 1
            . ' cleanups | ' . $clExecuted . ' | ' . $clSkipped . ' | ' . $clFailed . ' |' . PHP_EOL
503 5
            . '----------+----------+---------+--------+' . PHP_EOL . PHP_EOL;
504 5
505
        $this->write($out);
506
    }
507
508
    /**
509
     * Prints 'OK' or 'FAILURE' footer.
510
     *
511 3
     * @param Result $result
512
     */
513 3
    protected function printFooter(Result $result)
514 3
    {
515 1
        if (count($result->getBackups()) === 0) {
516 1
            $this->writeWithColor(
517
                'fg-black, bg-yellow',
518 1
                'No backups executed!'
519 3
            );
520 1
        } elseif ($result->allOk()) {
521 1
            $this->writeWithColor(
522
                'fg-black, bg-green',
523 1
                sprintf(
524 1
                    'OK (%d %s, %d %s, %d %s, %d %s, %d %s)' . PHP_EOL,
525 1
                    count($result->getBackups()),
526 1
                    Util\Str::appendPluralS('backup', count($result->getBackups())),
527
                    $this->numChecks,
528 1
                    Util\Str::appendPluralS('check', $this->numChecks),
529
                    $this->numCrypts,
530 3
                    Util\Str::appendPluralS('crypt', $this->numCrypts),
531 3
                    $this->numSyncs,
532 3
                    Util\Str::appendPluralS('sync', $this->numSyncs),
533 3
                    $this->numCleanups,
534 3
                    Util\Str::appendPluralS('cleanup', $this->numCleanups)
535 3
                )
536 3
            );
537 3
        } elseif ($result->backupOkButSkipsOrFails()) {
538 3
            $this->writeWithColor(
539 3
                'fg-black, bg-yellow',
540 3
                sprintf(
541
                    "OK, but skipped|failed Crypts, Syncs or Cleanups!\n" .
542 3
                    'Backups: %d, Crypts: %d|%d, Syncs: %d|%d, Cleanups: %d|%d.' . PHP_EOL,
543 3
                    count($result->getBackups()),
544 3
                    $result->cryptsSkippedCount(),
545 3
                    $result->cryptsFailedCount(),
546 3
                    $result->syncsSkippedCount(),
547 3
                    $result->syncsFailedCount(),
548 3
                    $result->cleanupsSkippedCount(),
549
                    $result->cleanupsFailedCount()
550 3
                )
551 3
            );
552
        } else {
553
            $this->writeWithColor(
554
                'fg-white, bg-red',
555
                sprintf(
556
                    "FAILURE!\n" .
557
                    'Backups: %d, failed Checks: %d, failed Crypts: %d, failed Syncs: %d, failed Cleanups: %d.' . PHP_EOL,
558 5
                    count($result->getBackups()),
559
                    $result->checksFailedCount(),
560 5
                    $result->cryptsFailedCount(),
561 2
                    $result->syncsFailedCount(),
562 2
                    $result->cleanupsFailedCount()
563
                )
564 2
            );
565 5
        }
566 1
    }
567 1
568 1
    /**
569 1
     * Writes a buffer out with a color sequence if colors are enabled.
570 1
     *
571 1
     * @author Sebastian Bergmann <[email protected]>
572 1
     * @param  string $color
573 1
     * @param  string $buffer
574 1
     */
575 1
    protected function writeWithColor($color, $buffer)
576 1
    {
577 1
        if ($this->colors) {
578 1
            $buffer = Util\Cli::formatWithColor($color, $buffer);
579 1
        }
580 1
        $this->write($buffer . PHP_EOL);
581 1
    }
582 3
583 1
    /**
584 1
     * Writes a buffer with Ansible like asterisk decoration.
585 1
     *
586
     * @param string $buffer
587 1
     */
588 1
    protected function writeWithAsterisk($buffer)
589 1
    {
590 1
        $this->write(Util\Cli::formatWithAsterisk($buffer));
591 1
    }
592 1
593 1
    /**
594 1
     * Writes a buffer.
595 1
     *
596 1
     * @param string $buffer
597 1
     */
598 1
    public function write($buffer)
599 1
    {
600 1
        if (PHP_SAPI != 'cli') {
601
            $buffer = htmlspecialchars($buffer);
602 1
        }
603 1
        echo $buffer;
604 1
    }
605
}
606