Completed
Pull Request — master (#32)
by
unknown
08:40
created

Installer::installRunner()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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