Completed
Pull Request — master (#9)
by
unknown
12:13
created

ScriptHandler::hasDirectory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 0
cts 10
cp 0
rs 9.7333
c 0
b 0
f 0
cc 2
nc 2
nop 4
crap 6
1
<?php
2
/**
3
 * GpsLab component.
4
 *
5
 * @author    Peter Gribanov <[email protected]>
6
 * @copyright Copyright (c) 2017, Peter Gribanov
7
 * @license   http://opensource.org/licenses/MIT
8
 */
9
10
namespace GpsLab\Bundle\GeoIP2Bundle\Composer;
11
12
use Composer\Script\Event;
13
use Symfony\Component\Process\PhpExecutableFinder;
14
use Symfony\Component\Process\Process;
15
16
class ScriptHandler
17
{
18
    /**
19
     * Composer variables are declared static so that an event could update
20
     * a composer.json and set new options, making them immediately available
21
     * to forthcoming listeners.
22
     */
23
    private static $options = [
24
        'symfony-app-dir' => 'app',
25
        'symfony-bin-dir' => 'bin
26
    ];
27
28
    /**
29
     * @param Event $event
30
     */
31
    public static function updateDatabase(Event $event)
32
    {
33
        $options = static::getOptions($event);
34
        $console_dir = static::getConsoleDir($event, 'clear the cache');
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting ']'
Loading history...
35
36
        if (null === $console_dir) {
37
            return;
38
        }
39
40
        static::executeCommand($event, $console_dir, 'geoip2:update --no-debug', $options['process-timeout']);
41
    }
42
43
    /**
44
     * @param Event $event
45
     * @param string $console_dir
46
     * @param string $cmd
47
     * @param int $timeout
48
     */
49
    protected static function executeCommand(Event $event, $console_dir, $cmd, $timeout = 300)
50
    {
51
        $php = escapeshellarg(self::getPhp(false));
52
        $php_args = implode(' ', array_map('escapeshellarg', self::getPhpArguments()));
53
        $console = escapeshellarg($console_dir.'/console');
54
        if ($event->getIO()->isDecorated()) {
55
            $console .= ' --ansi';
56
        }
57
58
        $command = $php.($php_args ? ' '.$php_args : '').' '.$console.' '.$cmd;
59
        if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
60
            // Symfony 4.2 +
61
            $process = Process::fromShellCommandline($command, null, null, null, $timeout);
62
        } else {
63
            // Symfony 4.1 and below
64
            $process = new Process($command, null, null, null, $timeout);
65
        }
66
        $process->run(function ($type, $buffer) use ($event) {
67
            $event->getIO()->write($buffer, false);
68
        });
69
70
        if (!$process->isSuccessful()) {
71
            throw new \RuntimeException(sprintf(
72
                "An error occurred when executing the \"%s\" command:\n\n%s\n\n%s.",
73
                escapeshellarg($cmd),
74
                $process->getOutput(),
75
                $process->getErrorOutput()
76
            ));
77
        }
78
    }
79
80
    /**
81
     * @param Event $event
82
     *
83
     * @return array
84
     */
85
    protected static function getOptions(Event $event)
86
    {
87
        $options = array_merge(self::$options, $event->getComposer()->getPackage()->getExtra());
88
89
        $options['process-timeout'] = $event->getComposer()->getConfig()->get('process-timeout');
90
91
        return $options;
92
    }
93
94
    /**
95
     * Returns a relative path to the directory that contains the `console` command or null if not found.
96
     *
97
     * @param Event  $event       The command event
98
     * @param string $action_name The name of the action
99
     *
100
     * @return string|null
101
     */
102
    protected static function getConsoleDir(Event $event, $action_name)
103
    {
104
        $options = static::getOptions($event);
105
106
        if (self::useNewDirectoryStructure($options)) {
107
            if (!self::hasDirectory($event, 'symfony-bin-dir', $options['symfony-bin-dir'], $action_name)) {
108
                return;
109
            }
110
111
            return $options['symfony-bin-dir'];
112
        }
113
114
        if (!self::hasDirectory($event, 'symfony-app-dir', $options['symfony-app-dir'], 'execute command')) {
115
            return;
116
        }
117
118
        return $options['symfony-app-dir'];
119
    }
120
121
    /**
122
     * @param Event  $event
123
     * @param string $config_name
124
     * @param string $path
125
     * @param string $action_name
126
     *
127
     * @return bool
128
     */
129
    private static function hasDirectory(Event $event, $config_name, $path, $action_name)
130
    {
131
        if (!is_dir($path)) {
132
            $event->getIO()->write(sprintf(
133
                'The %s (%s) specified in composer.json was not found in %s, can not %s.',
134
                $config_name,
135
                $path,
136
                getcwd(),
137
                $action_name
138
            ));
139
140
            return false;
141
        }
142
143
        return true;
144
    }
145
146
    /**
147
     * Returns true if the new directory structure is used.
148
     *
149
     * @param array $options Composer options
150
     *
151
     * @return bool
152
     */
153
    private static function useNewDirectoryStructure(array $options)
154
    {
155
        return isset($options['symfony-bin-dir']) && is_dir($options['symfony-bin-dir']);
156
    }
157
158
    /**
159
     * Get path to php executable.
160
     *
161
     * @param bool $include_args
162
     *
163
     * @throws \RuntimeException
164
     *
165
     * @return string
166
     */
167
    private static function getPhp($include_args = true)
168
    {
169
        $phpFinder = new PhpExecutableFinder();
170
        if (!$phpPath = $phpFinder->find($include_args)) {
171
            throw new \RuntimeException('The php executable could not be found, add it to your PATH environment variable and try again');
172
        }
173
174
        return $phpPath;
175
    }
176
177
    /**
178
     * @return array
179
     */
180
    private static function getPhpArguments()
181
    {
182
        $arguments = [];
183
        $php_finder = new PhpExecutableFinder();
184
        if (method_exists($php_finder, 'findArguments')) {
185
            $arguments = $php_finder->findArguments();
186
        }
187
188
        if ($env = strval(getenv('COMPOSER_ORIGINAL_INIS'))) {
189
            $paths = explode(PATH_SEPARATOR, $env);
190
            $ini = array_shift($paths);
191
        } else {
192
            $ini = php_ini_loaded_file();
193
        }
194
195
        if ($ini) {
196
            $arguments[] = '--php-ini='.$ini;
197
        }
198
199
        return $arguments;
200
    }
201
}
202