|
|
@ -5,13 +5,18 @@ namespace jrosset\EnvReader;
|
|
|
|
use DateTime;
|
|
|
|
use DateTime;
|
|
|
|
use DateTimeInterface;
|
|
|
|
use DateTimeInterface;
|
|
|
|
use Exception;
|
|
|
|
use Exception;
|
|
|
|
|
|
|
|
use InvalidArgumentException;
|
|
|
|
use jrosset\Collections\IArrayCast;
|
|
|
|
use jrosset\Collections\IArrayCast;
|
|
|
|
use jrosset\Collections\InsensitiveCaseKeyCollection;
|
|
|
|
use jrosset\Collections\InsensitiveCaseKeyCollection;
|
|
|
|
use jrosset\Collections\InsensitiveCaseKeyImmutableCollection;
|
|
|
|
use jrosset\Collections\InsensitiveCaseKeyImmutableCollection;
|
|
|
|
use jrosset\Singleton\ISingleton;
|
|
|
|
use jrosset\Singleton\ISingleton;
|
|
|
|
use jrosset\Singleton\TSingleton;
|
|
|
|
use jrosset\Singleton\TSingleton;
|
|
|
|
use RangeException;
|
|
|
|
use RangeException;
|
|
|
|
|
|
|
|
use ReflectionEnum;
|
|
|
|
|
|
|
|
use ReflectionEnumBackedCase;
|
|
|
|
|
|
|
|
use ReflectionException;
|
|
|
|
use UnexpectedValueException;
|
|
|
|
use UnexpectedValueException;
|
|
|
|
|
|
|
|
use UnitEnum;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* A generic configuration class
|
|
|
|
* A generic configuration class
|
|
|
@ -40,10 +45,8 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
* Initial properties
|
|
|
|
* Initial properties
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return string[]|IArrayCast Initial properties
|
|
|
|
* @return string[]|IArrayCast Initial properties
|
|
|
|
*
|
|
|
|
|
|
|
|
* @noinspection PhpReturnDocTypeMismatchInspection
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected function initialProperties () {
|
|
|
|
protected function initialProperties (): array|IArrayCast {
|
|
|
|
return [];
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -77,14 +80,14 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
* Get a property value
|
|
|
|
* Get a property value
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param mixed $default The default value if property is not set
|
|
|
|
* @param mixed|null $default The default value if property is not set
|
|
|
|
* Raise an exception if property is not set AND $default is Null
|
|
|
|
* <br>Raise an exception if property is not set AND $default is Null
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return mixed The property value
|
|
|
|
* @return mixed The property value
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @throws UnexpectedValueException If property is not set AND $default is Null
|
|
|
|
* @throws UnexpectedValueException If property is not set AND $default is Null
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public function getProperty (string $name, $default = null) {
|
|
|
|
public function getProperty (string $name, mixed $default = null): mixed {
|
|
|
|
if (!$this->hasProperty($name)) {
|
|
|
|
if (!$this->hasProperty($name)) {
|
|
|
|
if ($default === null) {
|
|
|
|
if ($default === null) {
|
|
|
|
throw new UnexpectedValueException('The "' . $name . '" property is not set');
|
|
|
|
throw new UnexpectedValueException('The "' . $name . '" property is not set');
|
|
|
@ -100,7 +103,7 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param string|null $default The default value if property is not set
|
|
|
|
* @param string|null $default The default value if property is not set
|
|
|
|
* Raise an exception if property is not set AND $default is Null
|
|
|
|
* <br>Raise an exception if property is not set AND $default is Null
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return string The property value
|
|
|
|
* @return string The property value
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -122,7 +125,7 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param bool|null $default The default value if property is not set
|
|
|
|
* @param bool|null $default The default value if property is not set
|
|
|
|
* Raise an exception if property is not set AND $default is Null
|
|
|
|
* <br>Raise an exception if property is not set AND $default is Null
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return bool The property value
|
|
|
|
* @return bool The property value
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -132,25 +135,18 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
* @noinspection PhpUnused
|
|
|
|
* @noinspection PhpUnused
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public function getPropertyAsBool (string $name, ?bool $default = null): bool {
|
|
|
|
public function getPropertyAsBool (string $name, ?bool $default = null): bool {
|
|
|
|
switch ($value = $this->getProperty($name, $default === null ? null : ($default === true ? '1' : '0'))) {
|
|
|
|
return match ($value = $this->getProperty($name, $default === null ? null : ($default === true ? '1' : '0'))) {
|
|
|
|
case '1':
|
|
|
|
'1', 'true' => true,
|
|
|
|
case 'true':
|
|
|
|
'0', 'false' => false,
|
|
|
|
return true;
|
|
|
|
default => throw new RangeException('The "' . $name . '" property is not a valid boolean : ' . $value),
|
|
|
|
|
|
|
|
};
|
|
|
|
case '0':
|
|
|
|
|
|
|
|
case 'false':
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
throw new RangeException('The "' . $name . '" property is not a valid boolean : ' . $value);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Get a property value as an integer
|
|
|
|
* Get a property value as an integer
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param int|null $default The default value if property is not set
|
|
|
|
* @param int|null $default The default value if property is not set
|
|
|
|
* Raise an exception if property is not set AND $default is Null
|
|
|
|
* <br>Raise an exception if property is not set AND $default is Null
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return int The property value
|
|
|
|
* @return int The property value
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -171,7 +167,7 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param float|null $default The default value if property is not set
|
|
|
|
* @param float|null $default The default value if property is not set
|
|
|
|
* Raise an exception if property is not set AND $default is Null
|
|
|
|
* <br>Raise an exception if property is not set AND $default is Null
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return float The property value
|
|
|
|
* @return float The property value
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -194,7 +190,7 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param string $name The property name
|
|
|
|
* @param DateTime|null $default The default value if property is not set
|
|
|
|
* @param DateTime|null $default The default value if property is not set
|
|
|
|
* Raise an exception if property is not set AND $default is Null
|
|
|
|
* <br>Raise an exception if property is not set AND $default is Null
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return DateTime The property value
|
|
|
|
* @return DateTime The property value
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -206,7 +202,7 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
public function getPropertyAsDateTime (string $name, ?DateTime $default = null): DateTime {
|
|
|
|
public function getPropertyAsDateTime (string $name, ?DateTime $default = null): DateTime {
|
|
|
|
$value = DateTime::createFromFormat(
|
|
|
|
$value = DateTime::createFromFormat(
|
|
|
|
DateTimeInterface::RFC3339,
|
|
|
|
DateTimeInterface::RFC3339,
|
|
|
|
$this->getProperty($name, $default === null ? null : $default->format(DateTimeInterface::RFC3339))
|
|
|
|
$this->getProperty($name, $default?->format(DateTimeInterface::RFC3339))
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
$errors = DateTime::getLastErrors();
|
|
|
|
$errors = DateTime::getLastErrors();
|
|
|
@ -234,4 +230,60 @@ abstract class GenericConfig implements ISingleton {
|
|
|
|
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Get a property value as an enum
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param string $name The property name
|
|
|
|
|
|
|
|
* @param class-string<UnitEnum> $enumClass The enum class name
|
|
|
|
|
|
|
|
* @param UnitEnum|null $default The default value if property is not set
|
|
|
|
|
|
|
|
* <br>Raise an exception if not <b>$enumClass</b> enum
|
|
|
|
|
|
|
|
* <br>Raise an exception if property is not set AND $default is Null
|
|
|
|
|
|
|
|
* <br>Raise an exception if property is set but not valid (not an enum)
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return UnitEnum The enum
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @throws ReflectionException If <b>$enumClass</b> is not a valid enum class
|
|
|
|
|
|
|
|
* @throws InvalidArgumentException If <b>$default</b> is not a <b>$enumClass</b> enum
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public function getPropertyAsEnum (string $name, string $enumClass, ?UnitEnum $default = null): UnitEnum {
|
|
|
|
|
|
|
|
$enumReflection = new ReflectionEnum($enumClass);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//region Check default value type
|
|
|
|
|
|
|
|
if ($default !== null && !$default instanceof $enumClass) {
|
|
|
|
|
|
|
|
throw new InvalidArgumentException('The default property type must be an ' . $enumClass);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
//region Return default value (or raise exception) if property is not set
|
|
|
|
|
|
|
|
if (!$this->hasProperty($name)) {
|
|
|
|
|
|
|
|
if ($default === null) {
|
|
|
|
|
|
|
|
throw new UnexpectedValueException('The "' . $name . '" property is not set');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return $default;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//region Try to find the enum through a case name
|
|
|
|
|
|
|
|
$propertyValue = $this->getPropertyAsString($name);
|
|
|
|
|
|
|
|
if ($enumReflection->hasCase($propertyValue)) {
|
|
|
|
|
|
|
|
return $enumReflection->getCase($propertyValue)->getValue();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
//region Try to find enum through the value (if BackedEnum)
|
|
|
|
|
|
|
|
if ($enumReflection->isBacked()) {
|
|
|
|
|
|
|
|
if (((string)$enumReflection->getBackingType()) === 'int') {
|
|
|
|
|
|
|
|
$propertyValue = $this->getPropertyAsInt($name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @var ReflectionEnumBackedCase $enumBackedCase */
|
|
|
|
|
|
|
|
foreach ($enumReflection->getCases() as $enumBackedCase) {
|
|
|
|
|
|
|
|
if ($enumBackedCase->getBackingValue() === $propertyValue) {
|
|
|
|
|
|
|
|
return $enumBackedCase->getValue();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
//region Unable to find valid enum → raise exception
|
|
|
|
|
|
|
|
throw new UnexpectedValueException('The "' . $name . '" property is not a valid enum ' . $enumClass);
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|