Passed
Pull Request — stable (#96)
by
unknown
01:57
created

TestCommand::fromEnvFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace NunoMaduro\Collision\Adapters\Laravel\Commands;
4
5
use Dotenv\Dotenv;
6
use Illuminate\Console\Command;
7
use Illuminate\Support\Str;
8
use RuntimeException;
9
use Symfony\Component\Process\Exception\ProcessSignaledException;
10
use Symfony\Component\Process\Process;
11
12
class TestCommand extends Command
13
{
14
    /**
15
     * The name and signature of the console command.
16
     *
17
     * @var string
18
     */
19
    protected $signature = 'test {--without-tty : Disable output to TTY}';
20
21
    /**
22
     * The console command description.
23
     *
24
     * @var string
25
     */
26
    protected $description = 'Run the application tests';
27
28
    /**
29
     * The arguments to be used while calling phpunit.
30
     *
31
     * @var array
32
     */
33
    protected $arguments = [
34
        '--printer',
35
        'NunoMaduro\Collision\Adapters\Phpunit\Printer',
36
    ];
37
38
    /**
39
     * Create a new command instance.
40
     *
41
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
42
     */
43
    public function __construct()
44
    {
45
        parent::__construct();
46
47
        $this->ignoreValidationErrors();
48
    }
49
50
    /**
51
     * Execute the console command.
52
     *
53
     * @return mixed
54
     */
55
    public function handle()
56
    {
57
        $options = array_slice($_SERVER['argv'], $this->option('without-tty') ? 3 : 2);
58
59
        $envs = $this->phpunitEnvs();
60
61
        $process = (new Process(array_merge(
62
            $this->binary(),
63
            array_merge(
64
                $this->arguments,
65
                $this->phpunitArguments($options)
66
            )
67
        ), null, $envs))->setTimeout(null);
68
69
        try {
70
            $process->setTty(! $this->option('without-tty'));
71
        } catch (RuntimeException $e) {
72
            $this->output->writeln('Warning: '.$e->getMessage());
73
        }
74
75
        try {
76
            return $process->run(function ($type, $line) {
77
                $this->output->write($line);
78
            });
79
        } catch (ProcessSignaledException $e) {
80
            if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) {
81
                throw $e;
82
            }
83
        }
84
    }
85
86
    /**
87
     * Get the PHP binary to execute.
88
     *
89
     * @return array
90
     */
91
    protected function binary()
92
    {
93
        if ('phpdbg' === PHP_SAPI) {
94
            return [PHP_BINARY, '-qrr', 'vendor/phpunit/phpunit/phpunit'];
95
        }
96
97
        return [PHP_BINARY, 'vendor/phpunit/phpunit/phpunit'];
98
    }
99
100
    /**
101
     * Get the array of arguments for running PHPUnit.
102
     *
103
     * @param  array  $options
104
     *
105
     * @return array
106
     */
107
    protected function phpunitArguments($options)
108
    {
109
        $options = array_values(array_filter($options, function ($option) {
110
            return ! Str::startsWith($option, '--env=');
111
        }));
112
113
        if (! file_exists($file = base_path('phpunit.xml'))) {
114
            $file = base_path('phpunit.xml.dist');
115
        }
116
117
        return array_merge(['-c', $file], $options);
118
    }
119
120
    /**
121
     * Gets an array with phpunit envs detected on the phpunit.xml file.
122
     *
123
     * @return array
124
     */
125
    protected function phpunitEnvs()
126
    {
127
        $envs = [];
128
129
        if (! file_exists($file = base_path('phpunit.xml'))) {
130
            $file = base_path('phpunit.xml.dist');
131
        }
132
133
134
        if (file_exists($file)) {
135
            /** @var \SimpleXMLElement $xml */
136
            $xml = simplexml_load_string((string) file_get_contents($file));
137
138 View Code Duplication
            if (is_iterable($xml->php->server)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
139
                foreach ($xml->php->server as $env) {
140
                    if (isset($env['name'])) {
141
                        $envs[$env['name']->__toString()] = $env['value'] ? $env['value']->__toString() : false;
142
                    }
143
                }
144
            }
145
146 View Code Duplication
            if (is_iterable($xml->php->env)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
                foreach ($xml->php->env as $env) {
148
                    if (isset($env['name'])) {
149
                        $envs[$env['name']->__toString()] = $env['value'] ? $env['value']->__toString() : false;
150
                    }
151
                }
152
            }
153
        }
154
155
156
        if (!empty($envs['APP_ENV']) && ! $this->option('env')) {
157
            $envs = array_merge($this->fromEnvFile($envs['APP_ENV']), $envs);
158
        }
159
160
        return $envs;
161
    }
162
163
    /**
164
     * Loads the environment file if it exists otherwise returns empty array
165
     *
166
     * @param $environment
167
     * @return array
168
     */
169
    protected function fromEnvFile($environment)
170
    {
171
        return Dotenv::createImmutable(
172
            $this->laravel->environmentPath(),
0 ignored issues
show
Bug introduced by
The method environmentPath() does not exist on Illuminate\Contracts\Foundation\Application. Did you maybe mean environment()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
173
            '.env.' . $environment
174
        )->safeLoad();
175
    }
176
}
177