Skip to content

Commit 04ce8f7

Browse files
authored
Merge pull request #121 from beyondcode/dev
3.0.0
2 parents 99ec962 + 65c50b3 commit 04ce8f7

File tree

10 files changed

+485
-284
lines changed

10 files changed

+485
-284
lines changed

.scrutinizer.yml

Lines changed: 0 additions & 23 deletions
This file was deleted.

.styleci.yml

Lines changed: 0 additions & 4 deletions
This file was deleted.

.travis.yml

Lines changed: 0 additions & 22 deletions
This file was deleted.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ Here is an example output of the command:
1111

1212
## Included checks
1313

14-
- Is the APP_KEY set?
15-
- Are your composer dependencies up to date with the composer.lock file?
14+
- Is the `APP_KEY` set?
15+
- Are your composer dependencies up to date with the `composer.lock` file?
1616
- Do you have the correct PHP version installed?
1717
- Do you have the correct PHP extensions installed?
1818
- Can a connection to the database be established?

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
"php": "^8.2",
2020
"composer/semver": "^1.4|^3.0",
2121
"geerlingguy/ping": "^1.1",
22-
"illuminate/support": "^9.0|^10.0|^11.0",
22+
"illuminate/support": "^9.0|^10.0|^11.0|^12.0",
2323
"vlucas/phpdotenv": "^5.0"
2424
},
2525
"require-dev": {
2626
"larapack/dd": "^1.0",
2727
"mockery/mockery": "^1.0",
28-
"orchestra/testbench": "^7.0|^8.0",
29-
"phpunit/phpunit": "^9.5.10",
30-
"predis/predis": "^1.1",
28+
"orchestra/testbench": "^7.0|^8.0|^10.0",
29+
"phpunit/phpunit": "^9.5.10|^11.5.3",
30+
"predis/predis": "^1.1|^2.3",
3131
"scrutinizer/ocular": "^1.5"
3232
},
3333
"autoload": {

config/config.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
],
3030
\BeyondCode\SelfDiagnosis\Checks\EnvFileExists::class,
3131
\BeyondCode\SelfDiagnosis\Checks\ExampleEnvironmentVariablesAreSet::class,
32+
\BeyondCode\SelfDiagnosis\Checks\UsedEnvironmentVariablesAreDefined::class => [
33+
'directories' => [
34+
config_path(),
35+
app_path(),
36+
],
37+
],
3238
\BeyondCode\SelfDiagnosis\Checks\LocalesAreInstalled::class => [
3339
'required_locales' => [
3440
'en_US',
@@ -65,6 +71,7 @@
6571
\BeyondCode\SelfDiagnosis\Checks\ConfigurationIsNotCached::class,
6672
\BeyondCode\SelfDiagnosis\Checks\RoutesAreNotCached::class,
6773
\BeyondCode\SelfDiagnosis\Checks\ExampleEnvironmentVariablesAreUpToDate::class,
74+
\BeyondCode\SelfDiagnosis\Checks\UsedEnvironmentVariablesAreDefined::class,
6875
],
6976
'production' => [
7077
\BeyondCode\SelfDiagnosis\Checks\ComposerWithoutDevDependenciesIsUpToDate::class,
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
3+
namespace BeyondCode\SelfDiagnosis\Checks;
4+
5+
use Illuminate\Support\Arr;
6+
use Illuminate\Support\Collection;
7+
use RecursiveDirectoryIterator;
8+
use RecursiveIteratorIterator;
9+
use RegexIterator;
10+
11+
class UsedEnvironmentVariablesAreDefined implements Check
12+
{
13+
/**
14+
* Stores processed var names
15+
*
16+
* @var array
17+
*/
18+
private $processed = [];
19+
20+
/**
21+
* Stores undefined var names
22+
*
23+
* @var array
24+
*/
25+
public $undefined = [];
26+
27+
/**
28+
* The amount of undefined .env variables
29+
*
30+
* @var integer
31+
*/
32+
public $amount = 0;
33+
34+
/**
35+
* The name of the check.
36+
*
37+
* @param array $config
38+
* @return string
39+
*/
40+
public function name(array $config): string
41+
{
42+
return trans('self-diagnosis::checks.used_env_variables_are_defined.name');
43+
}
44+
45+
/**
46+
* The error message to display in case the check does not pass.
47+
*
48+
* @param array $config
49+
* @return string
50+
*/
51+
public function message(array $config): string
52+
{
53+
return trans('self-diagnosis::checks.used_env_variables_are_defined.message', [
54+
'amount' => $this->amount,
55+
'undefined' => implode(PHP_EOL, $this->undefined),
56+
]);
57+
}
58+
59+
/**
60+
* Perform the actual verification of this check.
61+
*
62+
* @param array $config
63+
* @return bool
64+
* @throws \Exception
65+
*/
66+
public function check(array $config): bool
67+
{
68+
$paths = Collection::make(Arr::get($config, 'directories', []));
69+
70+
foreach ($paths as $path) {
71+
$files = $this->recursiveDirSearch($path, '/.*?.php/');
72+
73+
foreach ($files as $file) {
74+
preg_match_all(
75+
'# env\((.*?)\)| getenv\((.*?)\)#',
76+
str_replace(["\n", "\r"], '', file_get_contents($file)),
77+
$values
78+
);
79+
80+
$values = array_filter(
81+
array_merge($values[1], $values[2])
82+
);
83+
84+
foreach ($values as $value) {
85+
$result = $this->getResult(
86+
explode(',', str_replace(["'", '"', ' '], '', $value))
87+
);
88+
89+
if (!$result) {
90+
continue;
91+
}
92+
93+
$this->storeResult($result);
94+
}
95+
}
96+
}
97+
98+
return $this->amount === 0;
99+
}
100+
101+
/**
102+
* Get result based on comma separated env() or getenv() parameters
103+
*
104+
* @param array $values
105+
* @return object|bool
106+
*/
107+
private function getResult(array $values)
108+
{
109+
$envVar = $values[0];
110+
111+
if (in_array($envVar, $this->processed, true)) {
112+
return false;
113+
}
114+
115+
$this->processed[] = $envVar;
116+
117+
return (object)[
118+
'envVar' => $envVar,
119+
'hasValue' => env($envVar) !== null,
120+
'hasDefault' => isset($values[1]),
121+
];
122+
}
123+
124+
/**
125+
* Store result based on getResult's return value
126+
*
127+
* @param $result
128+
*/
129+
private function storeResult($result)
130+
{
131+
if (!$result->hasValue && !$result->hasDefault) {
132+
$this->undefined[] = $result->envVar;
133+
$this->amount++;
134+
}
135+
}
136+
137+
/**
138+
* Recursively search folder(s) for files matching pattern
139+
*
140+
* @param string $folder
141+
* @param string $pattern
142+
* @return array
143+
*/
144+
private function recursiveDirSearch(string $folder, string $pattern): array
145+
{
146+
if (!file_exists($folder)) {
147+
return [];
148+
}
149+
150+
$files = new RegexIterator(
151+
new RecursiveIteratorIterator(
152+
new RecursiveDirectoryIterator($folder)
153+
),
154+
$pattern, RegexIterator::GET_MATCH
155+
);
156+
157+
$list = [[]];
158+
159+
foreach ($files as $file) {
160+
$list[] = $file;
161+
}
162+
163+
$list = array_merge(...$list);
164+
165+
return $list;
166+
}
167+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace BeyondCode\SelfDiagnosis\Tests;
4+
5+
use BeyondCode\SelfDiagnosis\Checks\UsedEnvironmentVariablesAreDefined;
6+
use BeyondCode\SelfDiagnosis\SelfDiagnosisServiceProvider;
7+
use Orchestra\Testbench\TestCase;
8+
9+
class UsedEnvironmentVariablesAreDefinedTest extends TestCase
10+
{
11+
public function getPackageProviders($app)
12+
{
13+
return [
14+
SelfDiagnosisServiceProvider::class,
15+
];
16+
}
17+
18+
/** @test
19+
* @throws \Exception
20+
*/
21+
public function it_checks_if_used_env_vars_are_defined()
22+
{
23+
$envPath = base_path('.env');
24+
file_put_contents($envPath, implode("\n", [
25+
'FILLED=value',
26+
'NOT_FILLED=another',
27+
'FILLED_WITH_FALSE=false',
28+
29+
'DEPENDING_ON_DEFAULT=custom',
30+
'DEFAULT_IS_FALSE=false',
31+
'GET_DEPENDING_ON_DEFAULT=default',
32+
]));
33+
34+
\Dotenv\Dotenv::createImmutable(base_path())->load();
35+
36+
env('FILLED');
37+
env('NOT_FILLED');
38+
env('FILLED_WITH_FALSE');
39+
getenv('GET_FILLED');
40+
41+
env('DEPENDING_ON_DEFAULT', 'default');
42+
env('DEFAULT_IS_FALSE', false);
43+
getenv('GET_DEPENDING_ON_DEFAULT', 'default');
44+
45+
env('UNDEFINED');
46+
getenv('GET_UNDEFINED');
47+
env('UNDEFINED');
48+
getenv('GET_UNDEFINED');
49+
50+
$config = [
51+
'directories' => [
52+
__DIR__,
53+
],
54+
];
55+
56+
$check = new \BeyondCode\SelfDiagnosis\Checks\UsedEnvironmentVariablesAreDefined();
57+
58+
$this->assertFalse($check->check($config));
59+
$this->assertSame(2, $check->amount);
60+
$this->assertContains('UNDEFINED', $check->undefined);
61+
$this->assertContains('GET_UNDEFINED', $check->undefined);
62+
$this->assertStringContainsString('2 used environmental variables are undefined:', $check->message($config));
63+
$this->assertStringContainsString('UNDEFINED', $check->message($config));
64+
$this->assertStringContainsString('GET_UNDEFINED', $check->message($config));
65+
66+
unlink($envPath);
67+
}
68+
}

0 commit comments

Comments
 (0)