Skip to content

Commit

Permalink
Spring updates (#8)
Browse files Browse the repository at this point in the history
* Fixes #7 

* - Adds new ExtendedArguments class for dot.array support
- Adds `StringSerializable` interface and new json/php simple serializers
- Exceptions refactored with static methods for better readability
- Config now loads environment variables from .env file
- adds 2 new functions (snake_to_camel_case and camel_to_snake_case)
- ConfigurationFactory extends Argument interface now

* Updates the license
* Ensure the variable is always array
* Ensure the variable exists before calling unset()
  • Loading branch information
kodeart authored Jun 2, 2018
1 parent 9b6bbfe commit 22e0c31
Show file tree
Hide file tree
Showing 31 changed files with 754 additions and 81 deletions.
30 changes: 20 additions & 10 deletions AccessorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
namespace Koded\Stdlib;

use Koded\Exceptions\ReadOnlyException;
use Koded\Stdlib\Interfaces\Data;
use Traversable;

/**
Expand All @@ -33,12 +32,12 @@ public function & __get($index)

public function __set($index, $value)
{
throw new ReadOnlyException(Data::E_READONLY_INSTANCE, [':class' => get_class($this)]);
throw ReadOnlyException::forInstance($index, get_class($this));
}

public function __clone()
{
throw new ReadOnlyException(Data::E_CLONING_DISALLOWED, [':class' => get_class($this)]);
throw ReadOnlyException::forCloning(get_class($this));
}

public function __isset($index)
Expand All @@ -51,11 +50,6 @@ public function get(string $index, $default = null)
return $this->storage[$index] ?? $default;
}

public function toArray(): array
{
return $this->storage;
}

public function has($index): bool
{
return array_key_exists($index, $this->storage);
Expand All @@ -66,10 +60,26 @@ public function count()
return count($this->storage);
}

public function toArray(): array
{
return $this->storage;
}

/**
* Returns the object state as JSON string.
*
* @param int $options By default these are added:
* - JSON_NUMERIC_CHECK
* - JSON_PRESERVE_ZERO_FRACTION
* - JSON_UNESCAPED_SLASHES
* - JSON_UNESCAPED_UNICODE
*
* @return string
*/
public function toJSON(int $options = 0): string
{
$options |= JSON_NUMERIC_CHECK | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES;
return json_encode($this, $options);
$options |= JSON_NUMERIC_CHECK | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
return json_encode($this->storage, $options);
}

public function getIterator(): Traversable
Expand Down
4 changes: 1 addition & 3 deletions Arguments.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
use Countable;
use IteratorAggregate;
use JsonSerializable;
use Koded\Stdlib\Interfaces\{
Argument, NamespaceDataFilter, TransformsToImmutable
};
use Koded\Stdlib\Interfaces\{ Argument, NamespaceDataFilter, TransformsToImmutable };

/**
* Arguments is a MUTABLE, multi purpose class that encapsulates data.
Expand Down
25 changes: 12 additions & 13 deletions ArrayDataFilterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,41 @@ public function filter(
{
$filtered = [];

foreach ($data as $k => $v) {
if ($trim && '' !== $prefix && 0 === strpos($k, $prefix, 0)) {
$k = str_replace($prefix, '', $k);
foreach ($data as $index => $value) {
if ($trim && '' !== $prefix && 0 === strpos($index, $prefix, 0)) {
$index = str_replace($prefix, '', $index);
}
$filtered[$lowercase ? strtolower($k) : $k] = $v;
$filtered[$lowercase ? strtolower($index) : $index] = $value;
}

return $filtered;
}

public function find(string $index, $default = null)
{
$storage = $this->storage;

if (isset($storage[$index])) {
return $storage[$index];
if (isset($this->storage[$index])) {
return $this->storage[$index];
}

$storage = $this->storage;
foreach (explode('.', $index) as $token) {
if (!is_array($storage) || !array_key_exists($token, $storage)) {
if (false === is_array($storage) || false === array_key_exists($token, $storage)) {
return $default;
}

$storage = $storage[$token];
$storage = &$storage[$token];
}

return $storage;
}

public function extract(array $keys): array
public function extract(array $indexes): array
{
$found = [];
foreach ($keys as $index) {
foreach ($indexes as $index) {
$found[$index] = $this->storage[$index] ?? null;
}

return $found;
}
}
}
44 changes: 28 additions & 16 deletions Config.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);

/*
* This file is part of the Koded package.
Expand All @@ -20,7 +20,7 @@
* from files or other Config instances. There are 2 common patterns
* to populate the config,
*
* either you can fill the Config instance from a config files:
* either you can fill the Config instance from config files:
*
* $app->config()->fromPhpFile('myconfig.php');
* $app->config()->fromJsonFile('myconfig.json');
Expand Down Expand Up @@ -115,36 +115,47 @@ public function fromObject($object): ConfigurationFactory

public function fromJsonFile(string $filename): ConfigurationFactory
{
return $this->loadData(function($filename) {
return $this->loadDataFrom($filename, function($filename) {
/** @noinspection PhpIncludeInspection */
return json_decode(file_get_contents($filename), true);
}, $filename);
});
}

public function fromIniFile(string $filename): ConfigurationFactory
{
return $this->loadData(function($filename) {
return $this->loadDataFrom($filename, function($filename) {
return parse_ini_file($filename, true, INI_SCANNER_TYPED) ?: [];
}, $filename);
});
}

public function fromEnvFile(string $filename, string $namespace = ''): ConfigurationFactory
{
return $this->loadData(function($filename) use ($namespace) {
$data = parse_ini_file($filename, false, INI_SCANNER_TYPED) ?: [];
return $this->loadDataFrom($filename, function($filename) use ($namespace) {
try {
$data = parse_ini_file($filename, false, INI_SCANNER_TYPED) ?: [];
} catch (Exception $e) {
return [];
}

foreach ($data as $key => $value) {
$_ENV[$key] = $value;

if (null !== $value) {
putenv($key . '=' . $value);
}
}

if (empty($namespace)) {
return $data;
}

return $this->filter($data, $namespace);

}, $filename);
});
}

public function fromEnvVariable(string $variable): ConfigurationFactory
{
if (!empty($filename = getenv($variable))) {
if (false === empty($filename = getenv($variable))) {
$extension = ucfirst(pathinfo($filename, PATHINFO_EXTENSION));
return call_user_func([$this, "from{$extension}File"], $filename);
}
Expand All @@ -160,10 +171,10 @@ public function fromEnvVariable(string $variable): ConfigurationFactory

public function fromPhpFile(string $filename): ConfigurationFactory
{
return $this->loadData(function($filename) {
return $this->loadDataFrom($filename, function($filename) {
/** @noinspection PhpIncludeInspection */;
return include $filename;
}, $filename);
});
}

public function fromEnvironment(
Expand All @@ -175,7 +186,8 @@ public function fromEnvironment(
{
$data = [];
foreach ($variableNames as $variable) {
$data[] = $variable . '=' . getenv($variable);
$value = getenv($variable);
$data[] = $variable . '=' . (false === $value ? 'null' : $value);
}

$data = parse_ini_string(join(PHP_EOL, $data), false, INI_SCANNER_TYPED) ?: [];
Expand All @@ -196,10 +208,10 @@ public function namespace(string $prefix, bool $lowercase = true, bool $trim = t
return (new static($this->rootPath))->import($this->filter($this->toArray(), $prefix, $lowercase, $trim));
}

protected function loadData(callable $callable, string $filename): ConfigurationFactory
protected function loadDataFrom(string $filename, callable $loader): ConfigurationFactory
{
$file = ('/' === $filename[0]) ? $filename : $this->rootPath . '/' . ltrim($filename, '/');
$this->import($callable($file));
$this->import($loader($file));

return $this;
}
Expand Down
29 changes: 23 additions & 6 deletions Exceptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,44 @@ class KodedException extends RuntimeException
/**
* @var array A map of exception code => message
*/
protected $messages = [];
protected $messages = [
Data::E_PHP_EXCEPTION => '[Exception] :message',
];

/**
* KodedException constructor.
*
* @param int $code As defined in the child classes
* @param array $arguments [optional]
* @param Exception $previous [optional]
* @param int $code As defined in the child classes
* @param array $arguments [optional]
* @param Exception $previous [optional]
*/
public function __construct(int $code, array $arguments = [], Exception $previous = null)
{
$message = strtr($this->messages[$code] ?? $this->message, $arguments);
parent::__construct($message, $code, $previous);
}

public static function generic(string $message, Exception $previous = null)
{
return new static(Data::E_PHP_EXCEPTION, [':message' => $message], $previous);
}
}

class ReadOnlyException extends KodedException
{

protected $messages = [
Data::E_CLONING_DISALLOWED => 'Cloning the :class instance is not allowed',
Data::E_READONLY_INSTANCE => ':class instance is read-only',
Data::E_READONLY_INSTANCE => 'Cannot set :index. :class instance is read-only',
];
}

public static function forInstance(string $index, string $class)
{
return new static(Data::E_READONLY_INSTANCE, [':index' => $index, ':class' => $class]);
}

public static function forCloning(string $class)
{
return new static(Data::E_CLONING_DISALLOWED, [':class' => $class]);
}
}
Loading

0 comments on commit 22e0c31

Please sign in to comment.