ComposerAction::run()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 52
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 35
c 3
b 0
f 0
dl 0
loc 52
ccs 0
cts 19
cp 0
rs 9.36
cc 3
nc 3
nop 2
crap 12

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Action;
4
5
use App\Action\AbstractAction;
6
use App\Action\ActionInterface;
7
use App\Facades\Log;
8
use App\Facades\Settings;
9
use App\Model\Deployment;
10
use Ronanchilvers\Foundation\Config;
11
use Ronanchilvers\Utility\File;
12
use Symfony\Component\Process\Exception\ProcessFailedException;
13
use Symfony\Component\Process\Process;
14
use RuntimeException;
15
16
/**
17
 * Action to run composer on the project if a composer.json file is found
18
 *
19
 * @author Ronan Chilvers <[email protected]>
20
 */
21
class ComposerAction extends AbstractAction
22
{
23
    /**
24
     * @see \App\Action\ActionInterface::run()
25
     */
26
    public function run(Config $configuration, Context $context)
27
    {
28
        $deployment    = $context->getOrThrow('deployment', 'Invalid or missing deployment');
29
        $deploymentDir = $context->getOrThrow('deployment_dir', 'Invalid or missing deployment directory');
30
        $composerJson  = File::join($deploymentDir, 'composer.json');
31
        if (!is_readable($composerJson)) {
32
            $this->info(
33
                $deployment,
34
                'No composer.json file found - skipping composer installation'
35
            );
36
            return;
37
        }
38
        $composerPath = $this->getComposerPath($deployment);
39
        $composerArgs = $configuration->get(
40
            'composer.command',
41
            'install --no-dev --optimize-autoloader'
42
        );
43
        $phpPath      = Settings::get('binary.php');
44
        $command      = "{$phpPath} {$composerPath} {$composerArgs}";
45
        Log::debug('Executing composer', [
46
            'command' => $command,
47
        ]);
48
        $this->info(
49
            $deployment,
50
            [
51
                "Directory: {$deploymentDir}",
52
                "Command: {$command}",
53
            ]
54
        );
55
        $process = new Process(
56
            explode(' ', $command),
57
            $deploymentDir,
58
            [
59
                'COMPOSER_HOME' => dirname($composerPath),
60
            ]
61
        );
62
        $process->run();
63
        if (!$process->isSuccessful()) {
64
            $this->error(
65
                $deployment,
66
                [
67
                    'Composer run failed',
68
                    $process->getErrorOutput()
69
                ]
70
            );
71
            throw new ProcessFailedException($process);
72
        }
73
        $this->info(
74
            $deployment,
75
            [
76
                $process->getOutput(),
77
                $process->getErrorOutput(),
78
            ]
79
        );
80
    }
81
82
    /**
83
     * Get the path to the installed composer phar file
84
     *
85
     * This method returns the path to a composer phar file, downloading it
86
     * if required.
87
     *
88
     * @return string
89
     * @throws RuntimeException If composer cannot be found
90
     * @author Ronan Chilvers <[email protected]>
91
     */
92
    protected function getComposerPath(Deployment $deployment)
93
    {
94
        $baseDir  = Settings::get('build.base_dir');
95
        $filename = File::join($baseDir, 'composer.phar');
96
        if (!is_readable($filename)) {
97
            $this->info(
98
                $deployment,
99
                'Downloading composer.phar'
100
            );
101
            $installer = File::join($baseDir, 'composer-setup.php');
102
            if (!copy('https://getcomposer.org/installer', $installer)) {
103
                throw new RuntimeException('Unable to download composer installer');
104
            }
105
            $expected = file_get_contents('https://composer.github.io/installer.sig');
106
            $actual = hash_file('sha384', $installer);
107
            if (!$expected == $actual) {
108
                throw new RuntimeException('Signature mismatch for composer installer');
109
            }
110
            $phpPath = Settings::get('binary.php');
111
            $process = new Process(
112
                [$phpPath, $installer],
113
                $baseDir,
114
                [
115
                    'COMPOSER_HOME' => $baseDir,
116
                ]
117
            );
118
            $process->run();
119
            if (!$process->isSuccessful()) {
120
                $this->error(
121
                    $deployment,
122
                    [
123
                        'Failed downloading composer.phar',
124
                        $process->getOutput(),
125
                        $process->getErrorOutput()
126
                    ]
127
                );
128
                throw new RuntimeException('Failed to run composer installer');
129
            }
130
            if (!unlink($installer)) {
131
                $this->error(
132
                    $deployment,
133
                    'Unable to remove the composer installer file ' . $installer
134
                );
135
                throw new RuntimeException('Unable to remove the composer installer file');
136
            }
137
        }
138
139
        return $filename;
140
    }
141
}
142