ldc-boutique-cnc-sable/shared/Enums/BaseEnum.php
2026-10-27 09:58:12 +01:00

160 lines
3.7 KiB
PHP

<?php
declare(strict_types=1);
namespace Shared\Enums;
/**
* @template V of string|int
*
* @mixin \BackedEnum
*/
trait BaseEnum
{
private const LABELS_CONSTANT_NAME = 'LABELS';
/**
* @return V
*/
public function value(): string | int
{
return $this->value;
}
public function label(): string
{
return self::toLabels()[$this->name] ?? ucfirst(strtolower($this->name));
}
public function name(): string
{
return $this->name;
}
/**
* @return array<string,string>
*/
public static function toLabels(): array
{
static $cache = null;
if ($cache !== null) {
return $cache;
}
$labels = defined(self::class . '::' . self::LABELS_CONSTANT_NAME)
? constant(self::class . '::' . self::LABELS_CONSTANT_NAME)
: null;
$result = [];
foreach (self::cases() as $enum) {
if ($labels !== null && ! isset($labels[$enum->name])) {
throw new \Error('Missing definition label ' . self::class . " for '{$enum->name}'");
}
$result[$enum->name] = $labels[$enum->name] ?? ucfirst(strtolower($enum->name));
}
return $cache = $result;
}
/**
* @return array<string, V>
*/
public static function toValues(): array
{
static $cache = null;
if ($cache !== null) {
return $cache;
}
return $cache = array_column(
self::cases(),
'value',
'name'
);
}
/**
* @param self|V $value
*/
public static function make(self | int | string $value, string $field = 'value'): ?self
{
if ($value instanceof self) {
return $value;
}
if ($field === 'value') {
$tryValue = null;
try {
$tryValue = self::tryFrom(intval($value));
} catch (\ValueError) {
$tryValue = self::tryFrom(strval($value));
} finally {
if ($tryValue !== null) {
return $tryValue;
}
}
}
if ($field === 'label') {
$normalizedSearch = preg_replace('/[\W_]+/u', '', mb_strtolower((string) $value));
foreach (self::cases() as $enum) {
$normalizedLabel = preg_replace('/[\W_]+/u', '', mb_strtolower($enum->label()));
if ($normalizedLabel === $normalizedSearch) {
return $enum;
}
}
return null;
}
foreach (self::cases() as $enum) {
if ($enum->{$field} === $value) {
return $enum;
}
}
return null;
}
public function equals(object ...$others): bool
{
return in_array($this, $others, true);
}
public function jsonSerialize(): mixed
{
return $this->value;
}
// * PRIVATE
/**
* @return array<string, array<string, mixed>>
*/
private static function getCustomDefinitions(): array
{
static $cache = null;
if ($cache !== null) {
return $cache;
}
$names = array_column(self::cases(), 'name', 'name');
$filteredConstants = [];
foreach ((new \ReflectionClass(self::class))->getConstants() as $key => $constant) {
if ($key === self::LABELS_CONSTANT_NAME || ! \is_array($constant)) {
continue;
}
if (! empty(array_intersect_key($constant, $names))) {
$filteredConstants[$key] = $constant;
}
}
return $cache = $filteredConstants;
}
}