*/ trait BaseEnum { // * GENERIC METHODS /** * Get enum value * * @return string|integer */ public function value(): string|int { return self::toValues()[$this->name]; } /** * Get enum label * * @return string */ public function label(): string { return self::toLabels()[$this->name]; } /** * Get enum name * * @return string */ public function name(): string { return $this->name; } // * STATIC FETCH METHODS /** * Get enum labels * * @return array */ public static function toLabels(): array { if (empty(self::getCache('labels'))) { $labels = self::getLabelsConstant(); self::setCache('labels', \collect(self::cases()) ->mapWithKeys(function ($enum) use ($labels) { if (!\is_null($labels) and !isset($labels[$enum->name])) { throw new \Error('Missing definition label ' . self::class . " for {$enum->name}"); } return [$enum->name => \trans( !\is_null($labels) ? $labels[$enum->name] : Str::ucfirst($enum->name) )]; })->all()); } return self::getCache('labels'); } /** * Get enum values * * @return array */ public static function toValues(): array { if (empty(self::getCache('values'))) { self::setCache('values', \collect(self::cases()) ->mapWithKeys(fn ($enum) => [$enum->name => $enum->value])->all()); } return self::getCache('values'); } /** * Get enums * * @return array */ public static function all(): array { return self::cases(); } /** * Get enums * * @return array */ public static function toArray(): array { if (empty(self::getCache('enums'))) { $definitions = self::getCustomDefinitions(); self::setCache('enums', \collect(self::cases()) ->mapWithKeys(function ($enum) use ($definitions) { $baseArray = [ 'name' => $enum->name, 'label' => $enum->label(), 'value' => $enum->value, ]; foreach ($definitions as $index => $elements) { $index = Str::lower(Str::singular($index)); if (!isset($elements[$enum->name])) { throw new \Error("Missing definition {$index} " . self::class . " for {$enum->name}"); } $baseArray[$index] = $elements[$enum->name]; } return [$enum->name => (object)$baseArray]; })->all()); } return self::getCache('enums'); } /** * Fetch enum using value * * @param \App\Traits\Enums\BaseEnum|integer|string $value * @return \App\Traits\Enums\BaseEnum|null */ public static function make(self|int|string $value): self|null { return !\is_object($value) ? \collect(self::cases())->keyBy('value')->get($value) : $value; } /** * Test if 2 enum are equals * * @param object ...$others * @return boolean * @throws \Error If provided element are not enums taht extends BaseEnum. */ public function equals(object ...$others): bool { foreach ($others as $other) { if (!\in_array(BaseEnum::class, \class_uses_recursive($other))) { throw new \Error(__METHOD__ . ' requires $enum to use ' . BaseEnum::class); } if ( get_class($this) === get_class($other) && $this->value === $other->value ) { return true; } } return false; } /** * Serialize to json * * @return mixed */ public function jsonSerialize(): mixed { return $this->value; } // * CACHE /** * Get cache array * * @param string $index * @return array */ private static function getCache(string $index): array { self::initCache(); if (!isset($GLOBALS[self::class]['props'][$index])) { $GLOBALS[self::class]['props'][$index] = []; } return $GLOBALS[self::class]['props'][$index]; } /** * Set cache array * * @param string $index * @param array $items * @return void */ private static function setCache(string $index, array $items): void { self::initCache(); if (!isset($GLOBALS[self::class]['props'][$index])) { $GLOBALS[self::class]['props'][$index] = []; } $GLOBALS[self::class]['props'][$index] = $items; } /** * Init cache if needed * * @return void */ private static function initCache(): void { if (!isset($GLOBALS[self::class])) { $GLOBALS[self::class] = [ 'props' => [ 'enums' => [], 'values' => [], 'labels' => [] ], 'customProps' => null ]; } } // * PRIVATE /** * Fetch the LABELS constant if exists * * @return array|null */ private static function getLabelsConstant(): array|null { $class_name = self::class; try { $constant_reflex = new \ReflectionClassConstant($class_name, 'LABELS'); return $constant_reflex->getValue(); } catch (\ReflectionException $e) { return null; } } /** * Get custom constants * * @return array */ private static function getCustomDefinitions(): array { // ? Has custom props in cache ? if (!isset($GLOBALS[self::class]) or \is_null($GLOBALS[self::class]['customProps'])) { $names = \collect(self::cases())->keyBy('name'); $GLOBALS[self::class]['customProps'] = \collect((new \ReflectionClass(self::class))->getConstants()) ->filter(function (mixed $constant, string $key) use ($names) { if ($key === 'LABELS' or !\is_array($constant)) { return false; } return \collect($constant)->keys() ->filter(fn (string $name) => $names->has($name))->count(); })->all(); } return $GLOBALS[self::class]['customProps']; } }