Add getPropertyAsEnum method

master 3.0.0
Julien Rosset 7 months ago
parent 2dd3b9137a
commit 78292f0bf3

@ -9,15 +9,15 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
"dev-master": "3.x-dev"
}
},
"minimum-stability": "stable",
"require": {
"php": "^7.4 || ^8.0",
"jrosset/singleton": "^1.5",
"jrosset/collections": "^2.3 || ^3.0"
"php": "^8.1",
"jrosset/singleton": "^2.0",
"jrosset/collections": "^3.5"
},
"autoload": {
"psr-4": {

@ -5,13 +5,18 @@ namespace jrosset\EnvReader;
use DateTime;
use DateTimeInterface;
use Exception;
use InvalidArgumentException;
use jrosset\Collections\IArrayCast;
use jrosset\Collections\InsensitiveCaseKeyCollection;
use jrosset\Collections\InsensitiveCaseKeyImmutableCollection;
use jrosset\Singleton\ISingleton;
use jrosset\Singleton\TSingleton;
use RangeException;
use ReflectionEnum;
use ReflectionEnumBackedCase;
use ReflectionException;
use UnexpectedValueException;
use UnitEnum;
/**
* A generic configuration class
@ -40,10 +45,8 @@ abstract class GenericConfig implements ISingleton {
* Initial properties
*
* @return string[]|IArrayCast Initial properties
*
* @noinspection PhpReturnDocTypeMismatchInspection
*/
protected function initialProperties () {
protected function initialProperties (): array|IArrayCast {
return [];
}
/**
@ -76,15 +79,15 @@ abstract class GenericConfig implements ISingleton {
/**
* Get a property value
*
* @param string $name The property name
* @param mixed $default The default value if property is not set
* Raise an exception if property is not set AND $default is Null
* @param string $name The property name
* @param mixed|null $default The default value if property is not set
* <br>Raise an exception if property is not set AND $default is Null
*
* @return mixed The property value
*
* @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 ($default === null) {
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|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
*
@ -122,7 +125,7 @@ abstract class GenericConfig implements ISingleton {
*
* @param string $name The property name
* @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
*
@ -132,25 +135,18 @@ abstract class GenericConfig implements ISingleton {
* @noinspection PhpUnused
*/
public function getPropertyAsBool (string $name, ?bool $default = null): bool {
switch ($value = $this->getProperty($name, $default === null ? null : ($default === true ? '1' : '0'))) {
case '1':
case 'true':
return true;
case '0':
case 'false':
return false;
default:
throw new RangeException('The "' . $name . '" property is not a valid boolean : ' . $value);
}
return match ($value = $this->getProperty($name, $default === null ? null : ($default === true ? '1' : '0'))) {
'1', 'true' => true,
'0', 'false' => false,
default => throw new RangeException('The "' . $name . '" property is not a valid boolean : ' . $value),
};
}
/**
* Get a property value as an integer
*
* @param string $name The property name
* @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
*
@ -171,7 +167,7 @@ abstract class GenericConfig implements ISingleton {
*
* @param string $name The property name
* @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
*
@ -194,7 +190,7 @@ abstract class GenericConfig implements ISingleton {
*
* @param string $name The property name
* @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
*
@ -206,7 +202,7 @@ abstract class GenericConfig implements ISingleton {
public function getPropertyAsDateTime (string $name, ?DateTime $default = null): DateTime {
$value = DateTime::createFromFormat(
DateTimeInterface::RFC3339,
$this->getProperty($name, $default === null ? null : $default->format(DateTimeInterface::RFC3339))
$this->getProperty($name, $default?->format(DateTimeInterface::RFC3339))
);
$errors = DateTime::getLastErrors();
@ -234,4 +230,60 @@ abstract class GenericConfig implements ISingleton {
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
}
}

@ -43,14 +43,14 @@ trait TMultiLevelProperties {
* Get a property value
*
* @param string|string[]|IArrayCast $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
*
* @return mixed The property value
*
* @throws UnexpectedValueException If property is not set AND $default is Null
*/
public function getProperty ($name, $default = null) {
public function getProperty ($name, mixed $default = null) {
if (!$this->hasProperty($name)) {
if ($default === null) {
throw new UnexpectedValueException('The "' . $name . '" property is not set');

@ -3,3 +3,5 @@ WEBSITE_NAME="Foo Bar"
DB_NAME=Bar
DB_LOGIN=Bar
DB_PASS=*****
TEST=Test2

@ -0,0 +1,7 @@
<?php
enum TestEnum: int {
case Test1 = 1;
case Test2 = 2;
case Test3 = 3;
}

@ -2,6 +2,7 @@
/** @noinspection PhpIllegalPsrClassPathInspection */
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/TestEnum.php';
use jrosset\EnvReader\EnvConfig;
@ -19,3 +20,4 @@ class Env extends EnvConfig {
var_dump(Env::getInstance()->getProperties());
var_dump(Env::getInstance()->getProperty('db_host', 'localhost'));
var_dump(Env::getInstance()->getPropertyAsEnum('test', TestEnum::class, TestEnum::Test1));
Loading…
Cancel
Save