Skip to content

Commit

Permalink
helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
henzeb committed Jun 7, 2022
1 parent c879e70 commit a120e54
Show file tree
Hide file tree
Showing 10 changed files with 472 additions and 29 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

All notable changes to `Enumhancer` will be documented in this file

## 1.8.0 - 2022-06-07
- added [Helper functions](docs/functions.md) to ease usage of basic enums.

## 1.7.0 - 2022-06-06
- When using [Comparison](docs/comparison.md), you can now assert with `is` or `isNot`

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ This package currently supports the following:
Laravel specific features:
- Casting (Laravel Specific)

Helper functions:
- backing
- name
- value

Note: While functionality that also exists in Spatie's PHP Enum is made backwards
compatible to allow for an easy migration to PHP native enums, currently this is
not the case for the PHPUnit assertions or Faker Provider.
Expand Down Expand Up @@ -77,6 +82,11 @@ implemented the methods of `Makers`, `Extractor` and `Reporters`.
- [Subset](docs/subset.md)
- [Value](docs/value.md)

### Helper functions
- [Backing](docs/functions.md#backing)
- [Name](docs/functions.md#name)
- [Value](docs/functions.md#value)

### Laravel specific Features

- [Casting](docs/casting.md)
Expand Down
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"orchestra/testbench": "^7.0"
},
"autoload": {
"files": [
"src/Functions/Functions.php"
],
"psr-4": {
"Henzeb\\Enumhancer\\": "src/"
}
Expand Down
116 changes: 116 additions & 0 deletions docs/functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Helper functions

To accommodate situations that haven't been solved (yet), a few helper
functions.

Each helper function that works with values has a lowercase version
for easy usage.

Each helper function has a full name version and a shortcut, just pick your
personal favorite poison.

Each function also accepts null and returns null when
this happens. This eases usage with optional situations.

## Backing

In some situations, libraries or frameworks only accept backed enumerations
and/or Stringable objects. Or you want to use the name/value of either backed or
basic enums. This method gives you a proxy object with name and value
properties.

Note: an example of where this is useful is in Laravel's Query Builder.

### Examples

```php
enum MyEnum {
case Enum;
case Other;
}

enum MyStringEnum: string {
case String = 'My string';
}

\Henzeb\Enumhancer\Functions\b(MyEnum::Enum)->name; // Enum
\Henzeb\Enumhancer\Functions\b(MyEnum::Enum)->value; // Enum
(string)\Henzeb\Enumhancer\Functions\b(MyEnum::Enum); // Enum

\Henzeb\Enumhancer\Functions\b(MyEnum::Enum, false)->value; // enum
(string)\Henzeb\Enumhancer\Functions\b(MyEnum::Enum, false); // enum

\Henzeb\Enumhancer\Functions\b(MyStringEnum::String, false)->value; // My string
(string)\Henzeb\Enumhancer\Functions\b(MyStringEnum::String, false); // My string

\Henzeb\Enumhancer\Functions\backing(MyEnum::Enum)->name; // Enum
\Henzeb\Enumhancer\Functions\backing(MyEnum::Enum)->value; // Enum
(string)\Henzeb\Enumhancer\Functions\backing(MyEnum::Enum); // Enum

\Henzeb\Enumhancer\Functions\backing(MyEnum::Enum, false)->value; // enum
(string)\Henzeb\Enumhancer\Functions\backing(MyEnum::Enum, false); // enum

\Henzeb\Enumhancer\Functions\backing(MyStringEnum::String, false)->value; // My string
(string)\Henzeb\Enumhancer\Functions\backing(MyStringEnum::String, false); // My string

# Lower case
\Henzeb\Enumhancer\Functions\bl(MyEnum::Enum)->name; // Enum
\Henzeb\Enumhancer\Functions\bl(MyEnum::Enum)->value; // enum
(string)\Henzeb\Enumhancer\Functions\bl(MyEnum::Enum); // enum

\Henzeb\Enumhancer\Functions\bl(MyStringEnum::String)->value; // My string
(string)\Henzeb\Enumhancer\Functions\bl(MyStringEnum::String); // My string

\Henzeb\Enumhancer\Functions\backingLowercase(MyEnum::Enum)->name; // Enum
\Henzeb\Enumhancer\Functions\backingLowercase(MyEnum::Enum)->value; // enum
(string)\Henzeb\Enumhancer\Functions\backingLowercase(MyEnum::Enum); // enum

\Henzeb\Enumhancer\Functions\backingLowercase(MyStringEnum::String)->value; // My string
(string)\Henzeb\Enumhancer\Functions\backingLowercase(MyStringEnum::String); // My string

```

## Name

This function is particular useful when you want to use it as an array key.

```php
enum MyEnum {
case Enum;
}

\Henzeb\Enumhancer\Functions\n(MyEnum::Enum); // Enum
\Henzeb\Enumhancer\Functions\name(MyEnum::Enum); // Enum
```

## Value

This function returns the value of your Enum. Works just like
[Value](value.md), except for the lower case variants which return the
lower case version of the enum name.

```php
enum MyEnum {
case Enum;
}

enum MyStringEnum: string {
case String = 'String';
}

\Henzeb\Enumhancer\Functions\v(MyEnum::Enum); // Enum
\Henzeb\Enumhancer\Functions\v(MyEnum::Enum, false); // enum
\Henzeb\Enumhancer\Functions\v(MyStringEnum::String, false); // My string

\Henzeb\Enumhancer\Functions\value(MyEnum::Enum); // Enum
\Henzeb\Enumhancer\Functions\value(MyEnum::Enum, false); // enum
\Henzeb\Enumhancer\Functions\value(MyStringEnum::String, false); // My string

# Lower case
\Henzeb\Enumhancer\Functions\vl(MyEnum::Enum); // enum
\Henzeb\Enumhancer\Functions\vl(MyStringEnum::String); // My string

\Henzeb\Enumhancer\Functions\valueLowercase(MyEnum::Enum); // enum
\Henzeb\Enumhancer\Functions\valueLowercase(MyStringEnum::String); // My string

```
96 changes: 96 additions & 0 deletions src/Functions/Functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Henzeb\Enumhancer\Functions;

use UnitEnum;
use Henzeb\Enumhancer\Helpers\EnumProxy;
use Henzeb\Enumhancer\Helpers\EnumValue;

/**
* returns a proxy object with a value property equal to it's name when given enum is not backed
* @param UnitEnum|null $enum
* @param bool $keepValueCase
* @return EnumProxy|null
*/
function b(?UnitEnum $enum, bool $keepValueCase = true): ?EnumProxy
{
if(!$enum) {
return null;
}

return new EnumProxy($enum, $keepValueCase);
}

function backing(?UnitEnum $enum, bool $keepValueCase = true): ?EnumProxy
{
return b($enum, $keepValueCase);
}

/**
* returns a proxy object with a lower cased value equal to it's name when given enum is not backed
*
* @param UnitEnum|null $enum
* @return EnumProxy|null
*/
function bl(?UnitEnum $enum): ?EnumProxy
{
return b($enum, false);
}

function backingLowercase(?UnitEnum $enum): ?EnumProxy
{
return bl($enum);
}

/**
* returns the name of the given enum. Useful when using it as an array key.
*
* @param UnitEnum|null $enum
* @return string|null
*/
function n(?UnitEnum $enum): ?string
{
return $enum?->name;
}

function name(?UnitEnum $enum): ?string
{
return n($enum);
}

/**
* Returns a value equal to it's name when given enum is not backed by default
*
* @param UnitEnum|null $enum
* @param bool $keepValueCase returns a lower cased enum name when it's a UnitEnum
* @return string|int|null
*/
function v(?UnitEnum $enum, bool $keepValueCase = true): string|int|null
{
if(!$enum) {
return null;
}
return EnumValue::value($enum, $keepValueCase);
}


function value(?UnitEnum $enum, bool $keepValueCase = true): string|int|null
{
return v($enum, $keepValueCase);
}

/**
* Returns a lowercase value equal to it's name when given enum is not backed.
*
* @param UnitEnum|null $enum
* @return string|int|null
*/
function vl(?UnitEnum $enum): string|int|null
{
return value($enum, false);
}

function valueLowercase(?UnitEnum $enum): string|int|null
{
return vl($enum);
}
24 changes: 24 additions & 0 deletions src/Helpers/EnumProxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Henzeb\Enumhancer\Helpers;

use UnitEnum;
use Stringable;
use function Henzeb\Enumhancer\Functions\v;

class EnumProxy implements Stringable
{
public readonly string $name;
public readonly string $value;

public function __construct(private readonly UnitEnum $enum, bool $keepValueCase)
{
$this->name = $this->enum->name;
$this->value = v($this->enum, $keepValueCase);
}

public function __toString(): string
{
return $this->value;
}
}
38 changes: 10 additions & 28 deletions src/Laravel/Concerns/CastsBasicEnumerations.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Database\Eloquent\Model;
use Henzeb\Enumhancer\Helpers\EnumValue;
use Henzeb\Enumhancer\Helpers\EnumMakers;
use function Henzeb\Enumhancer\Functions\b;

/**
* @mixin Model
Expand All @@ -22,18 +23,18 @@ protected function getEnumCastableAttributeValue($key, $value)

$castType = $this->getCasts()[$key];

/**
* @TODO: remove when fixed: https://github.com/laravel/framework/issues/42658
*/
if ($this->shouldUseWorkaround($castType)) {
return $this->enumToArrayWorkaround($value);
if (!$value instanceof $castType) {
$value = EnumMakers::make($castType, $value);
}

if ($value instanceof $castType) {
return $value;
if ($this->shouldUseBasicEnumWorkaround($castType)) {

$keepEnumCase = property_exists($this, 'keepEnumCase') ? $this->keepEnumCase : true;

return b($value, $keepEnumCase);
}

return EnumMakers::make($castType, $value);
return $value;
}

protected function setEnumCastableAttribute($key, $value)
Expand All @@ -59,26 +60,7 @@ protected function setEnumCastableAttribute($key, $value)
}
}

/**
* @TODO: remove when fixed: https://github.com/laravel/framework/issues/42658
* @param $value
* @return object
*/
private function enumToArrayWorkaround(string|int $value): object
{
return new class($value) {
public function __construct(public readonly string|int $value)
{
}
};
}

/**
* @TODO: remove when fixed: https://github.com/laravel/framework/issues/42658
* @param string $enumClass
* @return bool
*/
private function shouldUseWorkaround(string $enumClass): bool
private function shouldUseBasicEnumWorkaround(string $enumClass): bool
{
return (!is_subclass_of($enumClass, BackedEnum::class, true))
&& 'toArray' === (debug_backtrace(2)[5]['function'] ?? null);
Expand Down
5 changes: 4 additions & 1 deletion tests/Fixtures/EnhancedBackedEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
use Henzeb\Enumhancer\Contracts\Mapper;
use Henzeb\Enumhancer\Concerns\Enhancers;
use Henzeb\Enumhancer\Concerns\Constructor;
use function Henzeb\Enumhancer\Functions\s;
use function Henzeb\Enumhancer\Functions\n;


/**
* @EnhancedBackedEnum
Expand All @@ -21,7 +24,7 @@ enum EnhancedBackedEnum: string
protected function labels(): array
{
return [
'ENUM' => 'My label'
n(self::ENUM) => 'My label'
];
}

Expand Down
Loading

0 comments on commit a120e54

Please sign in to comment.