Passed
Push — master ( a467a6...de53c5 )
by Sebastian
02:03
created

Installer::setTemplate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
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;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, CaptainHook\App\Runner\Util. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
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/captainhookphp/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
     */
40
    protected $hookToHandle;
41
42
    /**
43
     * Hook template
44
     *
45
     * @var Template
46
     */
47
    private $template;
48
49
    /**
50
     * @param  bool $force
51
     * @return \CaptainHook\App\Runner\Installer
52
     */
53 3
    public function setForce(bool $force) : Installer
54
    {
55 3
        $this->force = $force;
56 3
        return $this;
57
    }
58
59
    /**
60
     * Hook setter
61
     *
62
     * @param  string $hook
63
     * @return \CaptainHook\App\Runner\Installer
64
     * @throws \CaptainHook\App\Exception\InvalidHookName
65
     */
66 4
    public function setHook(string $hook) : Installer
67
    {
68 4
        if (!empty($hook) && !Util::isValid($hook)) {
69 1
            throw new Exception\InvalidHookName('Invalid hook name \'' . $hook . '\'');
70
        }
71 3
        $this->hookToHandle = $hook;
72 3
        return $this;
73
    }
74
75
    /**
76
     * Execute installation
77
     *
78
     * @return void
79
     */
80 3
    public function run() : void
81
    {
82 3
        $hooks = $this->getHooksToInstall();
83
84 3
        foreach ($hooks as $hook => $ask) {
85 3
            $this->installHook($hook, ($ask && !$this->force));
86
        }
87 3
    }
88
89
    /**
90
     * Return list of hooks to install
91
     *
92
     * @return array
93
     */
94 3
    public function getHooksToInstall() : array
95
    {
96 3
        return empty($this->hookToHandle) ? Util::getValidHooks() : [$this->hookToHandle => false];
97
    }
98
99
    /**
100
     * Install given hook
101
     *
102
     * @param string $hook
103
     * @param bool   $ask
104
     */
105 4
    public function installHook(string $hook, bool $ask): void
106
    {
107 4
        $doIt = true;
108 4
        if ($ask) {
109 1
            $answer = $this->io->ask('  <info>Install \'' . $hook . '\' hook?</info> <comment>[y,n]</comment> ', 'y');
110 1
            $doIt   = IOUtil::answerToBool($answer);
111
        }
112
113 4
        if ($doIt) {
114 3
            $this->writeHookFile($hook);
115
        }
116 4
    }
117
118
    /**
119
     * Write given hook to .git/hooks directory
120
     *
121
     * @param  string $hook
122
     * @return void
123
     */
124 5
    public function writeHookFile(string $hook) : void
125
    {
126 5
        $hooksDir = $this->repository->getHooksDir();
127 5
        $hookFile = $hooksDir . DIRECTORY_SEPARATOR . $hook;
128 5
        $doIt     = true;
129
130
        // if hook is configured and no force option is set
131
        // ask the user if overwriting the hook is ok
132 5
        if ($this->needInstallConfirmation($hook)) {
133 1
            $ans  = $this->io->ask('  <comment>The \'' . $hook . '\' hook exists! Overwrite? [y,n]</comment> ', 'n');
134 1
            $doIt = IOUtil::answerToBool($ans);
135
        }
136
137 5
        if ($doIt) {
138 4
            $code = $this->getHookSourceCode($hook);
139 4
            $file = new File($hookFile);
140 4
            $file->write($code);
141 4
            chmod($hookFile, 0755);
142 4
            $this->io->write('  <info>\'' . $hook . '\' hook installed successfully</info>');
143
        }
144 5
    }
145
146
    /**
147
     * Return the source code for a given hook script
148
     *
149
     * @param  string $hook
150
     * @return string
151
     */
152 4
    protected function getHookSourceCode(string $hook) : string
153
    {
154 4
        return $this->template->getCode($hook);
155
    }
156
157
    /**
158
     * If the hook already exists the user has to confirm the installation
159
     *
160
     * @param  string $hook The name of the hook to check
161
     * @return bool
162
     */
163 5
    protected function needInstallConfirmation(string $hook) : bool
164
    {
165 5
        return $this->repository->hookExists($hook) && !$this->force;
166
    }
167
168
    /**
169
     * Set used hook template
170
     *
171
     * @param Template $template
172
     *
173
     * @return Installer
174
     */
175 4
    public function setTemplate(Template $template) : Installer
176
    {
177 4
        $this->template = $template;
178 4
        return $this;
179
    }
180
}
181