Skip to content

Added process of quotes #3

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

Merged
merged 4 commits into from
Jul 4, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,44 @@
```
APP_ENV=dev
DATABASE_DNS=mysql:host=localhost;dbname=test;
DATABASE_USER=root
DATABASE_USER="root"
DATABASE_PASSWORD=root
MODULE_ENABLED=true
```

**How to use ?**
**Load the variables**

```php
<?php
use DevCoder\DotEnv;

(new DotEnv(__DIR__ . '/.env'))->load();
$absolutePathToEnvFile = __DIR__ . '/.env';

echo getenv('APP_ENV');
// dev
echo getenv('DATABASE_DNS');
// mysql:host=localhost;dbname=test;
(new DotEnv($absolutePathToEnvFile))->load();
```

**Use them!**
```php
/**
* string(33) "mysql:host=localhost;dbname=test;"
*/
var_dump(getenv('DATABASE_DNS'));

/**
* Removes double and single quotes from the variable:
*
* string(4) "root"
*/
var_dump(getenv('DATABASE_USER'));

/**
* Processes booleans as such:
*
* bool(true)
*/
var_dump(getenv('MODULE_ENABLED'));
```

Ideal for small project
Simple and easy!

Simple and easy!
63 changes: 42 additions & 21 deletions src/DotEnv.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,6 @@

class DotEnv
{
/**
* Convert true and false to booleans, instead of:
*
* VARIABLE=false -> ['VARIABLE' => 'false']
*
* it will be
*
* VARIABLE=false -> ['VARIABLE' => false]
*
* default = true
*/
const PROCESS_BOOLEANS = 'PROCESS_BOOLEANS';

/**
* The directory where the .env file can be located.
*
Expand All @@ -31,6 +18,13 @@ class DotEnv
*/
protected $options = [];

/**
* Process strings to obtain characteristics of it
*
* @var Processor
*/
protected $processor;

public function __construct(string $path, array $options = [])
{
if (!file_exists($path)) {
Expand All @@ -40,12 +34,15 @@ public function __construct(string $path, array $options = [])
$this->path = $path;

$this->processOptions($options);

$this->processor = new Processor();
}

private function processOptions(array $options) : void
{
$this->options = array_merge([
static::PROCESS_BOOLEANS => true
Option::PROCESS_BOOLEANS => true,
Option::PROCESS_QUOTES => true
], $options);
}

Expand Down Expand Up @@ -78,16 +75,40 @@ public function load() : void
}
}

private function processValue(string $value) {
$trimmedValue = trim($value);

if (!empty($this->options[static::PROCESS_BOOLEANS])) {
$loweredValue = strtolower($trimmedValue);
private function processValue(string $value)
{
/**
* First trim spaces and quotes if configured
*/
$preprocessedValue = $this->preprocessValue($value);

$isBoolean = in_array($loweredValue, ['true', 'false'], true);
/**
* If the value is a boolean resolve it as such
*/
if (!empty($this->options[Option::PROCESS_BOOLEANS])) {
$isBoolean = $this->processor->isBoolean($preprocessedValue);

if ($isBoolean) {
return $loweredValue === 'true';
return $this->processor->resolveAsBoolean($preprocessedValue);
}
}

/**
* Does not match any processor options, return as is
*/
return $preprocessedValue;
}

private function preprocessValue(string $value) : string
{
$trimmedValue = trim($value);

if (!empty($this->options[Option::PROCESS_QUOTES])) {
$wrappedBySingleQuotes = $this->processor->isWrappedByChar($trimmedValue, '\'');
$wrappedByDoubleQuotes = $this->processor->isWrappedByChar($trimmedValue, '"');

if ($wrappedBySingleQuotes || $wrappedByDoubleQuotes) {
return $this->processor->removeFirstAndLastChar($trimmedValue);
}
}

Expand Down
32 changes: 32 additions & 0 deletions src/Option.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace DevCoder;

class Option
{
/**
* Convert true and false to booleans, instead of:
*
* VARIABLE=false -> ['VARIABLE' => 'false']
*
* it will be
*
* VARIABLE=false -> ['VARIABLE' => false]
*
* default = true
*/
const PROCESS_BOOLEANS = 'PROCESS_BOOLEANS';

/**
* Remove double and single quotes at the start and end of the variables, instead of:
*
* VARIABLE="This is a "sample" value" -> ['VARIABLE' => '"This is a "sample" value"']
*
* it will be
*
* VARIABLE="This is a "sample" value" -> ['VARIABLE' => 'This is a "sample" value']
*
* default = true
*/
const PROCESS_QUOTES = 'PROCESS_QUOTES';
}
32 changes: 32 additions & 0 deletions src/Processor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace DevCoder;

class Processor
{
public function resolveAsBoolean(string $boolean) : bool
{
return strtolower($boolean) === 'true';
}

public function isBoolean(string $value) : bool
{
$loweredValue = strtolower($value);

return in_array($loweredValue, ['true', 'false'], true);
}

public function isWrappedByChar(string $value, string $char) : bool
{
return $value[0] === $char && $value[-1] === $char;
}

public function removeFirstAndLastChar(string $value) : string
{
/**
* Since this function is used for the quote removal
* we don't need mb_substr
*/
return substr($value, 1, -1);
}
}
45 changes: 41 additions & 4 deletions tests/DotenvTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Test\DevCoder;

use DevCoder\DotEnv;
use DevCoder\Option;
use PHPUnit\Framework\TestCase;

class DotenvTest extends TestCase
Expand Down Expand Up @@ -50,19 +51,19 @@ public function testFileNotExist() {
public function testProcessBoolean()
{
(new DotEnv($this->env('.env.boolean'), [
DotEnv::PROCESS_BOOLEANS => true
Option::PROCESS_BOOLEANS => true
]))->load();

$this->assertEquals(false, $_ENV['FALSE1']);
$this->assertEquals(false, $_ENV['FALSE2']);
$this->assertEquals(false, $_ENV['FALSE3']);
$this->assertEquals("'false'", $_ENV['FALSE4']);
$this->assertEquals(false, $_ENV['FALSE4']);
$this->assertEquals('0', $_ENV['FALSE5']);

$this->assertEquals(true, $_ENV['TRUE1']);
$this->assertEquals(true, $_ENV['TRUE2']);
$this->assertEquals(true, $_ENV['TRUE3']);
$this->assertEquals("'true'", $_ENV['TRUE4']);
$this->assertEquals(true, $_ENV['TRUE4']);
$this->assertEquals('1', $_ENV['TRUE5']);
}

Expand All @@ -72,11 +73,47 @@ public function testProcessBoolean()
public function testDontProcessBoolean()
{
(new DotEnv($this->env('.env.boolean'), [
DotEnv::PROCESS_BOOLEANS => false
Option::PROCESS_BOOLEANS => false
]))->load();

$this->assertEquals('false', $_ENV['FALSE1']);

$this->assertEquals('true', $_ENV['TRUE1']);
}

/**
* @runInSeparateProcess
*/
public function testProcessQuotes()
{
(new DotEnv($this->env('.env.quotes'), [
Option::PROCESS_QUOTES => true
]))->load();

$this->assertEquals('q1', $_ENV['QUOTED1']);
$this->assertEquals('q2', $_ENV['QUOTED2']);
$this->assertEquals('"q3"', $_ENV['QUOTED3']);
$this->assertEquals('This is a "sample" value', $_ENV['QUOTED4']);
$this->assertEquals('\"This is a "sample" value\"', $_ENV['QUOTED5']);
$this->assertEquals('"q6', $_ENV['QUOTED6']);
$this->assertEquals('q7"', $_ENV['QUOTED7']);
}

/**
* @runInSeparateProcess
*/
public function testDontProcessQuotes()
{
(new DotEnv($this->env('.env.quotes'), [
Option::PROCESS_QUOTES => false
]))->load();

$this->assertEquals('"q1"', $_ENV['QUOTED1']);
$this->assertEquals('\'q2\'', $_ENV['QUOTED2']);
$this->assertEquals('""q3""', $_ENV['QUOTED3']);
$this->assertEquals('"This is a "sample" value"', $_ENV['QUOTED4']);
$this->assertEquals('\"This is a "sample" value\"', $_ENV['QUOTED5']);
$this->assertEquals('"q6', $_ENV['QUOTED6']);
$this->assertEquals('q7"', $_ENV['QUOTED7']);
}
}
7 changes: 7 additions & 0 deletions tests/env/.env.quotes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
QUOTED1="q1"
QUOTED2='q2'
QUOTED3=""q3""
QUOTED4="This is a "sample" value"
QUOTED5=\"This is a "sample" value\"
QUOTED6="q6
QUOTED7=q7"