Skip to content

Commit

Permalink
Merge pull request #122 from markdegrootnl/writer
Browse files Browse the repository at this point in the history
Support for writing Config back to a file
  • Loading branch information
filips123 authored Sep 1, 2019
2 parents d30cdc7 + 8384ab2 commit 72bec48
Show file tree
Hide file tree
Showing 19 changed files with 913 additions and 0 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: php
dist: trusty

php:
- 5.5
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@ assert($conf['secret'] == '123');
assert($conf['secret'] == '456');
```

### Saving config

It is possible to save the config back to a file in any of the supported formats
except PHP.

```php
$config = Config::load('config.json');

$ini = $config->toString(new Ini()); // Encode to string if you want to save the file yourself

$config->toFile('config.yaml');
```

### Using with default values

Sometimes in your own projects you may want to use Config for storing
Expand Down
80 changes: 80 additions & 0 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Noodlehaus\Exception\EmptyDirectoryException;
use InvalidArgumentException;
use Noodlehaus\Parser\ParserInterface;
use Noodlehaus\Writer\WriterInterface;

/**
* Configuration reader and writer for PHP.
Expand All @@ -33,6 +34,18 @@ class Config extends AbstractConfig
'Noodlehaus\Parser\Yaml'
];

/**
* All formats supported by Config.
*
* @var array
*/
protected $supportedWriters = [
'Noodlehaus\Writer\Ini',
'Noodlehaus\Writer\Json',
'Noodlehaus\Writer\Xml',
'Noodlehaus\Writer\Yaml'
];

/**
* Static method for loading a Config instance.
*
Expand Down Expand Up @@ -105,6 +118,41 @@ protected function loadFromFile($path, ParserInterface $parser = null)
}
}

/**
* Writes configuration to file.
*
* @param string $filename Filename to save configuration to
* @param WriterInterface $writer Configuration writer
*
* @throws WriteException if the data could not be written to the file
*/
public function toFile($filename, WriterInterface $writer = null)
{
if ($writer === null) {
// Get file information
$info = pathinfo($filename);
$parts = explode('.', $info['basename']);
$extension = array_pop($parts);

// Skip the `dist` extension
if ($extension === 'dist') {
$extension = array_pop($parts);
}

// Get file writer
$writer = $this->getWriter($extension);

// Try to save file
$writer->toFile($this->all(), $filename);

// Clean writer
$writer = null;
} else {
// Try to load file using specified writer
$writer->toFile($this->all(), $filename);
}
}

/**
* Loads configuration from string.
*
Expand All @@ -119,6 +167,17 @@ protected function loadFromString($configuration, ParserInterface $parser)
$this->data = array_replace_recursive($this->data, $parser->parseString($configuration));
}

/**
* Writes configuration to string.
*
* @param WriterInterface $writer Configuration writer
* @param boolean $pretty Encode pretty
*/
public function toString(WriterInterface $writer, $pretty = true)
{
return $writer->toString($this->all(), $pretty);
}

/**
* Gets a parser for a given file extension.
*
Expand All @@ -140,6 +199,27 @@ protected function getParser($extension)
throw new UnsupportedFormatException('Unsupported configuration format');
}

/**
* Gets a writer for a given file extension.
*
* @param string $extension
*
* @return Noodlehaus\Writer\WriterInterface
*
* @throws UnsupportedFormatException If `$extension` is an unsupported file format
*/
protected function getWriter($extension)
{
foreach ($this->supportedWriters as $writer) {
if (in_array($extension, $writer::getSupportedExtensions())) {
return new $writer();
}
}

// If none exist, then throw an exception
throw new UnsupportedFormatException('Unsupported configuration format'.$extension);
}

/**
* Gets an array of paths
*
Expand Down
19 changes: 19 additions & 0 deletions src/Exception/WriteException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Noodlehaus\Exception;

use Noodlehaus\ErrorException;

class WriteException extends ErrorException
{
public function __construct(array $error)
{
$message = isset($error['message']) ? $error['message'] : 'There was an error writing the file';
$code = isset($error['code']) ? $error['code'] : 0;
$severity = isset($error['type']) ? $error['type'] : 1;
$filename = isset($error['file']) ? $error['file'] : __FILE__;
$exception = isset($error['exception']) ? $error['exception'] : null;

parent::__construct($message, $code, $severity, $filename, $exception);
}
}
33 changes: 33 additions & 0 deletions src/Writer/AbstractWriter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Noodlehaus\Writer;

use Noodlehaus\Exception\WriteException;

/**
* Base Writer.
*
* @package Config
* @author Jesus A. Domingo <[email protected]>
* @author Hassan Khan <[email protected]>
* @author Filip Š <[email protected]>
* @author Mark de Groot <[email protected]>
* @link https://github.com/noodlehaus/config
* @license MIT
*/
abstract class AbstractWriter implements WriterInterface
{
/**
* {@inheritdoc}
*/
public function toFile($config, $filename)
{
$contents = $this->toString($config);
$success = @file_put_contents($filename, $contents);
if ($success === false) {
throw new WriteException(['file' => $filename]);
}

return $contents;
}
}
60 changes: 60 additions & 0 deletions src/Writer/Ini.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Noodlehaus\Writer;

/**
* Ini Writer.
*
* @package Config
* @author Jesus A. Domingo <[email protected]>
* @author Hassan Khan <[email protected]>
* @author Filip Š <[email protected]>
* @author Mark de Groot <[email protected]>
* @link https://github.com/noodlehaus/config
* @license MIT
*/
class Ini extends AbstractWriter
{
/**
* {@inheritdoc}
* Writes an array to a Ini string.
*/
public function toString($config, $pretty = true)
{
return $this->toINI($config);
}

/**
* {@inheritdoc}
*/
public static function getSupportedExtensions()
{
return ['ini', 'properties'];
}

/**
* Converts array to INI string.
* @param array $arr Array to be converted
* @param array $parent Parent array
*
* @return string Converted array as INI
*
* @see https://stackoverflow.com/a/17317168/6523409/
*/
protected function toINI(array $arr, array $parent = [])
{
$converted = '';

foreach ($arr as $k => $v) {
if (is_array($v)) {
$sec = array_merge((array) $parent, (array) $k);
$converted .= '['.implode('.', $sec).']'.PHP_EOL;
$converted .= $this->toINI($v, $sec);
} else {
$converted .= $k.'='.$v.PHP_EOL;
}
}

return $converted;
}
}
51 changes: 51 additions & 0 deletions src/Writer/Json.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Noodlehaus\Writer;

use Noodlehaus\Exception\WriteException;

/**
* JSON Writer.
*
* @package Config
* @author Jesus A. Domingo <[email protected]>
* @author Hassan Khan <[email protected]>
* @author Filip Š <[email protected]>
* @author Mark de Groot <[email protected]>
* @link https://github.com/noodlehaus/config
* @license MIT
*/
class Json extends AbstractWriter
{
/**
* {@inheritdoc}
* Writes an array to a JSON file.
*/
public function toFile($config, $filename)
{
$data = $this->toString($config);
$success = @file_put_contents($filename, $data.PHP_EOL);
if ($success === false) {
throw new WriteException(['file' => $filename]);
}

return $data;
}

/**
* {@inheritdoc}
* Writes an array to a JSON string.
*/
public function toString($config, $pretty = true)
{
return json_encode($config, $pretty ? (JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) : 0);
}

/**
* {@inheritdoc}
*/
public static function getSupportedExtensions()
{
return ['json'];
}
}
48 changes: 48 additions & 0 deletions src/Writer/WriterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Noodlehaus\Writer;

use Noodlehaus\Exception\WriteException;

/**
* Config file parser interface.
*
* @package Config
* @author Jesus A. Domingo <[email protected]>
* @author Hassan Khan <[email protected]>
* @author Filip Š <[email protected]>
* @author Mark de Groot <[email protected]>
* @link https://github.com/noodlehaus/config
* @license MIT
*/
interface WriterInterface
{
/**
* Writes a configuration from `$config` to `$filename`.
*
* @param array $config
* @param string $filename
*
* @throws WriteException if the data could not be written to the file
*
* @return array
*/
public function toFile($config, $filename);

/**
* Writes a configuration from `$config` to a string.
*
* @param array $config
* @param bool $pretty
*
* @return array
*/
public function toString($config, $pretty = true);

/**
* Returns an array of allowed file extensions for this writer.
*
* @return array
*/
public static function getSupportedExtensions();
}
Loading

0 comments on commit 72bec48

Please sign in to comment.