Completed
Push — master ( ca4c8c...687844 )
by Sebastian
03:10
created

Hook::doConditionsApply()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
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\Runner;
11
12
use CaptainHook\App\Config;
13
use CaptainHook\App\Config\Options;
14
use CaptainHook\App\Console\IO;
15
use CaptainHook\App\Console\IOUtil;
16
use SebastianFeldmann\Git\Repository;
17
use RuntimeException;
18
19
/**
20
 * Hook
21
 *
22
 * @package CaptainHook
23
 * @author  Sebastian Feldmann <[email protected]>
24
 * @link    https://github.com/captainhookphp/captainhook
25
 * @since   Class available since Release 0.9.0
26
 */
27
abstract class Hook extends RepositoryAware
28
{
29
    /**
30
     * Hook that should be handled.
31
     *
32
     * @var string
33
     */
34
    protected $hook;
35
36
    /**
37
     * List of original hook arguments
38
     *
39
     * @var \CaptainHook\App\Config\Options
40
     */
41
    protected $arguments;
42
43
    /**
44
     * HookHandler constructor.
45
     *
46
     * @param \CaptainHook\App\Console\IO       $io
47
     * @param \CaptainHook\App\Config           $config
48
     * @param \SebastianFeldmann\Git\Repository $repository
49
     * @param \CaptainHook\App\Config\Options   $arguments
50
     */
51 25
    public function __construct(IO $io, Config $config, Repository $repository, Options $arguments)
52
    {
53 25
        parent::__construct($io, $config, $repository);
54 25
        $this->arguments = $arguments;
55 25
    }
56
57
    /**
58
     * Execute stuff before executing any actions
59
     *
60
     * @return void
61
     */
62 9
    public function beforeHook() : void
63
    {
64
        // empty template method
65 9
    }
66
67
    /**
68
     * Execute stuff before every actions
69
     *
70
     * @return void
71
     */
72 1
    public function beforeAction() : void
73
    {
74
        // empty template method
75 1
    }
76
77
    /**
78
     * Execute stuff after every actions
79
     *
80
     * @return void
81
     */
82 1
    public function afterAction() : void
83
    {
84
        //empty template method
85 1
    }
86
87
    /**
88
     * Execute stuff after all actions
89
     *
90
     * @return void
91
     */
92 9
    public function afterHook() : void
93
    {
94
        // empty template method
95 9
    }
96
97
    /**
98
     * Execute the hook and all its actions
99
     *
100
     * @return void
101
     * @throws \Exception
102
     */
103 25
    public function run() : void
104
    {
105
        /** @var \CaptainHook\App\Config\Hook $hookConfig */
106 25
        $hookConfig = $this->config->getHookConfig($this->hook);
107 25
        $actions    = $hookConfig->getActions();
108
109
        // if hook is not enabled in captainhook configuration skip the execution
110 25
        if (!$hookConfig->isEnabled()) {
111 10
            $this->io->write($this->formatHookHeadline('Skip'));
112 10
            return;
113
        }
114
        // if no actions are configured do nothing
115 15
        if (count($actions) === 0) {
116 4
            $this->io->write(['', '<info>No actions to execute</info>']);
117 4
            return;
118
        }
119
120 11
        $this->io->write($this->formatHookHeadline('Execute'));
121 11
        $this->beforeHook();
122 9
        foreach ($actions as $action) {
123 9
            $this->handleAction($action);
124
        }
125 9
        $this->afterHook();
126 9
    }
127
128
    /**
129
     * Executes a configured hook action
130
     *
131
     * @param  \CaptainHook\App\Config\Action $action
132
     * @return void
133
     * @throws \Exception
134
     */
135 9
    protected function handleAction(Config\Action $action) : void
136
    {
137 9
        $this->io->write(['', 'Action: <comment>' . $action->getAction() . '</comment>']);
138
139 9
        if (!$this->doConditionsApply($action->getConditions())) {
140 1
            $this->io->write(
141 1
                ['', 'Action: <comment>' . $action->getAction() . '</comment> skipped due to failing conditions']
142
            );
143 1
            return;
144
        }
145
146 8
        $execMethod = self::getExecMethod(Util::getExecType($action->getAction()));
147 8
        $this->{$execMethod}($action);
148 8
    }
149
150
    /**
151
     * Execute a php hook action
152
     *
153
     * @param  \CaptainHook\App\Config\Action $action
154
     * @return void
155
     * @throws \CaptainHook\App\Exception\ActionFailed
156
     */
157 1
    protected function executePhpAction(Config\Action $action) : void
158
    {
159 1
        $this->beforeAction();
160 1
        $runner = new Action\PHP();
161 1
        $runner->execute($this->config, $this->io, $this->repository, $action);
162 1
        $this->afterAction();
163 1
    }
164
165
    /**
166
     * Execute a cli hook action
167
     *
168
     * @param  \CaptainHook\App\Config\Action $action
169
     * @return void
170
     * @throws \CaptainHook\App\Exception\ActionFailed
171
     */
172 7
    protected function executeCliAction(Config\Action $action) : void
173
    {
174
        // since the cli has no straight way to communicate back to php
175
        // cli hooks have to handle sync stuff by them self
176
        // so no 'beforeAction' or 'afterAction' is called here
177 7
        $runner = new Action\Cli();
178 7
        $runner->execute($this->io, $action, $this->arguments);
179 7
    }
180
181
    /**
182
     * Return the right method name to execute an action
183
     *
184
     * @param  string $type
185
     * @return string
186
     */
187 10
    public static function getExecMethod(string $type) : string
188
    {
189 10
        $valid = ['php' => 'executePhpAction', 'cli' => 'executeCliAction'];
190
191 10
        if (!isset($valid[$type])) {
192 1
            throw new RuntimeException('invalid action type: ' . $type);
193
        }
194 9
        return $valid[$type];
195
    }
196
197
    /**
198
     * Check if conditions apply
199
     *
200
     * @param  \CaptainHook\App\Config\Condition[] $conditions
201
     * @return bool
202
     */
203 9
    private function doConditionsApply(array $conditions) : bool
204
    {
205 9
        $conditionRunner = new Condition($this->io, $this->repository);
206 9
        foreach ($conditions as $config) {
207 2
            if (!$conditionRunner->doesConditionApply($config)) {
208 2
                return false;
209
            }
210
        }
211 8
        return true;
212
    }
213
214
    /**
215
     * Some fancy output formatting
216
     *
217
     * @param  string $mode
218
     * @return array
219
     */
220 21
    private function formatHookHeadline(string $mode) : array
221
    {
222 21
        $headline = ' ' . $mode . ' hook: <comment>' . $this->hook . '</comment> ';
223
        return [
224 21
            '',
225 21
            IOUtil::getLineSeparator(8) .
226 21
            $headline .
227 21
            IOUtil::getLineSeparator(80 - 8 - strlen(strip_tags($headline)))
228
        ];
229
    }
230
}
231