Настройки для PHP-скриптов
<?php
/**
* unicode без BOM / (0xef, 0xbb, 0xbf) / chr(239), chr(187), chr(191)
*
* @version 2.7.20
* @todo Оболочка для конфигурационных массивов
* @example $object = new Config( ['param' => [ 'var' => 1 ] ] );
* @example echo $object->param->var;
*
* @uses ArrayAccess
* @uses ArrayIterator
* @uses array_unshift
* @uses array_keys
* @uses array_values
* @uses array_reverse
* @uses array_flip
* @uses array_search
* @uses array_unique
* @uses in_array
* @uses function_exists
* @uses call_user_func
* @uses serialize
* @uses implode
*
* @magic __construct
* @magic __call
* @magic __toString
* @magic __isset
* @magic __unset
* @magic __get
* @magic __set
*************************************************************************************************/
final class Config implements ArrayAccess {
/**
* @access protected
* @const array
*/
protected const _EMPTY_VALUES =
[
NULL, FALSE, ' ', '', ' ', ' ', [], [' '], [''], [' '], [' ']
];
/**
* @access protected
* @const array
*/
protected const _NO_CHANGE_KEYS =
[
'connection',
'password',
'token'
];
/**
* @access protected
* @var integer
*/
protected static int $_count = -1;
/**
* @access protected
* @var integer
*/
protected static float $_time = 0;
/**
* Singleton
*
* @final
* @static
* @access public
* @param array $array
* @return object singleton
*/
final public static function instance(array $array = []): self
{
/**
* @staticvar object singleton
*/
static $_;
if ( ! $_)
{
if (_DEBUG)
{
static::$_time = microtime(TRUE);
}
$_ = new static($array);
}
return $_;
}
/**
* Singleton
*
* @final
* @static
* @access public
* @param array $array
* @return object singleton
*/
final public static function factory(array $array = []) /** singleton **/
{
return static::instance($array);
}
/**
* @access private
* @var array
*/
private array $_ = [];
/**
* @access private
* @var array
*/
private array $_keys = [];
/**
* __construct
*
* @final
* @access public
* @param array|object Config $input
* @param array $keys_object
* @return no type
*/
final public function __construct($input = [], array $keys_object = []) /** no type **/
{
static::$_count++;
if ($input instanceof self)
$this->_in_object($input, $keys_object);
else
$this->
}
/**
* __clone
*
* @final
* @access private
*/
final private function __clone() { }
/**
* __call
*
* $keys = $object->array->name->keys(); or if ($object->name->keys('str')) { ... }
* $flip = $object->array->name->flip();
* $values = $object->array->name->values(); or if ($object->name->values('str')) { ... }
* $reverse = $object->array->name->reverse()->as_array();
* $array = $object->array->names->values()->flip('array');
*
* @final
* @access public
* @return mixed
*/
final public function __call($method, $args) /** mixed **/
{
if (in_array($method, ['keys', 'values', 'reverse', 'flip']) && function_exists('array_' .$method))
{
$array = call_user_func('array_' .$method, $this->as_array());
if (isset($args[0]))
{
if ($args[0] === 'array')
return $array;
elseif ($method === 'keys' || $method === 'values')
{
return in_array($args[0], $array);
}
}
return new self($array);
}
}
/**
* __toString
*
* echo $object;
*
* @access public
* @return string
*/
public function __toString(): string
{
return serialize($this->_);
}
/**
* foreach ($object->getIterator() as $key => $value) { ... }
*
* @access public
* @return Traversable
*/
public function getIterator(): Traversable
{
return new ArrayIterator($this->_);
}
/**
* $array = $object->getArrayCopy();
*
* @access public
* @return iterable
*/
public function getArrayCopy(): iterable
{
return (array) $this->_;
}
/**
* __isset
*
* if (isset($object->key)) { ... }
*
* @access public
* @param string $key
* @return boolean
*/
public function __isset($key): bool
{
return isset($this->_[$key]);
}
/**
* __unset
*
* unset($object->key);
*
* @access public
* @param string $key
* @return void
*/
public function __unset($key = NULL): void
{
if ($key === NULL)
$this->_unset();
else
{
unset($this->_[$key]);
if (($key = array_search($key, $this->_keys)) !== FALSE)
{
unset($this->_keys[$key]); // unset key
}
}
}
/**
* __set
*
* $object->key1->key2->key3-> ... = 'set value';
*
* @access public
* @param string $key
* @param mixed $value
* @return void
*/
public function __set($key = NULL, $value = NULL): void
{
if (isset($this->_[$key]) && in_array($key, self::_NO_CHANGE_KEYS))
{ /** return void; **/ }
else
{
if ($key === NULL)
$this->_[] = $value;
else
{
$this->_[$key] = $value;
}
$this->_to_object($this->_);
}
}
/**
* __get
*
* $object->key1->key2->key3-> ...
*
* @access public
* @param string $key
* @return mixed
*/
public function & __get($key) /** mixed **/
{
if (($_ = ($this->_[$key] ?? NULL)) instanceof self)
{
$_ = ( ! in_array($key, $this->_keys) && in_array($_->as_array(), self::_EMPTY_VALUES, TRUE)
? $_->result($key)
: $_);
}
return $_;
}
/**
* [!] ArrayAccess
* @link https://www.php.net/manual/en/class.arrayaccess.php
*
* @access public
* @param string $key
* @return boolean
*/
public function offsetExists($key): bool
{
return $this->__isset($key);
}
/**
* [!] ArrayAccess
* @link https://www.php.net/manual/en/class.arrayaccess.php
*
* @access public
* @param string $key
* @return void
*/
public function offsetUnset($key): void
{
$this->__unset($key);
}
/**
* [!] ArrayAccess
* @link https://www.php.net/manual/en/class.arrayaccess.php
*
* @access public
* @param string $key
* @param mixed $value
* @return void
*/
public function offsetSet($key = NULL, $value = NULL): void
{
$this->__set($key, $value);
}
/**
* [!] ArrayAccess
* @link https://www.php.net/manual/en/class.arrayaccess.php
*
* @access public
* @param string $key
* @return mixed
*/
public function & offsetGet($key) /** mixed **/
{
return $this->__get($key);
}
/**
* DEBUG COUNT
*
* @final
* @access public
* @return integer
*/
final public function count(): int
{
return static::$_count;
}
/**
* DEBUG TIME
*
* @final
* @access public
* @return integer
*/
final public function time(): float
{
return static::$_time;
}
/**
* $object->key->empty();
* $object->key->empty('keyname');
*
* @access public
* @return mixed
*/
public function empty($key = NULL, $unset = FALSE) /** mixed **/
{
$result = $this->result($key, $unset);
if ($result instanceof self)
{
$result = $result->getArrayCopy();
}
return (empty($result) ? NULL : $result);
}
/**
* $object->key->result('key', TRUE); - unset($object->key) and return value;
* $object->key->result('key'); or $object->key->result();
*
* @access public
* @param string $key
* @param boolean $unset
* @return mixed
*/
public function & result($key = NULL, $unset = FALSE) /** mixed **/
{
if (empty($key))
{
$result = new self($this->_);
! $unset || $this->__unset();
}
elseif (($result = $this->__get($key)) && $unset)
{
$this->__unset($key);
}
return $result;
}
/**
* $object->key->last();
*
* @access public
* @return mixed
*/
public function & last() /** mixed **/
{
return $this->__get(key(array_slice($this->_, -1)));
}
/**
* echo $object->key->implode(',');
*
* @access public
* @param string $delimiter
* @return string
*/
public function implode(string $delimiter = '|'): string
{
return implode($delimiter, $this->_);
}
/**
* $object->key->unshift(['key' => 'value']);
*
* @access public
* @param mixed $mixed
* @return self
*/
public function unshift($mixed): self
{
$array = $this->as_array();
array_unshift($array, $mixed);
$this->_to_object(array_unique($array));
return $this;
}
/**
* $object->array->map('trim');
* $object->array->map(function($_){ return TRUE;})->as_array();
*
* @access public
* @param mixed $callbacks
* @param iterable $iterable
* @return self
*/
public function map($callbacks, iterable $iterable = NULL): self
{
if ($iterable === NULL)
{
$iterable = $this->_;
}
foreach ($iterable as $key => $_)
{
$iterable[$key] =
(
is_iterable($_)
? $this->map($callbacks, $iterable[$key])
: call_user_func($callbacks, $iterable[$key])
);
}
return new self($iterable);
}
/**
* $array1 <<<-- $array2
*
* $object->key->merge(['key' => 'value']);
*
* $object->key->key2 = ['keyname' => TRUE];
* $object->key->merge('key2');
* return $object->key->keyname .... a key2 unsete
*
* @access public
* @param array|string $input
* @return self
*/
public function merge($input = []): self
{
if (is_string($input) && isset($this->_[$input]) && ($this->_[$input] instanceof self))
{
$key = $input;
$input = $this->_[$input]->as_array();
unset($this->_[$key]);
}
$this->_to_object
(
$this->_merge
(
($this->_ instanceof self)
? $this->_->as_array()
: $this->_,
$input instanceof self
? $input->as_array()
: (array) $input
)
);
return $this;
}
/**
* $array1 -->>> $array2
*
* $object->key->merge_revers(['key' => 'value']);
*
* @access public
* @param array $array
* @return self
*/
public function merge_revers(array $array = []): self
{
$this->_to_object
(
$this->_merge
(
$array,
($this->_ instanceof self)
? $this->_->as_array()
: $this->_
)
);
return $this;
}
/**
* $object->key->load(['/path/config/array.php', '/path/array.php']);
* $object->key2->load('/path/config/array2.php');
*
* @access public
* @param array|string $paths
* @return self
*/
public function load($paths = NULL): self
{
if ( ! empty($paths))
{
$array = $this->as_array();
foreach ((array) $paths as $_)
{
$array = $this->_merge($array, (array) require $_);
}
$this->_to_object($array);
}
return $this;
}
/**
* $object->key->load_revers(['/path/config/array.php', '/path/array.php']);
* $object->key->load_revers('/path/config/array.php');
*
* @access public
* @param array|string $paths
* @return self
*/
public function load_revers($paths = NULL): self
{
if ( ! empty($paths))
{
$array = $this->as_array();
foreach ((array) $paths as $_)
{
$array = $this->_merge((array) require $_, $array);
}
$this->_to_object($array);
}
return $this;
}
/**
* $object->as_array()
* $object->key->as_array()
* $object->key->as_array(TRUE) or $object->key->as_array('UNSET')
*
* @final
* @access public
* @param boolean $unset
* @return array
*/
final public function & as_array($unset = FALSE): array
{
$array = [];
foreach ($this->_ as $key => $_)
{
$array[$key] = ($_ instanceof self)
? $_->as_array()
: $_;
}
! $unset || $this->__unset();
return $array;
}
/**
* $object->as_keys()
* $object->key->as_keys()
*
* @final
* @access public
* @return array
*/
final public function as_keys(): array
{
return $this->_keys;
}
/**
* if ($object->key->is_key('keyname')) { ... }
*
* @final
* @access public
* @param string $key
* @return boolean
*/
final public function is_key(string $key = NULL): bool
{
return in_array($key, $this->_keys);
}
/**
* $object->default('keyname', 'typename', ['keydefault' => 'value']);
* $object->keyname->as_array();
*
* @final
* @access public
* @param string $key
* @param string $type
* @param array $default
* @return self
*/
final public function default($key = NULL, $type = NULL, array $default = []): self
{
if ( ! isset($this->_[$key]))
{
$this->_[$key] = new self;
}
$this->_[$key] = new self
(
($type && $this->_[$key]->{$type})
? $this->_merge($default, $this->_[$key]->{$type}->as_array())
: $default
);
return $this;
}
/**
* $array1 <<<-- $array2
*
* @final
* @access protected
* @param array $array1
* @param array $array2
* @return array
*/
final protected function _merge(array $array1, array $array2): array
{
if (array_keys(($_ = array_keys($array2))) !== $_) // is_assoc
{
foreach ($array2 as $key => $_)
$array1[$key] = (is_array($_) && isset($array1[$key]) && is_array($array1[$key]))
? $this->_merge($array1[$key], $_)
: $_;
}
else
{
foreach ($array2 as $_)
{
if ( ! in_array($_, $array1, TRUE))
$array1[] = $_;
}
}
return $array1;
}
/**
* @final
* @access protected
* @param iterable $iterable
* @return void
*/
final protected function _to_object(iterable $iterable): void
{
foreach ($iterable as $key => $_)
{
$this->_[$key] = (is_array($_)
? new self($_)
: $_);
if ( ! in_array($key, $this->_keys))
{
$this->_keys[] = $key; // save keys
}
}
}
/**
* @final
* @access protected
* @param object Config $input
* @param array $keys_object
* @return void
*/
final protected function _in_object(Config $input, array $keys_object): void
{
$input = $input->as_array();
foreach ($input as $key => $_)
{
$this->_[$key] = ( ! in_array($key, $keys_object)
? $_
: (is_array($_)
? new self($_)
: $_));
}
}
/**
* @final
* @access protected
* @return void
*/
final protected function _unset(): void
{
$this->_ =
$this->_keys = [];
}
}
// End