Files   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 38
c 1
b 0
f 0
dl 0
loc 156
ccs 47
cts 47
cp 1
rs 10
wmc 15

8 Methods

Rating   Name   Duplication   Size   Complexity  
A shouldHookBeMoved() 0 3 1
A setMoveExistingTo() 0 4 1
A setHook() 0 11 1
A needConfirmation() 0 3 2
A backupHook() 0 21 3
A setForce() 0 4 1
A moveExistingHook() 0 13 4
A getHooksToHandle() 0 7 2
1
<?php
2
3
/**
4
 * This file is part of CaptainHook
5
 *
6
 * (c) Sebastian Feldmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace CaptainHook\App\Runner;
15
16
use CaptainHook\App\Exception;
17
use CaptainHook\App\Hook\Util as HookUtil;
18
use CaptainHook\App\Hooks;
19
use CaptainHook\App\Runner\Hook\Arg;
20
use RuntimeException;
21
use SebastianFeldmann\Camino\Check;
22
23
/**
24
 * Class HookMover
25
 *
26
 * @package CaptainHook
27
 * @author  Sebastian Feldmann <[email protected]>
28
 * @link    https://github.com/captainhook-git/captainhook
29
 * @since   Class available since Release 5.11.0
30
 */
31
abstract class Files extends RepositoryAware
32
{
33
    /**
34
     * Handle hooks brute force
35
     *
36
     * @var bool
37
     */
38
    protected bool $force = false;
39
40
    /**
41
     * Path where the existing hooks should be moved to
42
     *
43
     * @var string
44
     */
45
    protected string $moveExistingTo = '';
46
47
    /**
48
     * Hook(s) that should be handled.
49
     *
50
     * @var array<int, string>
51
     */
52
    protected array $hooksToHandle;
53
54
    /**
55
     * @param  bool $force
56
     * @return static
57
     */
58 12
    public function setForce(bool $force): self
59
    {
60 12
        $this->force = $force;
61 12
        return $this;
62
    }
63
64
    /**
65
     * Set the path where the current hooks should be moved to
66
     *
67
     * @param  string $backup
68
     * @return static
69
     */
70 18
    public function setMoveExistingTo(string $backup): static
71
    {
72 18
        $this->moveExistingTo = $backup;
73 18
        return $this;
74
    }
75
76
    /**
77
     * Limit uninstall to s specific hook
78
     *
79
     * @param  string $hook
80
     * @return static
81
     * @throws \CaptainHook\App\Exception\InvalidHookName
82
     */
83 28
    public function setHook(string $hook): self
84
    {
85 28
        $arg = new Arg(
86 28
            $hook,
87 28
            static function (string $hook): bool {
88 27
                return !HookUtil::isInstallable($hook);
89 28
            }
90 28
        );
91
92 23
        $this->hooksToHandle = $arg->hooks();
93 23
        return $this;
94
    }
95
96
    /**
97
     * Return list of hooks to handle
98
     *
99
     * [
100
     *   string    => bool
101
     *   HOOK_NAME => ASK_USER_TO_CONFIRM_INSTALL
102
     * ]
103
     *
104
     * @return array<string, bool>
105
     */
106 25
    protected function getHooksToHandle(): array
107
    {
108
        // if specific hooks are set, the user has actively chosen it, so don't ask for permission anymore
109
        // if all hooks get installed ask for permission
110 25
        return !empty($this->hooksToHandle)
111 16
            ? array_map(fn($hook) => false, array_flip($this->hooksToHandle))
112 25
            : array_map(fn($hook) => true, Hooks::nativeHooks());
113
    }
114
115
    /**
116
     * If a path to incorporate the existing hook is set we should incorporate existing hooks
117
     *
118
     * @return bool
119
     */
120 22
    protected function shouldHookBeMoved(): bool
121
    {
122 22
        return !empty($this->moveExistingTo);
123
    }
124
125
    /**
126
     * Move the existing hook to the configured location
127
     *
128
     * @param string $hook
129
     */
130 7
    protected function backupHook(string $hook): void
131
    {
132
        // no hook to move just exit
133 7
        if (!$this->repository->hookExists($hook)) {
134 1
            return;
135
        }
136
137 6
        $hookFileOrig   = $this->repository->getHooksDir() . DIRECTORY_SEPARATOR . $hook;
138 6
        $hookCmd        = rtrim($this->moveExistingTo, '/\\') . DIRECTORY_SEPARATOR . $hook;
139 6
        $hookCmdArgs    = $hookCmd . Hooks::getOriginalHookArguments($hook);
140 6
        $hookFileTarget = !Check::isAbsolutePath($this->moveExistingTo)
141 4
                        ? dirname($this->config->getPath()) . DIRECTORY_SEPARATOR . $hookCmd
142 2
                        : $hookCmd;
143
144 6
        $this->moveExistingHook($hookFileOrig, $hookFileTarget);
145
146 4
        $this->io->write(
147 4
            [
148 4
                '  Moved existing ' . $hook . ' hook to ' . $hookCmd,
149 4
                '  Add <comment>\'' . $hookCmdArgs . '\'</comment> to your '
150 4
                . $hook . ' configuration to execute it.'
151 4
            ]
152 4
        );
153
    }
154
155
    /**
156
     * If the hook exists the user has to confirm the action
157
     *
158
     * @param  string $hook The name of the hook to check
159
     * @return bool
160
     */
161 14
    protected function needConfirmation(string $hook): bool
162
    {
163 14
        return $this->repository->hookExists($hook) && !$this->force;
164
    }
165
166
    /**
167
     * Move the existing hook script to the new location
168
     *
169
     * @param  string $originalLocation
170
     * @param  string $newLocation
171
     * @return void
172
     * @throws \RuntimeException
173
     */
174 6
    protected function moveExistingHook(string $originalLocation, string $newLocation): void
175
    {
176 6
        $dir = dirname($newLocation);
177
        // make sure the target directory isn't a file
178 6
        if (file_exists($dir) && !is_dir($dir)) {
179 2
            throw new RuntimeException($dir . ' is not a directory');
180
        }
181
        // create the directory if it does not exist
182 4
        if (!is_dir($dir)) {
183 4
            mkdir($dir, 0755, true);
184
        }
185
        // move the hook into the target directory
186 4
        rename($originalLocation, $newLocation);
187
    }
188
}
189