Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d14445786 | |||
| 979ec79fc0 | |||
| dfe8607934 | |||
| a7ade86485 | |||
| b9feacaded | |||
| 646456b86b | |||
| 4b0550b8d2 | |||
| efb99f259e | |||
| 72f4827985 | |||
| d5bf24c8cf | |||
| 773f40e2d1 | |||
| 0bb137dff6 | |||
| 7e1a19b86b | |||
| 2524092cd8 | |||
| f692ca41b1 | |||
| b9620704bc | |||
| 5004e3c9d8 | |||
| e86528a366 | |||
| e99a995a2e | |||
| e29f9fcd88 | |||
| ae0eb1f939 |
35
.github/workflows/ci.yml
vendored
Normal file
35
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: CI
|
||||
run-name: ${{ github.actor}} runs CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
ci-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: php-actions/composer@v6
|
||||
env:
|
||||
COMPOSER_ROOT_VERSION: dev-master
|
||||
- name: "Restore result cache"
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ./tmp
|
||||
key: "result-cache-v1-${{ matrix.php-version }}-${{ github.run_id }}"
|
||||
restore-keys: |
|
||||
result-cache-v1-${{ matrix.php-version }}-
|
||||
- name: PHPStan Static Analysis
|
||||
uses: php-actions/phpstan@v3
|
||||
with:
|
||||
path: src/
|
||||
configuration: phpstan.neon
|
||||
- name: "Save result cache"
|
||||
uses: actions/cache/save@v4
|
||||
if: always()
|
||||
with:
|
||||
path: ./tmp
|
||||
key: "result-cache-v1-${{ matrix.php-version }}-${{ github.run_id }}"
|
||||
# We need to use phpunit from the self install to get the class paths
|
||||
- name: PHPunit Tests
|
||||
run: |
|
||||
vendor/bin/phpunit
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,3 +2,6 @@ vendor
|
||||
.phpunit.result.cache
|
||||
.phplint-cache
|
||||
composer.lock
|
||||
**/.env
|
||||
**/.target
|
||||
.phpunit.cache
|
||||
|
||||
@@ -78,7 +78,8 @@ return [
|
||||
// to parse, but not analyze
|
||||
"exclude_analysis_directory_list" => [
|
||||
'vendor',
|
||||
'test'
|
||||
'test',
|
||||
'tmp'
|
||||
],
|
||||
'exclude_file_list' => [
|
||||
],
|
||||
|
||||
23
Readme.md
23
Readme.md
@@ -61,6 +61,29 @@ DOUBLE="I will be used"
|
||||
DOUBLE="This will be ignored"
|
||||
```
|
||||
|
||||
A prefix name can be set with `[PrefixName]`. Tne name rules are like for variables, but spaces
|
||||
are allowed, but will be converted to "_".
|
||||
The prefix is valid from the time set until the next prefix block appears or the file ends.
|
||||
|
||||
Example
|
||||
|
||||
```ini
|
||||
FOO="bar"
|
||||
FOOBAR="bar bar"
|
||||
[SecitonA]
|
||||
FOO="other bar"
|
||||
FOOBAR="other bar bar"
|
||||
```
|
||||
|
||||
Will have environmen variables as
|
||||
|
||||
```php
|
||||
$_ENV["FOO"];
|
||||
$_ENV["FOOBAR"];
|
||||
$_ENV["SecitonA.FOO"];
|
||||
$_ENV["SecitonA.FOOBAR"];
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Phan
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"license": "MIT",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"gullevek\\dotEnv\\": "src/"
|
||||
"gullevek\\dotEnv\\": "src/",
|
||||
"gullevek\\dotenv\\": "src/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
@@ -25,8 +26,10 @@
|
||||
"exclude": ["/test/", "/test/*", "/phpstan.neon", "/psalm.xml", "/.phan/", "/.vscode/", "/phpunit.xml"]
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9",
|
||||
"phpstan/phpstan": "1.10.x-dev",
|
||||
"phan/phan": "v5.x-dev"
|
||||
"phan/phan": "^5.4",
|
||||
"phpstan/phpdoc-parser": "^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>
|
||||
@@ -1,10 +1,10 @@
|
||||
# PHP Stan Config
|
||||
|
||||
parameters:
|
||||
tmpDir: /tmp/phpstan-codeblocks-dotenv
|
||||
tmpDir: %currentWorkingDirectory%/tmp/phpstan-codeblocks-dotenv
|
||||
level: max
|
||||
paths:
|
||||
- %currentWorkingDirectory%
|
||||
- %currentWorkingDirectory%/src
|
||||
excludePaths:
|
||||
- vendor
|
||||
- test
|
||||
|
||||
11
phpunit.xml
11
phpunit.xml
@@ -1,5 +1,8 @@
|
||||
<phpunit
|
||||
colors="true"
|
||||
verbose="true"
|
||||
>
|
||||
<?xml version="1.0"?>
|
||||
<phpunit colors="true" cacheDirectory=".phpunit.cache">
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
<directory>test/phpUnitTests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
|
||||
@@ -22,6 +22,9 @@ class DotEnv
|
||||
* 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
|
||||
@@ -56,10 +59,14 @@ class DotEnv
|
||||
$status = 1;
|
||||
$block = false;
|
||||
$var = '';
|
||||
while ($line = fgets($fp)) {
|
||||
$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
|
||||
if (preg_match("/^\s*([\w_.]+)\s*=\s*((\"?).*)/", $line, $matches)) {
|
||||
$var = $matches[1];
|
||||
$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
|
||||
@@ -97,6 +104,9 @@ class DotEnv
|
||||
// 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);
|
||||
|
||||
@@ -5,12 +5,18 @@ 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
|
||||
{
|
||||
/**
|
||||
@@ -48,7 +54,7 @@ final class DotEnvTest extends TestCase
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function envFileProvider(): array
|
||||
public static function envFileProvider(): array
|
||||
{
|
||||
$dot_env_content = [
|
||||
'SOMETHING' => 'A',
|
||||
@@ -60,6 +66,8 @@ final class DotEnvTest extends TestCase
|
||||
'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',
|
||||
@@ -87,6 +95,8 @@ final class DotEnvTest extends TestCase
|
||||
'__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
|
||||
@@ -97,39 +107,39 @@ final class DotEnvTest extends TestCase
|
||||
'default' => [
|
||||
'folder' => null,
|
||||
'file' => null,
|
||||
'status' => 3,
|
||||
'content' => [],
|
||||
'expected_status' => 3,
|
||||
'expected_env' => [],
|
||||
'chmod' => null,
|
||||
],
|
||||
'cannot open file' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'cannot_read.env',
|
||||
'status' => 2,
|
||||
'content' => [],
|
||||
'expected_status' => 2,
|
||||
'expected_env' => [],
|
||||
// 0000
|
||||
'chmod' => '100000',
|
||||
],
|
||||
'empty file' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'empty.env',
|
||||
'status' => 1,
|
||||
'content' => [],
|
||||
'expected_status' => 1,
|
||||
'expected_env' => [],
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override all' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'test.env',
|
||||
'status' => 0,
|
||||
'content' => $dot_env_content,
|
||||
'expected_status' => 0,
|
||||
'expected_env' => $dot_env_content,
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override directory' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => null,
|
||||
'status' => 0,
|
||||
'content' => $dot_env_content,
|
||||
'expected_status' => 0,
|
||||
'expected_env' => $dot_env_content,
|
||||
'chmod' => null,
|
||||
],
|
||||
];
|
||||
@@ -138,10 +148,6 @@ final class DotEnvTest extends TestCase
|
||||
/**
|
||||
* 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
|
||||
@@ -149,6 +155,9 @@ final class DotEnvTest extends TestCase
|
||||
* @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,
|
||||
@@ -189,14 +198,14 @@ final class DotEnvTest extends TestCase
|
||||
$status = \gullevek\dotEnv\DotEnv::readEnvFile();
|
||||
}
|
||||
$this->assertEquals(
|
||||
$status,
|
||||
$expected_status,
|
||||
$status,
|
||||
'Assert returned status equal'
|
||||
);
|
||||
// now assert read data
|
||||
$this->assertEquals(
|
||||
$_ENV,
|
||||
$expected_env,
|
||||
$_ENV,
|
||||
'Assert _ENV correct'
|
||||
);
|
||||
// if we have file and chmod unset
|
||||
|
||||
@@ -10,6 +10,8 @@ HAS_COMMENT_QUOTES_NO_SPACE="Comment at end with quotes no space"# Comment QES
|
||||
HAS_COMMENT_NO_QUOTES_SPACE=Comment at end no quotes and space # Comment NQE
|
||||
HAS_COMMENT_NO_QUOTES_NO_SPACE=Comment at end no quotes no space# Comment NQES
|
||||
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
|
||||
@@ -47,3 +49,10 @@ SUPERLINE=
|
||||
EMPTY=
|
||||
= flase
|
||||
asfasdf
|
||||
# BLOCK TESTS
|
||||
[Var Test]
|
||||
TEST="Block 1 D"
|
||||
[OtherSet]
|
||||
TEST="Block 2 D"
|
||||
[Ignore-Invalid-Block]
|
||||
TEST="Block 3 D"
|
||||
|
||||
@@ -31,4 +31,8 @@ $status = DotEnv::readEnvFile(__DIR__ . DIRECTORY_SEPARATOR . 'env');
|
||||
print "STATUS: " . (string)$status . "<br>";
|
||||
print "ENV: <pre>" . print_r($_ENV, true) . "</pre><br>";
|
||||
|
||||
$status = gullevek\dotenv\DotEnv::readEnvFile(__DIR__ . DIRECTORY_SEPARATOR . 'env');
|
||||
print "STATUS B: " . (string)$status . "<br>";
|
||||
print "ENV B: <pre>" . print_r($_ENV, true) . "</pre><br>";
|
||||
|
||||
// __END__
|
||||
|
||||
2
tmp/.gitignore
vendored
Normal file
2
tmp/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
Reference in New Issue
Block a user