Completed
Push — master ( 4405cb...f3f48a )
by Sebastian
02:04
created

Book::getErrorOutput()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 9.6333
c 0
b 0
f 0
cc 3
nc 4
nop 2
crap 3
1
<?php
2
/**
3
 * This file is part of CaptainHook.
4
 *
5
 * (c) Sebastian Feldmann <[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
namespace CaptainHook\App\Hook\Message\Action;
11
12
use CaptainHook\App\Config;
13
use CaptainHook\App\Console\IO;
14
use CaptainHook\App\Console\IOUtil;
15
use CaptainHook\App\Exception\ActionFailed;
16
use CaptainHook\App\Hook\Action;
17
use CaptainHook\App\Hook\Message\RuleBook;
18
use SebastianFeldmann\Cli\Output\Util as OutputUtil;
19
use SebastianFeldmann\Git\Repository;
20
21
/**
22
 * Class Book
23
 *
24
 * @package CaptainHook
25
 * @author  Sebastian Feldmann <[email protected]>
26
 * @link    https://github.com/captainhookphp/captainhook
27
 * @since   Class available since Release 0.9.0
28
 */
29
abstract class Book implements Action
30
{
31
    /**
32
     * Execute the configured action
33
     *
34
     * @param  \CaptainHook\App\Config           $config
35
     * @param  \CaptainHook\App\Console\IO       $io
36
     * @param  \SebastianFeldmann\Git\Repository $repository
37
     * @param  \CaptainHook\App\Config\Action    $action
38
     * @return void
39
     * @throws \Exception
40
     */
41
    abstract public function execute(Config $config, IO $io, Repository $repository, Config\Action $action) : void;
42
43
    /**
44
     * Validate the message
45
     *
46
     * @param  \CaptainHook\App\Hook\Message\RuleBook $ruleBook
47
     * @param  \SebastianFeldmann\Git\Repository      $repository
48
     * @param  \CaptainHook\App\Console\IO            $io
49
     * @return void
50
     * @throws \CaptainHook\App\Exception\ActionFailed
51
     */
52 5
    protected function validate(RuleBook $ruleBook, Repository $repository, IO $io) : void
53
    {
54
        // if this is a merge commit skip enforcing message rules
55 5
        if ($repository->isMerging()) {
56 1
            return;
57
        }
58
59 4
        $problems = $ruleBook->validate($repository->getCommitMsg());
60
61 4
        if (count($problems)) {
62 1
            $io->writeError($this->getErrorOutput($problems, $repository));
63 1
            throw new ActionFailed('Commit message validation failed');
64
        }
65 3
        $io->write('<info>All rules passed</info>');
66 3
    }
67
68
    /**
69
     * Format the error output
70
     *
71
     * @param  array                             $problems
72
     * @param  \SebastianFeldmann\Git\Repository $repository
73
     * @return string
74
     */
75 1
    private function getErrorOutput(array $problems, Repository $repository) : string
76
    {
77 1
        $err  = count($problems);
78
        $head = [
79 1
            IOUtil::getLineSeparator(80, '-'),
80 1
            'CAPTAINHOOK FOUND ' . $err . ' PROBLEM' . ($err === 1 ? '' : 'S') . ' IN YOUR COMMIT MESSAGE',
81 1
            IOUtil::getLineSeparator(80, '-')
82
        ];
83 1
        $msg  = OutputUtil::trimEmptyLines($repository->getCommitMsg()->getLines());
84
85 1
        $lines = [IOUtil::getLineSeparator(80, '-')];
86 1
        foreach ($problems as $problem) {
87 1
            $lines[] = '  ' . $this->formatProblem($problem);
88
        }
89
90 1
        $lines[] = IOUtil::getLineSeparator(80, '-');
91
92 1
        return implode(PHP_EOL, array_merge($head, $msg, $lines));
93
    }
94
95
    /**
96
     * Indent multi line problems so the lines after the first one are indented for better readability
97
     *
98
     * @param  string $problem
99
     * @return string
100
     */
101 1
    private function formatProblem(string $problem) : string
102
    {
103 1
        $lines  = explode(PHP_EOL, $problem);
104 1
        $amount = count($lines);
105
106 1
        for ($i = 1; $i < $amount; $i++) {
107 1
            $lines[$i] = '    ' . $lines[$i];
108
        }
109
110 1
        return implode(PHP_EOL, $lines);
111
    }
112
}
113