Test Failed
Push — master ( e387ef...0464de )
by Lexey
03:14
created

Processor::showDifference()   C

Complexity

Conditions 8
Paths 11

Size

Total Lines 39
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 35

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 4
cts 16
cp 0.25
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 24
nc 11
nop 1
crap 35
1
<?php
2
3
namespace LF\EnvDiff;
4
5
use InvalidArgumentException;
6
use LF\EnvDiff\IO\IOInterface;
7
use RuntimeException;
8
9
class Processor
10
{
11
    /** @var IOInterface */
12
    private $io;
13
14
    /**
15
     * Processor constructor.
16
     *
17
     * @param IOInterface $io
18
     */
19
    public function __construct(IOInterface $io)
20
    {
21 13
        $this->io = $io;
22
    }
23 13
24 13
    /**
25
     * @param Config $config
26
     *
27
     * @throws InvalidArgumentException
28
     * @throws RuntimeException
29
     *
30
     * @return bool
31
     */
32 13
    public function actualizeEnv(Config $config)
33
    {
34 13
        $dist   = $config->getDist();
35 13
        $target = $config->getTarget();
36
        $exists = is_file($target);
37 13
38 12
        $this->io->write(sprintf('Actualize env from %s', $dist));
39
40 12
        try {
41
            $distEnv   = Env::parse($dist);
0 ignored issues
show
Documentation introduced by
$dist is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
42 12
            $actualEnv = $exists ? Env::parse($target) : [];
0 ignored issues
show
Documentation introduced by
$target is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
43
        } catch (InvalidArgumentException $exception) {
44 12
            $this->io->write(sprintf('<error>%s, abort</error>', $exception->getMessage()));
45
46
            return true;
47
        }
48 12
49 12
        $actualEnv = $this->processEnv($distEnv, $actualEnv, $config->isKeepOutdatedEnv());
50 12
51 12
        if (!is_dir($dir = dirname($target))) {
52 12
            mkdir($dir, 0755, true);
53 12
        }
54
55
        ksort($actualEnv);
56
        file_put_contents(
57
            $target,
58
            '# This file is auto-generated during the composer install' . PHP_EOL . Env::dump($actualEnv)
59
        );
60
61
        $this->io->write(sprintf('<info>%s has been %s</info>', $target, $exists ? 'updated' : 'created'));
62
63
        return false;
64
    }
65
66
    /**
67
     * @param Config $config
68
     *
69
     * @throws InvalidArgumentException
70
     *
71
     * @return bool
72
     */
73
    public function showDifference(Config $config)
74
    {
75
        $dist   = $config->getDist();
76
        $target = $config->getTarget();
77
78
        try {
79
            $distEnv   = Env::parse($dist);
0 ignored issues
show
Documentation introduced by
$dist is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
80
            $actualEnv = Env::parse($target);
0 ignored issues
show
Documentation introduced by
$target is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
81
        } catch (InvalidArgumentException $exception) {
82
            $this->io->write(sprintf('<error>%s</error>', $exception->getMessage()));
83
84
            return true;
85
        }
86
87
        $extraEnv   = array_diff_key($actualEnv, $distEnv);
88
        $missingEnv = array_diff_key($distEnv, $actualEnv);
89
        $changedEnv = array_diff(array_intersect_key($distEnv, $actualEnv), $actualEnv);
90
91
        if (!count($missingEnv) && !count($extraEnv) && !count($changedEnv)) {
92
            $this->io->write(sprintf('<info>%s and %s is identical</info>', $target, $dist));
93
94 12
            return false;
95
        }
96 12
97
        $this->io->write(sprintf('Diff between %s and %s files:', $target, $dist));
98
        $this->io->write('');
99
100 12
        foreach ($missingEnv as $env => $value) {
101
            $this->io->write(sprintf('<fg=red>- %s=%s</>', $env, $value));
102
        }
103
        foreach ($extraEnv as $env => $value) {
104
            $this->io->write(sprintf('<fg=green>+ %s=%s</>', $env, $value));
105
        }
106
        foreach ($changedEnv as $env => $default) {
107
            $this->io->write(sprintf('<fg=cyan>@ %s=%s (%s)</>', $env, $actualEnv[$env], $default));
108
        }
109
110
        return false;
111 12
    }
112
113 12
    /**
114 6
     * @param array $expectedEnv
115
     * @param array $actualEnv
116
     * @param bool  $keepOutdated
117 6
     *
118 6
     * @return array
119 3
     *
120
     * @throws RuntimeException
121 3
     */
122 3
    private function processEnv(array $expectedEnv, array $actualEnv, $keepOutdated)
123 3
    {
124
        if (false === $keepOutdated) {
125 3
            $actualEnv = array_intersect_key($actualEnv, $expectedEnv);
126 3
        }
127 3
128
        return $this->getEnv($expectedEnv, $actualEnv);
129 6
    }
130
131
    /**
132
     * @param array $expectedEnv
133
     * @param array $actualEnv
134
     *
135
     * @return array
136
     *
137
     * @throws RuntimeException
138
     */
139
    private function getEnv(array $expectedEnv, array $actualEnv)
140
    {
141
        if (!$this->io->isInteractive()) {
142
            return array_replace($expectedEnv, $actualEnv);
143
        }
144
145
        $diffEnv = array_diff_key($expectedEnv, $actualEnv);
146
        if (count($diffEnv) > 0) {
147
            $this->io->write('<comment>Some env variables are missing. Please provide them.</comment>');
148
149
            foreach ($diffEnv as $env => $default) {
150
                $actualEnv[$env] = $this->io->ask(
151
                    sprintf('<question>%s</question> (<comment>%s</comment>): ', $env, $default),
152
                    $default
153
                );
154
            }
155
        }
156
157
        return $actualEnv;
158
    }
159
}
160