Completed
Push — master ( dde524...92e3a2 )
by Sebastian
06:05
created

Installer::setHook()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 2
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\Console\IOUtil;
13
use CaptainHook\App\Exception;
14
use CaptainHook\App\Hook\Template;
15
use CaptainHook\App\Hook\Util;
16
use CaptainHook\App\Storage\File;
17
18
/**
19
 * Class Installer
20
 *
21
 * @package CaptainHook
22
 * @author  Sebastian Feldmann <[email protected]>
23
 * @link    https://github.com/sebastianfeldmann/captainhook
24
 * @since   Class available since Release 0.9.0
25
 */
26
class Installer extends RepositoryAware
27
{
28
    /**
29
     * Overwrite hook
30
     *
31
     * @var bool
32
     */
33
    private $force;
34
35
    /**
36
     * Hook that should be handled.
37
     *
38
     * @var string
39 2
     */
40
    protected $hookToHandle;
41 2
42 2
    /**
43
     * @param  bool $force
44
     * @return \CaptainHook\App\Runner\Installer
45
     */
46
    public function setForce(bool $force)
47
    {
48 2
        $this->force = $force;
49
        return $this;
50 2
    }
51
52 2
    /**
53 2
     * Hook setter.
54
     *
55 2
     * @param  string $hook
56
     * @return \CaptainHook\App\Runner\RepositoryAware
57
     * @throws \CaptainHook\App\Exception\InvalidHookName
58
     */
59
    public function setHook(string $hook) : RepositoryAware
60
    {
61
        if (!empty($hook) && !Util::isValid($hook)) {
62 2
            throw new Exception\InvalidHookName('Invalid hook name \'' . $hook . '\'');
63
        }
64 2
        $this->hookToHandle = $hook;
65
        return $this;
66
    }
67
68
    /**
69
     * Execute installation.
70
     */
71
    public function run()
72
    {
73 3
        $hooks = $this->getHooksToInstall();
74
75 3
        foreach ($hooks as $hook => $ask) {
76 3
            $this->installHook($hook, ($ask && !$this->force));
77 1
        }
78 1
    }
79
80
    /**
81 3
     * Return list of hooks to install.
82 2
     *
83
     * @return array
84 3
     */
85
    public function getHooksToInstall() : array
86
    {
87
        return empty($this->hookToHandle) ? Util::getValidHooks() : [$this->hookToHandle => false];
88
    }
89
90
    /**
91 3
     * Install given hook.
92
     *
93 3
     * @param string $hook
94 3
     * @param bool   $ask
95 3
     */
96
    public function installHook(string $hook, bool $ask)
97
    {
98
        $doIt = true;
99 3
        if ($ask) {
100 1
            $answer = $this->io->ask('  <info>Install \'' . $hook . '\' hook?</info> <comment>[y,n]</comment> ', 'y');
101 1
            $doIt   = IOUtil::answerToBool($answer);
102
        }
103
104 3
        if ($doIt) {
105 2
            $this->writeHookFile($hook);
106 2
        }
107 2
    }
108 2
109 2
    /**
110
     * Write given hook to .git/hooks directory
111 3
     *
112
     * @param string $hook
113
     */
114
    public function writeHookFile(string $hook)
115
    {
116
        $hooksDir = $this->repository->getHooksDir();
117
        $hookFile = $hooksDir . DIRECTORY_SEPARATOR . $hook;
118
        $doIt     = true;
119 2
120
        // if hook is configured and no force option is set
121 2
        // ask the user if overwriting the hook is ok
122 2
        if ($this->needInstallConfirmation($hook)) {
123 2
            $ans  = $this->io->ask('  <comment>The \'' . $hook . '\' hook exists! Overwrite? [y,n]</comment> ', 'n');
124 2
            $doIt = IOUtil::answerToBool($ans);
125
        }
126
127
        if ($doIt) {
128
            $code = $this->getHookSourceCode($hook);
129
            $file = new File($hookFile);
130
            $file->write($code);
131
            chmod($hookFile, 0755);
132
            $this->io->write('  <info>\'' . $hook . '\' hook installed successfully</info>');
133 3
        }
134
    }
135 3
136
    /**
137
     * Return the source code for a given hook script.
138
     *
139
     * @param  string $hook
140
     * @return string
141
     */
142
    protected function getHookSourceCode(string $hook) : string
143
    {
144
        $absRepoPath = realpath($this->repository->getRoot());
145
        $vendorPath  = getcwd() . '/vendor';
146
        $configPath  = realpath($this->config->getPath());
147
        return Template::getCode($hook, $absRepoPath, $vendorPath, $configPath);
148
    }
149
150
    /**
151
     * If the hook already exists the user has to confirm the installation.
152
     *
153
     * @param  string $hook The name of the hook to check
154
     * @return bool
155
     */
156
    protected function needInstallConfirmation(string $hook) : bool
157
    {
158
        return $this->repository->hookExists($hook) && !$this->force;
159
    }
160
}
161