Skip to content

Commit

Permalink
Switch to external config writer library (#102)
Browse files Browse the repository at this point in the history
Uses the https://github.com/wintercms/laravel-config-writer repo to provide configuration modification. The original classes in Storm have been stubbed so that they continue to work as documented.
  • Loading branch information
bennothommo authored Aug 1, 2022
1 parent 71d6e70 commit 87009af
Show file tree
Hide file tree
Showing 8 changed files with 14 additions and 1,049 deletions.
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

0 comments on commit 87009af

Please sign in to comment.