Files
kimai/src/Configuration/StringAccessibleConfigTrait.php

213 lines
4.7 KiB
PHP

<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Configuration;
use App\Entity\Configuration;
/**
* @internal do NOT use this trait, but access your configs via SystemConfiguration
*/
trait StringAccessibleConfigTrait
{
/**
* @var array
*/
protected $settings;
/**
* @var array
*/
protected $original;
/**
* @var ConfigLoaderInterface
*/
protected $repository;
/**
* @var bool
*/
protected $initialized = false;
public function __construct(ConfigLoaderInterface $repository, array $settings)
{
$this->repository = $repository;
$this->original = $this->settings = $settings;
}
/**
* @param ConfigLoaderInterface $repository
* @return Configuration[]
*/
protected function getConfigurations(ConfigLoaderInterface $repository): array
{
return $repository->getConfiguration($this->getPrefix());
}
protected function prepare()
{
if ($this->initialized) {
return;
}
foreach ($this->getConfigurations($this->repository) as $configuration) {
$this->set($configuration->getName(), $configuration->getValue());
}
$this->initialized = true;
}
/**
* @return string
*/
abstract protected function getPrefix(): string;
/**
* @param string $key
* @return mixed
*/
public function default(string $key)
{
$key = $this->prepareSearchKey($key);
return $this->get($key, $this->original);
}
/**
* @param string $key
* @return string|int|bool|float|null|array
*/
public function find(string $key)
{
$this->prepare();
$key = $this->prepareSearchKey($key);
return $this->get($key, $this->settings);
}
private function prepareSearchKey(string $key): string
{
$prefix = $this->getPrefix() . '.';
$length = \strlen($prefix);
if (substr($key, 0, $length) === $prefix) {
$key = substr($key, $length);
}
return $key;
}
/**
* @param string $key
* @param array $config
* @return mixed
*/
private function get(string $key, array $config)
{
$keys = explode('.', $key);
$search = array_shift($keys);
if (!\array_key_exists($search, $config)) {
return null;
}
if (\is_array($config[$search]) && !empty($keys)) {
return $this->get(implode('.', $keys), $config[$search]);
}
return $config[$search];
}
public function has(string $key): bool
{
$this->prepare();
$key = $this->prepareSearchKey($key);
$keys = explode('.', $key);
$search = array_shift($keys);
if (!\array_key_exists($search, $this->settings)) {
return false;
}
return true;
}
public function offsetExists($offset): bool
{
return $this->has($offset);
}
/**
* @param $offset
* @return array|bool|float|int|string|null
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
return $this->find($offset);
}
/**
* @param mixed $offset
* @param mixed $value
* @throws \BadMethodCallException
*/
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}
/**
* @param mixed $offset
* @throws \BadMethodCallException
*/
public function offsetUnset($offset)
{
throw new \BadMethodCallException('SystemBundleConfiguration does not support offsetUnset()');
}
/**
* Set an array item to a given value using "dot" notation.
*
* If no key is given to the method, the entire array will be replaced.
*
* @see https://github.com/divineomega/array_undot
* @param string $key
* @param mixed $value
*
* @return array
*/
private function set(string $key, $value): array
{
$array = &$this->settings;
$keys = explode('.', $key);
while (\count($keys) > 1) {
$key = array_shift($keys);
if (!isset($array[$key]) || !\is_array($array[$key])) {
$array[$key] = [];
}
$array = &$array[$key];
}
$k = array_shift($keys);
if (\array_key_exists($k, $array)) {
if (\is_bool($array[$k])) {
$value = (bool) $value;
} elseif (\is_int($array[$k])) {
$value = (int) $value;
}
}
$array[$k] = $value;
return $array;
}
}