Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add check for empty environmental variables #84

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
7 changes: 7 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
],
\BeyondCode\SelfDiagnosis\Checks\EnvFileExists::class,
\BeyondCode\SelfDiagnosis\Checks\ExampleEnvironmentVariablesAreSet::class,
\BeyondCode\SelfDiagnosis\Checks\UsedEnvironmentVariablesAreDefined::class => [
'directories' => [
config_path(),
app_path(),
],
],
\BeyondCode\SelfDiagnosis\Checks\LocalesAreInstalled::class => [
'required_locales' => [
'en_US',
Expand Down Expand Up @@ -65,6 +71,7 @@
\BeyondCode\SelfDiagnosis\Checks\ConfigurationIsNotCached::class,
\BeyondCode\SelfDiagnosis\Checks\RoutesAreNotCached::class,
\BeyondCode\SelfDiagnosis\Checks\ExampleEnvironmentVariablesAreUpToDate::class,
\BeyondCode\SelfDiagnosis\Checks\UsedEnvironmentVariablesAreDefined::class,
],
'production' => [
\BeyondCode\SelfDiagnosis\Checks\ComposerWithoutDevDependenciesIsUpToDate::class,
Expand Down
6 changes: 6 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,10 @@
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
<php>
<env name="FILLED" value="filled" force="true" />
<env name="GET_FILLED" value="filled" force="true" />
<env name="NOT_FILLED" value="" force="true" />
<env name="FILLED_WITH_FALSE" value="false" force="true" />
</php>
</phpunit>
167 changes: 167 additions & 0 deletions src/Checks/UsedEnvironmentVariablesAreDefined.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php

namespace BeyondCode\SelfDiagnosis\Checks;

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RegexIterator;

class UsedEnvironmentVariablesAreDefined implements Check
{
/**
* Stores processed var names
*
* @var array
*/
private $processed = [];

/**
* Stores undefined var names
*
* @var array
*/
public $undefined = [];

/**
* The amount of undefined .env variables
*
* @var integer
*/
public $amount = 0;

/**
* The name of the check.
*
* @param array $config
* @return string
*/
public function name(array $config): string
{
return trans('self-diagnosis::checks.used_env_variables_are_defined.name');
}

/**
* The error message to display in case the check does not pass.
*
* @param array $config
* @return string
*/
public function message(array $config): string
{
return trans('self-diagnosis::checks.used_env_variables_are_defined.message', [
'amount' => $this->amount,
'undefined' => implode(PHP_EOL, $this->undefined),
]);
}

/**
* Perform the actual verification of this check.
*
* @param array $config
* @return bool
* @throws \Exception
*/
public function check(array $config): bool
{
$paths = Collection::make(Arr::get($config, 'directories', []));

foreach ($paths as $path) {
$files = $this->recursiveDirSearch($path, '/.*?.php/');

foreach ($files as $file) {
preg_match_all(
'# env\((.*?)\)| getenv\((.*?)\)#',
str_replace(["\n", "\r"], '', file_get_contents($file)),
$values
);

$values = array_filter(
array_merge($values[1], $values[2])
);

foreach ($values as $value) {
$result = $this->getResult(
explode(',', str_replace(["'", '"', ' '], '', $value))
);

if (!$result) {
continue;
}

$this->storeResult($result);
}
}
}

return $this->amount === 0;
}

/**
* Get result based on comma separated env() or getenv() parameters
*
* @param array $values
* @return object|bool
*/
private function getResult(array $values)
{
$envVar = $values[0];

if (in_array($envVar, $this->processed, true)) {
return false;
}

$this->processed[] = $envVar;

return (object)[
'envVar' => $envVar,
'hasValue' => env($envVar) !== null,
'hasDefault' => isset($values[1]),
];
}

/**
* Store result based on getResult's return value
*
* @param $result
*/
private function storeResult($result)
{
if (!$result->hasValue && !$result->hasDefault) {
$this->undefined[] = $result->envVar;
$this->amount++;
}
}

/**
* Recursively search folder(s) for files matching pattern
*
* @param string $folder
* @param string $pattern
* @return array
*/
private function recursiveDirSearch(string $folder, string $pattern): array
{
if (!file_exists($folder)) {
return [];
}

$files = new RegexIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($folder)
),
$pattern, RegexIterator::GET_MATCH
);

$list = [[]];

foreach ($files as $file) {
$list[] = $file;
}

$list = array_merge(...$list);

return $list;
}
}
55 changes: 55 additions & 0 deletions tests/UsedEnvironmentVariablesAreDefinedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace BeyondCode\SelfDiagnosis\Tests;

use BeyondCode\SelfDiagnosis\Checks\UsedEnvironmentVariablesAreDefined;
use BeyondCode\SelfDiagnosis\SelfDiagnosisServiceProvider;
use Orchestra\Testbench\TestCase;

class UsedEnvironmentVariablesAreDefinedTest extends TestCase
{
public function getPackageProviders($app)
{
return [
SelfDiagnosisServiceProvider::class,
];
}

/** @test
* @throws \Exception
*/
public function it_checks_if_used_env_vars_are_defined()
{
env('FILLED');
env('NOT_FILLED');
env('FILLED_WITH_FALSE');
getenv('GET_FILLED');

env('DEPENDING_ON_DEFAULT', 'default');
env('DEFAULT_IS_FALSE', false);
getenv('GET_DEPENDING_ON_DEFAULT', 'default');

env('UNDEFINED');
getenv('GET_UNDEFINED');
// Doubles should be ignored
env('UNDEFINED');
getenv('GET_UNDEFINED');

$config = [
'directories' => [
__DIR__
],
];

$check = new UsedEnvironmentVariablesAreDefined();

$this->assertFalse($check->check($config));
$this->assertSame($check->amount, 2);
$this->assertContains('UNDEFINED', $check->undefined);
$this->assertContains('GET_UNDEFINED', $check->undefined);
$this->assertSame(
"2 used environmental variables are undefined: \nUNDEFINED\nGET_UNDEFINED",
$check->message($config)
);
}
}
Loading