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

Switch to external config writer library #102

Merged
merged 1 commit into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
"symfony/yaml": "^6.0",
"twig/twig": "~3.0",
"wikimedia/less.php": "~3.0",
"wikimedia/minify": "~2.2"
"wikimedia/minify": "~2.2",
"winter/laravel-config-writer": "^1.0.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.8",
Expand Down
2 changes: 0 additions & 2 deletions src/Config/ConfigWriter.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?php namespace Winter\Storm\Config;

use Exception;

use PhpParser\Error;
use PhpParser\Lexer\Emulative;
use PhpParser\ParserFactory;
Expand Down
240 changes: 3 additions & 237 deletions src/Parse/EnvFile.php
Original file line number Diff line number Diff line change
@@ -1,241 +1,7 @@
<?php namespace Winter\Storm\Parse;
<?php namespace Winter\Storm\Parse;

use Winter\Storm\Support\Str;
use Winter\Storm\Parse\Contracts\DataFileInterface;
use Winter\LaravelConfig\EnvFile as BaseEnvFile;

/**
* Class EnvFile
*/
class EnvFile implements DataFileInterface
class EnvFile extends BaseEnvFile
{
/**
* Lines of env data
*/
protected array $env = [];

/**
* Map of variable names to line indexes
*/
protected array $map = [];

/**
* Filepath currently being worked on
*/
protected ?string $filePath = null;

/**
* EnvFile constructor
*/
final public function __construct(string $filePath)
{
$this->filePath = $filePath;

list($this->env, $this->map) = $this->parse($filePath);
}

/**
* Return a new instance of `EnvFile` ready for modification of the file.
*/
public static function open(?string $filePath = null): static
{
if (!$filePath) {
$filePath = base_path('.env');
}

return new static($filePath);
}

/**
* Set a property within the env. Passing an array as param 1 is also supported.
*
* ```php
* $env->set('APP_PROPERTY', 'example');
* // or
* $env->set([
* 'APP_PROPERTY' => 'example',
* 'DIF_PROPERTY' => 'example'
* ]);
* ```
*/
public function set(array|string $key, $value = null): static
{
if (is_array($key)) {
foreach ($key as $item => $value) {
$this->set($item, $value);
}
return $this;
}

if (!isset($this->map[$key])) {
$this->env[] = [
'type' => 'var',
'key' => $key,
'value' => $value
];

$this->map[$key] = count($this->env) - 1;

return $this;
}

$this->env[$this->map[$key]]['value'] = $value;

return $this;
}

/**
* Push a newline onto the end of the env file
*/
public function addEmptyLine(): EnvFile
{
$this->env[] = [
'type' => 'nl'
];

return $this;
}

/**
* Write the current env lines to a fileh
*/
public function write(string $filePath = null): void
{
if (!$filePath) {
$filePath = $this->filePath;
}

file_put_contents($filePath, $this->render());
}

/**
* Get the env lines data as a string
*/
public function render(): string
{
$out = '';
foreach ($this->env as $env) {
switch ($env['type']) {
case 'comment':
$out .= $env['value'];
break;
case 'var':
$out .= $env['key'] . '=' . $this->escapeValue($env['value']);
break;
}

$out .= PHP_EOL;
}

return $out;
}

/**
* Wrap a value in quotes if needed
*
* @param mixed $value
*/
protected function escapeValue($value): string
{
if (is_numeric($value)) {
return $value;
}

if ($value === true) {
return 'true';
}

if ($value === false) {
return 'false';
}

if ($value === null) {
return 'null';
}

switch ($value) {
case 'true':
case 'false':
case 'null':
return $value;
default:
// addslashes() wont work as it'll escape single quotes and they will be read literally
return '"' . Str::replace('"', '\"', $value) . '"';
}
}

/**
* Parse a .env file, returns an array of the env file data and a key => position map
*/
protected function parse(string $filePath): array
{
if (!is_file($filePath)) {
return [[], []];
}

$contents = file($filePath);
if (empty($contents)) {
return [[], []];
}

$env = [];
$map = [];

foreach ($contents as $line) {
$type = !($line = trim($line))
? 'nl'
: (
Str::startsWith($line, '#')
? 'comment'
: 'var'
);

$entry = [
'type' => $type
];

if ($type === 'var') {
if (strpos($line, '=') === false) {
// if we cannot split the string, handle it the same as a comment
// i.e. inject it back into the file as is
$entry['type'] = $type = 'comment';
} else {
list($key, $value) = explode('=', $line);
$entry['key'] = trim($key);
$entry['value'] = trim($value, '"');
}
}

if ($type === 'comment') {
$entry['value'] = $line;
}

$env[] = $entry;
}

foreach ($env as $index => $item) {
if ($item['type'] !== 'var') {
continue;
}
$map[$item['key']] = $index;
}

return [$env, $map];
}

/**
* Get the variables from the current env lines data as an associative array
*/
public function getVariables(): array
{
$env = [];

foreach ($this->env as $item) {
if ($item['type'] !== 'var') {
continue;
}
$env[$item['key']] = $item['value'];
}

return $env;
}
}
Loading