Compare commits
6 Commits
v2.1.1
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| ade724b3bb | |||
| 532c66ac27 | |||
| 609b89641e | |||
| 8d14445786 | |||
| 979ec79fc0 | |||
| dfe8607934 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,3 +2,7 @@ vendor
|
||||
.phpunit.result.cache
|
||||
.phplint-cache
|
||||
composer.lock
|
||||
**/.env
|
||||
**/.target
|
||||
.phpunit.cache
|
||||
tools/
|
||||
|
||||
118
.phan/config.php
118
.phan/config.php
@@ -26,73 +26,75 @@
|
||||
// use Phan\Config;
|
||||
|
||||
return [
|
||||
// If true, missing properties will be created when
|
||||
// they are first seen. If false, we'll report an
|
||||
// error message.
|
||||
"allow_missing_properties" => false,
|
||||
// turn color on (-C)
|
||||
"color_issue_messages_if_supported" => true,
|
||||
// If true, missing properties will be created when
|
||||
// they are first seen. If false, we'll report an
|
||||
// error message.
|
||||
"allow_missing_properties" => false,
|
||||
|
||||
// Allow null to be cast as any type and for any
|
||||
// type to be cast to null.
|
||||
"null_casts_as_any_type" => false,
|
||||
// Allow null to be cast as any type and for any
|
||||
// type to be cast to null.
|
||||
"null_casts_as_any_type" => false,
|
||||
|
||||
// Backwards Compatibility Checking
|
||||
'backward_compatibility_checks' => true,
|
||||
// Backwards Compatibility Checking
|
||||
'backward_compatibility_checks' => true,
|
||||
|
||||
// Run a quick version of checks that takes less
|
||||
// time
|
||||
"quick_mode" => false,
|
||||
// Run a quick version of checks that takes less
|
||||
// time
|
||||
"quick_mode" => false,
|
||||
|
||||
// Only emit critical issues to start with
|
||||
// (0 is low severity, 5 is normal severity, 10 is critical)
|
||||
"minimum_severity" => 10,
|
||||
// Only emit critical issues to start with
|
||||
// (0 is low severity, 5 is normal severity, 10 is critical)
|
||||
"minimum_severity" => 10,
|
||||
|
||||
// default false for include path check
|
||||
"enable_include_path_checks" => true,
|
||||
"include_paths" => [
|
||||
],
|
||||
'ignore_undeclared_variables_in_global_scope' => true,
|
||||
// default false for include path check
|
||||
"enable_include_path_checks" => true,
|
||||
"include_paths" => [
|
||||
],
|
||||
'ignore_undeclared_variables_in_global_scope' => true,
|
||||
|
||||
"file_list" => [
|
||||
],
|
||||
"file_list" => [
|
||||
],
|
||||
|
||||
// A list of directories that should be parsed for class and
|
||||
// method information. After excluding the directories
|
||||
// defined in exclude_analysis_directory_list, the remaining
|
||||
// files will be statically analyzed for errors.
|
||||
//
|
||||
// Thus, both first-party and third-party code being used by
|
||||
// your application should be included in this list.
|
||||
'directory_list' => [
|
||||
// Change this to include the folders you wish to analyze
|
||||
// (and the folders of their dependencies)
|
||||
'.'
|
||||
// 'www',
|
||||
// To speed up analysis, we recommend going back later and
|
||||
// limiting this to only the vendor/ subdirectories your
|
||||
// project depends on.
|
||||
// `phan --init` will generate a list of folders for you
|
||||
],
|
||||
// A list of directories that should be parsed for class and
|
||||
// method information. After excluding the directories
|
||||
// defined in exclude_analysis_directory_list, the remaining
|
||||
// files will be statically analyzed for errors.
|
||||
//
|
||||
// Thus, both first-party and third-party code being used by
|
||||
// your application should be included in this list.
|
||||
'directory_list' => [
|
||||
// Change this to include the folders you wish to analyze
|
||||
// (and the folders of their dependencies)
|
||||
'.'
|
||||
// 'www',
|
||||
// To speed up analysis, we recommend going back later and
|
||||
// limiting this to only the vendor/ subdirectories your
|
||||
// project depends on.
|
||||
// `phan --init` will generate a list of folders for you
|
||||
],
|
||||
|
||||
|
||||
// A list of directories holding code that we want
|
||||
// to parse, but not analyze
|
||||
"exclude_analysis_directory_list" => [
|
||||
'vendor',
|
||||
'test',
|
||||
'tmp'
|
||||
],
|
||||
'exclude_file_list' => [
|
||||
],
|
||||
// A list of directories holding code that we want
|
||||
// to parse, but not analyze
|
||||
"exclude_analysis_directory_list" => [
|
||||
'vendor',
|
||||
'test',
|
||||
'tmp'
|
||||
],
|
||||
'exclude_file_list' => [
|
||||
],
|
||||
|
||||
// what not to show as problem
|
||||
'suppress_issue_types' => [
|
||||
// 'PhanUndeclaredMethod',
|
||||
'PhanEmptyFile',
|
||||
],
|
||||
// what not to show as problem
|
||||
'suppress_issue_types' => [
|
||||
// 'PhanUndeclaredMethod',
|
||||
'PhanEmptyFile',
|
||||
],
|
||||
|
||||
// Override to hardcode existence and types of (non-builtin) globals in the global scope.
|
||||
// Class names should be prefixed with `\`.
|
||||
//
|
||||
// (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`)
|
||||
'globals_type_map' => [],
|
||||
// Override to hardcode existence and types of (non-builtin) globals in the global scope.
|
||||
// Class names should be prefixed with `\`.
|
||||
//
|
||||
// (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`)
|
||||
'globals_type_map' => [],
|
||||
];
|
||||
|
||||
9
.phive/phars.xml
Normal file
9
.phive/phars.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phive xmlns="https://phar.io/phive">
|
||||
<phar name="phpcs" version="^4.0.1" installed="4.0.1" location="./tools/phpcs" copy="false"/>
|
||||
<phar name="phpcbf" version="^4.0.1" installed="4.0.1" location="./tools/phpcbf" copy="false"/>
|
||||
<phar name="phan" version="^5.5.2" installed="5.5.2" location="./tools/phan" copy="false"/>
|
||||
<phar name="psalm" version="^5.26.1" installed="5.26.1" location="./tools/psalm" copy="false"/>
|
||||
<phar name="phpstan" version="^2.1.33" installed="2.1.33" location="./tools/phpstan" copy="false"/>
|
||||
<phar name="phpunit" version="^12.5.4" installed="12.5.4" location="./tools/phpunit" copy="false"/>
|
||||
</phive>
|
||||
@@ -26,10 +26,10 @@
|
||||
"exclude": ["/test/", "/test/*", "/phpstan.neon", "/psalm.xml", "/.phan/", "/.vscode/", "/phpunit.xml"]
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9",
|
||||
"phan/phan": "^5.4",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpstan/phpdoc-parser": "^2.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0"
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0",
|
||||
"phpstan/phpstan": "2.1.x-dev",
|
||||
"phpunit/phpunit": "^12"
|
||||
}
|
||||
}
|
||||
|
||||
18
phpcs.xml
Normal file
18
phpcs.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="MyStandard">
|
||||
<description>PSR12 override rules (strict, standard). Switch spaces indent to tab.</description>
|
||||
<arg name="tab-width" value="4"/>
|
||||
<rule ref="PSR1"/>
|
||||
<rule ref="PSR12">
|
||||
<!-- turn off white space check for tab -->
|
||||
<exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
|
||||
</rule>
|
||||
<!-- no space indent, must be tab, 4 is tab iwdth -->
|
||||
<rule ref="Generic.WhiteSpace.DisallowSpaceIndent"/>
|
||||
<rule ref="Generic.WhiteSpace.ScopeIndent">
|
||||
<properties>
|
||||
<property name="indent" value="4"/>
|
||||
<property name="tabIndent" value="true"/>
|
||||
</properties>
|
||||
</rule>
|
||||
</ruleset>
|
||||
16
phpunit.xml
16
phpunit.xml
@@ -1,10 +1,8 @@
|
||||
<phpunit
|
||||
colors="true"
|
||||
verbose="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
<directory>test/phpUnitTests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<?xml version="1.0"?>
|
||||
<phpunit colors="true" cacheDirectory=".phpunit.cache">
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
<directory>test/phpUnitTests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
|
||||
216
src/DotEnv.php
216
src/DotEnv.php
@@ -6,115 +6,115 @@ namespace gullevek\dotEnv;
|
||||
|
||||
class DotEnv
|
||||
{
|
||||
/** @var string constant comment char, set to # */
|
||||
private const COMMENT_CHAR = '#';
|
||||
/** @var string constant comment char, set to # */
|
||||
private const COMMENT_CHAR = '#';
|
||||
|
||||
/**
|
||||
* parses .env file
|
||||
*
|
||||
* Rules for .env file
|
||||
* variable is any alphanumeric string followed by = on the same line
|
||||
* content starts with the first non space part
|
||||
* strings can be contained in "
|
||||
* strings MUST be contained in " if they are multiline
|
||||
* if string starts with " it will match until another " is found
|
||||
* anything AFTER " is ignored
|
||||
* if there are two variables with the same name only the first is used
|
||||
* variables are case sensitive
|
||||
*
|
||||
* [] Grouping Block Name as prefix until next or end if set,
|
||||
* space replaced by _, all other var rules apply
|
||||
*
|
||||
* @param string $path Folder to file, default is __DIR__
|
||||
* @param string $env_file What file to load, default is .env
|
||||
* @return int -1 other error
|
||||
* 0 for success full load
|
||||
* 1 for file loadable, no data or data already loaded
|
||||
* 2 for file not readable or open failed
|
||||
* 3 for file not found
|
||||
*/
|
||||
public static function readEnvFile(
|
||||
string $path = __DIR__,
|
||||
string $env_file = '.env'
|
||||
): int {
|
||||
// default -1;
|
||||
$status = -1;
|
||||
$env_file_target = $path . DIRECTORY_SEPARATOR . $env_file;
|
||||
// this is not a file -> abort
|
||||
if (!is_file($env_file_target)) {
|
||||
$status = 3;
|
||||
return $status;
|
||||
}
|
||||
// cannot open file -> abort
|
||||
if (!is_readable($env_file_target)) {
|
||||
$status = 2;
|
||||
return $status;
|
||||
}
|
||||
// open file
|
||||
if (($fp = fopen($env_file_target, 'r')) === false) {
|
||||
$status = 2;
|
||||
return $status;
|
||||
}
|
||||
// set to readable but not yet any data loaded
|
||||
$status = 1;
|
||||
$block = false;
|
||||
$var = '';
|
||||
$prefix_name = '';
|
||||
while (($line = fgets($fp)) !== false) {
|
||||
// [] block must be a single line, or it will be ignored
|
||||
if (preg_match("/^\s*\[([\w_.\s]+)\]/", $line, $matches)) {
|
||||
$prefix_name = preg_replace("/\s+/", "_", $matches[1]) . ".";
|
||||
} elseif (preg_match("/^\s*([\w_.]+)\s*=\s*((\"?).*)/", $line, $matches)) {
|
||||
// main match for variable = value part
|
||||
$var = $prefix_name . $matches[1];
|
||||
$value = $matches[2];
|
||||
$quotes = $matches[3];
|
||||
// write only if env is not set yet, and write only the first time
|
||||
if (empty($_ENV[$var])) {
|
||||
if (!empty($quotes)) {
|
||||
// match greedy for first to last so we move any " if there are
|
||||
if (preg_match('/^"(.*[^\\\])"/U', $value, $matches)) {
|
||||
$value = $matches[1];
|
||||
} else {
|
||||
// this is a multi line
|
||||
$block = true;
|
||||
// first " in string remove
|
||||
// add removed new line back because this is a multi line
|
||||
$value = ltrim($value, '"') . PHP_EOL;
|
||||
}
|
||||
} else {
|
||||
// strip any quotes at end for unquoted single line
|
||||
// an right hand spaces are removed too
|
||||
$value = false !== ($pos = strpos($value, self::COMMENT_CHAR)) ?
|
||||
rtrim(substr($value, 0, $pos)) : $value;
|
||||
}
|
||||
// if block is set, we strip line of slashes
|
||||
$_ENV[$var] = $block === true ? stripslashes($value) : $value;
|
||||
// set successful load
|
||||
$status = 0;
|
||||
}
|
||||
} elseif ($block === true) {
|
||||
// read line until there is a unescaped "
|
||||
// this also strips everything after the last "
|
||||
if (preg_match("/(.*[^\\\])\"/", $line, $matches)) {
|
||||
$block = false;
|
||||
// strip ending " and EVERYTHING that follows after that
|
||||
$line = $matches[1];
|
||||
}
|
||||
// just be sure it is init before we fill
|
||||
if (!isset($_ENV[$var])) {
|
||||
$_ENV[$var] = '';
|
||||
} elseif (!is_string($_ENV[$var])) {
|
||||
// if this is not string, skip
|
||||
continue;
|
||||
}
|
||||
// strip line of slashes
|
||||
$_ENV[$var] .= stripslashes($line);
|
||||
}
|
||||
}
|
||||
fclose($fp);
|
||||
return $status;
|
||||
}
|
||||
/**
|
||||
* parses .env file
|
||||
*
|
||||
* Rules for .env file
|
||||
* variable is any alphanumeric string followed by = on the same line
|
||||
* content starts with the first non space part
|
||||
* strings can be contained in "
|
||||
* strings MUST be contained in " if they are multiline
|
||||
* if string starts with " it will match until another " is found
|
||||
* anything AFTER " is ignored
|
||||
* if there are two variables with the same name only the first is used
|
||||
* variables are case sensitive
|
||||
*
|
||||
* [] Grouping Block Name as prefix until next or end if set,
|
||||
* space replaced by _, all other var rules apply
|
||||
*
|
||||
* @param string $path Folder to file, default is __DIR__
|
||||
* @param string $env_file What file to load, default is .env
|
||||
* @return int -1 other error
|
||||
* 0 for success full load
|
||||
* 1 for file loadable, no data or data already loaded
|
||||
* 2 for file not readable or open failed
|
||||
* 3 for file not found
|
||||
*/
|
||||
public static function readEnvFile(
|
||||
string $path = __DIR__,
|
||||
string $env_file = '.env'
|
||||
): int {
|
||||
// default -1;
|
||||
$status = -1;
|
||||
$env_file_target = $path . DIRECTORY_SEPARATOR . $env_file;
|
||||
// this is not a file -> abort
|
||||
if (!is_file($env_file_target)) {
|
||||
$status = 3;
|
||||
return $status;
|
||||
}
|
||||
// cannot open file -> abort
|
||||
if (!is_readable($env_file_target)) {
|
||||
$status = 2;
|
||||
return $status;
|
||||
}
|
||||
// open file
|
||||
if (($fp = fopen($env_file_target, 'r')) === false) {
|
||||
$status = 2;
|
||||
return $status;
|
||||
}
|
||||
// set to readable but not yet any data loaded
|
||||
$status = 1;
|
||||
$block = false;
|
||||
$var = '';
|
||||
$prefix_name = '';
|
||||
while (($line = fgets($fp)) !== false) {
|
||||
// [] block must be a single line, or it will be ignored
|
||||
if (preg_match("/^\s*\[([\w_.\s]+)\]/", $line, $matches)) {
|
||||
$prefix_name = preg_replace("/\s+/", "_", $matches[1]) . ".";
|
||||
} elseif (preg_match("/^\s*([\w_.]+)\s*=\s*((\"?).*)/", $line, $matches)) {
|
||||
// main match for variable = value part
|
||||
$var = $prefix_name . $matches[1];
|
||||
$value = $matches[2];
|
||||
$quotes = $matches[3];
|
||||
// write only if env is not set yet, and write only the first time
|
||||
if (empty($_ENV[$var])) {
|
||||
if (!empty($quotes)) {
|
||||
// match greedy for first to last so we move any " if there are
|
||||
if (preg_match('/^"(.*[^\\\])"/U', $value, $matches)) {
|
||||
$value = $matches[1];
|
||||
} else {
|
||||
// this is a multi line
|
||||
$block = true;
|
||||
// first " in string remove
|
||||
// add removed new line back because this is a multi line
|
||||
$value = ltrim($value, '"') . PHP_EOL;
|
||||
}
|
||||
} else {
|
||||
// strip any quotes at end for unquoted single line
|
||||
// an right hand spaces are removed too
|
||||
$value = false !== ($pos = strpos($value, self::COMMENT_CHAR)) ?
|
||||
rtrim(substr($value, 0, $pos)) : $value;
|
||||
}
|
||||
// if block is set, we strip line of slashes
|
||||
$_ENV[$var] = $block === true ? stripslashes($value) : $value;
|
||||
// set successful load
|
||||
$status = 0;
|
||||
}
|
||||
} elseif ($block === true) {
|
||||
// read line until there is a unescaped "
|
||||
// this also strips everything after the last "
|
||||
if (preg_match("/(.*[^\\\])\"/", $line, $matches)) {
|
||||
$block = false;
|
||||
// strip ending " and EVERYTHING that follows after that
|
||||
$line = $matches[1];
|
||||
}
|
||||
// just be sure it is init before we fill
|
||||
if (!isset($_ENV[$var])) {
|
||||
$_ENV[$var] = '';
|
||||
} elseif (!is_string($_ENV[$var])) {
|
||||
// if this is not string, skip
|
||||
continue;
|
||||
}
|
||||
// strip line of slashes
|
||||
$_ENV[$var] .= stripslashes($line);
|
||||
}
|
||||
}
|
||||
fclose($fp);
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -5,209 +5,214 @@ declare(strict_types=1);
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\Attributes\TestDox;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\CoversMethod;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
/**
|
||||
* Test class for DotEnv
|
||||
* @coversDefaultClass \gullevek\DotEnv
|
||||
* @testdox \gullevek\DotEnv method tests
|
||||
*/
|
||||
#[TestDox("\gullevek\DotEnv method tests")]
|
||||
#[CoversClass(\gullevek\dotEnv\DotEnv::class)]
|
||||
#[CoversMethod(\gullevek\dotEnv\DotEnv::class, 'readEnvFile')]
|
||||
final class DotEnvTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* setup the .env files before test run
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
// create .env files
|
||||
$file_content = __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'dotenv' . DIRECTORY_SEPARATOR
|
||||
. 'test.env';
|
||||
// copy to all folder levels
|
||||
$env_files = [
|
||||
__DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'dotenv' . DIRECTORY_SEPARATOR
|
||||
. '.env',
|
||||
__DIR__ . DIRECTORY_SEPARATOR
|
||||
. '.env',
|
||||
__DIR__ . DIRECTORY_SEPARATOR
|
||||
. '..' . DIRECTORY_SEPARATOR
|
||||
. '.env',
|
||||
];
|
||||
// if not found, skip -> all will fail
|
||||
if (is_file($file_content)) {
|
||||
foreach ($env_files as $env_file) {
|
||||
copy($file_content, $env_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* setup the .env files before test run
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
// create .env files
|
||||
$file_content = __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'dotenv' . DIRECTORY_SEPARATOR
|
||||
. 'test.env';
|
||||
// copy to all folder levels
|
||||
$env_files = [
|
||||
__DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'dotenv' . DIRECTORY_SEPARATOR
|
||||
. '.env',
|
||||
__DIR__ . DIRECTORY_SEPARATOR
|
||||
. '.env',
|
||||
__DIR__ . DIRECTORY_SEPARATOR
|
||||
. '..' . DIRECTORY_SEPARATOR
|
||||
. '.env',
|
||||
];
|
||||
// if not found, skip -> all will fail
|
||||
if (is_file($file_content)) {
|
||||
foreach ($env_files as $env_file) {
|
||||
copy($file_content, $env_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function envFileProvider(): array
|
||||
{
|
||||
$dot_env_content = [
|
||||
'SOMETHING' => 'A',
|
||||
'OTHER' => 'B IS B',
|
||||
'Complex' => 'A B \"D is F',
|
||||
'HAS_SPACE' => 'ABC',
|
||||
'HAS_COMMENT_QUOTES_SPACE' => 'Comment at end with quotes and space',
|
||||
'HAS_COMMENT_QUOTES_NO_SPACE' => 'Comment at end with quotes no space',
|
||||
'HAS_COMMENT_NO_QUOTES_SPACE' => 'Comment at end no quotes and space',
|
||||
'HAS_COMMENT_NO_QUOTES_NO_SPACE' => 'Comment at end no quotes no space',
|
||||
'COMMENT_IN_TEXT_QUOTES' => 'Foo bar # comment in here',
|
||||
'HAS_EQUAL_NO_QUITES' => 'Is This = Valid',
|
||||
'HAS_EQUAL_QUITES' => 'Is This = Valid',
|
||||
'FAILURE' => 'ABC',
|
||||
'SIMPLEBOX' => 'A B C',
|
||||
'TITLE' => '1',
|
||||
'FOO' => '1.2',
|
||||
'SOME.TEST' => 'Test Var',
|
||||
'SOME.LIVE' => 'Live Var',
|
||||
'A_TEST1' => 'foo',
|
||||
'A_TEST2' => '${TEST1:-bar}',
|
||||
'A_TEST3' => '${TEST4:-bar}',
|
||||
'A_TEST5' => 'null',
|
||||
'A_TEST6' => '${TEST5-bar}',
|
||||
'A_TEST7' => '${TEST6:-bar}',
|
||||
'B_TEST1' => 'foo',
|
||||
'B_TEST2' => '${TEST1:=bar}',
|
||||
'B_TEST3' => '${TEST4:=bar}',
|
||||
'B_TEST5' => 'null',
|
||||
'B_TEST6' => '${TEST5=bar}',
|
||||
'B_TEST7' => '${TEST6=bar}',
|
||||
'Test' => 'A',
|
||||
'TEST' => 'B',
|
||||
'LINE' => "ABC\nDEF",
|
||||
'OTHERLINE' => "ABC\nAF\"ASFASDF\nMORESHIT",
|
||||
'SUPERLINE' => '',
|
||||
'__FOO_BAR_1' => 'b',
|
||||
'__FOOFOO' => 'f ',
|
||||
123123 => 'number',
|
||||
'EMPTY' => '',
|
||||
'Var_Test.TEST' => 'Block 1 D',
|
||||
'OtherSet.TEST' => 'Block 2 D',
|
||||
];
|
||||
// 0: folder relative to test folder, if unset __DIR__
|
||||
// 1: file, if unset .env
|
||||
// 2: status to be returned
|
||||
// 3: _ENV file content to be set
|
||||
// 4: override chmod as octect in string
|
||||
return [
|
||||
'default' => [
|
||||
'folder' => null,
|
||||
'file' => null,
|
||||
'status' => 3,
|
||||
'content' => [],
|
||||
'chmod' => null,
|
||||
],
|
||||
'cannot open file' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'cannot_read.env',
|
||||
'status' => 2,
|
||||
'content' => [],
|
||||
// 0000
|
||||
'chmod' => '100000',
|
||||
],
|
||||
'empty file' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'empty.env',
|
||||
'status' => 1,
|
||||
'content' => [],
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override all' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'test.env',
|
||||
'status' => 0,
|
||||
'content' => $dot_env_content,
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override directory' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => null,
|
||||
'status' => 0,
|
||||
'content' => $dot_env_content,
|
||||
'chmod' => null,
|
||||
],
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function envFileProvider(): array
|
||||
{
|
||||
$dot_env_content = [
|
||||
'SOMETHING' => 'A',
|
||||
'OTHER' => 'B IS B',
|
||||
'Complex' => 'A B \"D is F',
|
||||
'HAS_SPACE' => 'ABC',
|
||||
'HAS_COMMENT_QUOTES_SPACE' => 'Comment at end with quotes and space',
|
||||
'HAS_COMMENT_QUOTES_NO_SPACE' => 'Comment at end with quotes no space',
|
||||
'HAS_COMMENT_NO_QUOTES_SPACE' => 'Comment at end no quotes and space',
|
||||
'HAS_COMMENT_NO_QUOTES_NO_SPACE' => 'Comment at end no quotes no space',
|
||||
'COMMENT_IN_TEXT_QUOTES' => 'Foo bar # comment in here',
|
||||
'HAS_EQUAL_NO_QUITES' => 'Is This = Valid',
|
||||
'HAS_EQUAL_QUITES' => 'Is This = Valid',
|
||||
'FAILURE' => 'ABC',
|
||||
'SIMPLEBOX' => 'A B C',
|
||||
'TITLE' => '1',
|
||||
'FOO' => '1.2',
|
||||
'SOME.TEST' => 'Test Var',
|
||||
'SOME.LIVE' => 'Live Var',
|
||||
'A_TEST1' => 'foo',
|
||||
'A_TEST2' => '${TEST1:-bar}',
|
||||
'A_TEST3' => '${TEST4:-bar}',
|
||||
'A_TEST5' => 'null',
|
||||
'A_TEST6' => '${TEST5-bar}',
|
||||
'A_TEST7' => '${TEST6:-bar}',
|
||||
'B_TEST1' => 'foo',
|
||||
'B_TEST2' => '${TEST1:=bar}',
|
||||
'B_TEST3' => '${TEST4:=bar}',
|
||||
'B_TEST5' => 'null',
|
||||
'B_TEST6' => '${TEST5=bar}',
|
||||
'B_TEST7' => '${TEST6=bar}',
|
||||
'Test' => 'A',
|
||||
'TEST' => 'B',
|
||||
'LINE' => "ABC\nDEF",
|
||||
'OTHERLINE' => "ABC\nAF\"ASFASDF\nMORESHIT",
|
||||
'SUPERLINE' => '',
|
||||
'__FOO_BAR_1' => 'b',
|
||||
'__FOOFOO' => 'f ',
|
||||
123123 => 'number',
|
||||
'EMPTY' => '',
|
||||
'Var_Test.TEST' => 'Block 1 D',
|
||||
'OtherSet.TEST' => 'Block 2 D',
|
||||
];
|
||||
// 0: folder relative to test folder, if unset __DIR__
|
||||
// 1: file, if unset .env
|
||||
// 2: status to be returned
|
||||
// 3: _ENV file content to be set
|
||||
// 4: override chmod as octect in string
|
||||
return [
|
||||
'default' => [
|
||||
'folder' => null,
|
||||
'file' => null,
|
||||
'expected_status' => 3,
|
||||
'expected_env' => [],
|
||||
'chmod' => null,
|
||||
],
|
||||
'cannot open file' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'cannot_read.env',
|
||||
'expected_status' => 2,
|
||||
'expected_env' => [],
|
||||
// 0000
|
||||
'chmod' => '100000',
|
||||
],
|
||||
'empty file' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'empty.env',
|
||||
'expected_status' => 1,
|
||||
'expected_env' => [],
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override all' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'test.env',
|
||||
'expected_status' => 0,
|
||||
'expected_env' => $dot_env_content,
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override directory' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => null,
|
||||
'expected_status' => 0,
|
||||
'expected_env' => $dot_env_content,
|
||||
'chmod' => null,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* test read .env file
|
||||
*
|
||||
* @covers ::readEnvFile
|
||||
* @dataProvider envFileProvider
|
||||
* @testdox Read _ENV file from $folder / $file with expected status: $expected_status [$_dataName]
|
||||
*
|
||||
* @param string|null $folder
|
||||
* @param string|null $file
|
||||
* @param int $expected_status
|
||||
* @param array $expected_env
|
||||
* @param string|null $chmod
|
||||
* @return void
|
||||
*/
|
||||
public function testReadEnvFile(
|
||||
?string $folder,
|
||||
?string $file,
|
||||
int $expected_status,
|
||||
array $expected_env,
|
||||
?string $chmod
|
||||
): void {
|
||||
// skip if chmod is set to 10000 (000 no rights) if we are root
|
||||
// as root there is no stop reading a file
|
||||
if (
|
||||
!empty($chmod) &&
|
||||
$chmod == '100000' &&
|
||||
getmyuid() == 0
|
||||
) {
|
||||
$this->markTestSkipped(
|
||||
"Skip cannot read file test because run user is root"
|
||||
);
|
||||
return;
|
||||
}
|
||||
// reset $_ENV for clean compare
|
||||
$_ENV = [];
|
||||
// previous file perm
|
||||
$old_chmod = null;
|
||||
// if we have change permission for file
|
||||
if (
|
||||
is_file($folder . DIRECTORY_SEPARATOR . $file) &&
|
||||
!empty($chmod)
|
||||
) {
|
||||
// get the old permissions
|
||||
$old_chmod = fileperms($folder . DIRECTORY_SEPARATOR . $file);
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, octdec($chmod));
|
||||
}
|
||||
if ($folder !== null && $file !== null) {
|
||||
$status = \gullevek\dotEnv\DotEnv::readEnvFile($folder, $file);
|
||||
} elseif ($folder !== null) {
|
||||
$status = \gullevek\dotEnv\DotEnv::readEnvFile($folder);
|
||||
} else {
|
||||
$status = \gullevek\dotEnv\DotEnv::readEnvFile();
|
||||
}
|
||||
$this->assertEquals(
|
||||
$status,
|
||||
$expected_status,
|
||||
'Assert returned status equal'
|
||||
);
|
||||
// now assert read data
|
||||
$this->assertEquals(
|
||||
$_ENV,
|
||||
$expected_env,
|
||||
'Assert _ENV correct'
|
||||
);
|
||||
// if we have file and chmod unset
|
||||
if ($old_chmod !== null) {
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, $old_chmod);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* test read .env file
|
||||
*
|
||||
* @param string|null $folder
|
||||
* @param string|null $file
|
||||
* @param int $expected_status
|
||||
* @param array $expected_env
|
||||
* @param string|null $chmod
|
||||
* @return void
|
||||
*/
|
||||
#[Test]
|
||||
#[TestDox('Read _ENV file from $folder / $file with expected status: $expected_status [$_dataName]')]
|
||||
#[DataProvider('envFileProvider')]
|
||||
public function testReadEnvFile(
|
||||
?string $folder,
|
||||
?string $file,
|
||||
int $expected_status,
|
||||
array $expected_env,
|
||||
?string $chmod
|
||||
): void {
|
||||
// skip if chmod is set to 10000 (000 no rights) if we are root
|
||||
// as root there is no stop reading a file
|
||||
if (
|
||||
!empty($chmod) &&
|
||||
$chmod == '100000' &&
|
||||
getmyuid() == 0
|
||||
) {
|
||||
$this->markTestSkipped(
|
||||
"Skip cannot read file test because run user is root"
|
||||
);
|
||||
return;
|
||||
}
|
||||
// reset $_ENV for clean compare
|
||||
$_ENV = [];
|
||||
// previous file perm
|
||||
$old_chmod = null;
|
||||
// if we have change permission for file
|
||||
if (
|
||||
is_file($folder . DIRECTORY_SEPARATOR . $file) &&
|
||||
!empty($chmod)
|
||||
) {
|
||||
// get the old permissions
|
||||
$old_chmod = fileperms($folder . DIRECTORY_SEPARATOR . $file);
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, octdec($chmod));
|
||||
}
|
||||
if ($folder !== null && $file !== null) {
|
||||
$status = \gullevek\dotEnv\DotEnv::readEnvFile($folder, $file);
|
||||
} elseif ($folder !== null) {
|
||||
$status = \gullevek\dotEnv\DotEnv::readEnvFile($folder);
|
||||
} else {
|
||||
$status = \gullevek\dotEnv\DotEnv::readEnvFile();
|
||||
}
|
||||
$this->assertEquals(
|
||||
$expected_status,
|
||||
$status,
|
||||
'Assert returned status equal'
|
||||
);
|
||||
// now assert read data
|
||||
$this->assertEquals(
|
||||
$expected_env,
|
||||
$_ENV,
|
||||
'Assert _ENV correct'
|
||||
);
|
||||
// if we have file and chmod unset
|
||||
if ($old_chmod !== null) {
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, $old_chmod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -8,18 +8,18 @@ use gullevek\dotEnv\DotEnv;
|
||||
|
||||
// copy test file to .env file in env folder
|
||||
$file_content = __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'phpUnitTests' . DIRECTORY_SEPARATOR
|
||||
. 'dotenv' . DIRECTORY_SEPARATOR
|
||||
. 'test.env';
|
||||
. 'phpUnitTests' . DIRECTORY_SEPARATOR
|
||||
. 'dotenv' . DIRECTORY_SEPARATOR
|
||||
. 'test.env';
|
||||
// env folder
|
||||
$env_file = __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'env' . DIRECTORY_SEPARATOR
|
||||
. '.env';
|
||||
. 'env' . DIRECTORY_SEPARATOR
|
||||
. '.env';
|
||||
if (!is_file($file_content)) {
|
||||
die("Cannot read $file_content");
|
||||
die("Cannot read $file_content");
|
||||
}
|
||||
if (copy($file_content, $env_file) === false) {
|
||||
die("Cannot copy $file_content to $env_file");
|
||||
die("Cannot copy $file_content to $env_file");
|
||||
}
|
||||
|
||||
print "BASE: " . __DIR__ . "<br>";
|
||||
|
||||
Reference in New Issue
Block a user