Hanle Enum not routable exception, instead of just resolvinf enum with null variables
This commit is contained in:
parent
fdfb6af639
commit
03bac5ba89
5 changed files with 91 additions and 32 deletions
|
|
@ -6,6 +6,7 @@ use BadMethodCallException;
|
|||
use JsonSerializable;
|
||||
use Kwaadpepper\Enum\Exceptions\DuplicateLabelsException;
|
||||
use Kwaadpepper\Enum\Exceptions\DuplicateValuesException;
|
||||
use Kwaadpepper\Enum\Exceptions\EnumNotRoutableException;
|
||||
use Kwaadpepper\Enum\Exceptions\UnknownEnumProperty;
|
||||
use ReflectionClass;
|
||||
use TypeError;
|
||||
|
|
@ -38,6 +39,25 @@ abstract class BaseEnum implements JsonSerializable
|
|||
|
||||
// -- ENUM MAGIC METHODS --
|
||||
|
||||
/**
|
||||
* @param int|string $value
|
||||
* @param string $label
|
||||
* @throws TypeError If anything else than string or int is used for value.
|
||||
* @throws EnumNotRoutableException If provided value are null
|
||||
*/
|
||||
public function __construct($value = null, string $label = null)
|
||||
{
|
||||
/**
|
||||
* This cannot be allowed, happens with laravel resolver
|
||||
* when using BaseEnum instead of BaseEnumRoutable
|
||||
*/
|
||||
if ($label === null and !is_subclass_of(static::class, BaseEnumRoutable::class)) {
|
||||
throw new EnumNotRoutableException();
|
||||
}
|
||||
$this->label = $label;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attribute
|
||||
* @return int|string
|
||||
|
|
@ -60,6 +80,7 @@ abstract class BaseEnum implements JsonSerializable
|
|||
* @return static
|
||||
* @throws TypeError If anything else than string or int is used.
|
||||
* @throws BadMethodCallException If a matching definition cannot be found.
|
||||
* @throws EnumNotRoutableException If provided value are null
|
||||
*/
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceAfterLastUsed
|
||||
public static function __callStatic(string $name, array $arguments)
|
||||
|
|
@ -166,13 +187,11 @@ abstract class BaseEnum implements JsonSerializable
|
|||
* @return static
|
||||
* @throws TypeError If anything else than string or int is used.
|
||||
* @throws BadMethodCallException If a matching definition cannot be found.
|
||||
* @throws EnumNotRoutableException If provided value are null
|
||||
*/
|
||||
public static function make($value): BaseEnum
|
||||
{
|
||||
if (!(is_string($value) || is_int($value))) {
|
||||
$enumClass = static::class;
|
||||
throw new TypeError("Only string and integer are allowed values for enum $enumClass.");
|
||||
}
|
||||
self::assertValidValue($value);
|
||||
|
||||
$definition = static::findDefinition($value);
|
||||
|
||||
|
|
@ -183,9 +202,10 @@ abstract class BaseEnum implements JsonSerializable
|
|||
);
|
||||
}
|
||||
|
||||
$obj = new static();
|
||||
$obj->value = $definition->value;
|
||||
$obj->label = $definition->label;
|
||||
$obj = new static(
|
||||
$definition->value,
|
||||
$definition->label
|
||||
);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
|
@ -281,4 +301,19 @@ abstract class BaseEnum implements JsonSerializable
|
|||
{
|
||||
return count($array) > count(array_unique($array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert value is valid
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @throws TypeError If anything else than string or int is used.
|
||||
*/
|
||||
private static function assertValidValue($value): void
|
||||
{
|
||||
if (!(is_string($value) || is_int($value))) {
|
||||
$enumClass = static::class;
|
||||
throw new TypeError("Only string and integer are allowed values for enum $enumClass.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ namespace Kwaadpepper\Enum;
|
|||
|
||||
use BadMethodCallException;
|
||||
use Illuminate\Contracts\Routing\UrlRoutable;
|
||||
use Kwaadpepper\Enum\Exceptions\EnumNotRoutableException;
|
||||
use Kwaadpepper\Enum\Exceptions\NotImplementedException;
|
||||
use TypeError;
|
||||
|
||||
/**
|
||||
* This Base Enum will be routable with laravel.
|
||||
|
|
@ -54,11 +56,11 @@ abstract class BaseEnumRoutable extends BaseEnum implements UrlRoutable
|
|||
$iValue = (is_numeric($value) and floatval(intval($value)) === floatval($value)) ?
|
||||
(int)$value : $value;
|
||||
return static::make($iValue);
|
||||
} catch (BadMethodCallException $e) {
|
||||
} catch (BadMethodCallException | EnumNotRoutableException | TypeError $e) {
|
||||
// try string value after that
|
||||
try {
|
||||
return static::make($value);
|
||||
} catch (BadMethodCallException $e) {
|
||||
} catch (BadMethodCallException | EnumNotRoutableException | TypeError $e) {
|
||||
// could not find a suitable value
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
16
src/Exceptions/EnumNotRoutableException.php
Normal file
16
src/Exceptions/EnumNotRoutableException.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Kwaadpepper\Enum\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Is thrown on enum constructor
|
||||
* as it happens with laravel resolver
|
||||
* it is named like this event if it is only on
|
||||
* BaseEnum which works on any application
|
||||
*/
|
||||
class EnumNotRoutableException extends Exception
|
||||
{
|
||||
//
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ trait CastsEnums
|
|||
{
|
||||
if (
|
||||
$value === null or
|
||||
$value instanceof BaseEnum or
|
||||
(\is_object($value) and \is_subclass_of($value, BaseEnum::class)) or
|
||||
!isset($this->enumCasts[$key])
|
||||
) {
|
||||
return $value;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace Kwaadpepper\Enum\Tests;
|
|||
use App\Http\Requests\PassDayRequest;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Kwaadpepper\Enum\Exceptions\EnumNotRoutableException;
|
||||
use Kwaadpepper\Enum\Exceptions\UnknownEnumClass;
|
||||
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
|
||||
use Kwaadpepper\Enum\Tests\Enums\ContactFormCivility;
|
||||
|
|
@ -137,79 +138,80 @@ class BaseEnumRoutableTest extends TestCase
|
|||
return response()->json([$force]);
|
||||
})->middleware('bindings');
|
||||
$router->get('/notroutable/{notroutable}', function (NotRoutableEnum $notroutable) {
|
||||
dd($notroutable);
|
||||
return response()->json([$notroutable]);
|
||||
})->middleware('bindings');
|
||||
}
|
||||
|
||||
public function testRoutesDays()
|
||||
{
|
||||
$response = $this->call('GET', sprintf('/days/%s', Days::none()->value));
|
||||
$response = $this->json('GET', sprintf('/days/%s', Days::none()->value));
|
||||
$response->assertOk();
|
||||
$response->assertExactJson([Days::none()]);
|
||||
$response = $this->call('GET', sprintf('/days/%s', Days::mon()->value));
|
||||
$response = $this->json('GET', sprintf('/days/%s', Days::mon()->value));
|
||||
$response->assertOk();
|
||||
$response->assertExactJson([Days::mon()]);
|
||||
}
|
||||
|
||||
public function testRoutesCivilities()
|
||||
{
|
||||
$response = $this->call('GET', sprintf('/civilities/%s', ContactFormCivility::mme()->value));
|
||||
$response = $this->json('GET', sprintf('/civilities/%s', ContactFormCivility::mme()->value));
|
||||
$response->assertOk();
|
||||
$response->assertExactJson([ContactFormCivility::mme()]);
|
||||
}
|
||||
|
||||
public function testRoutesWithEnumIntString()
|
||||
{
|
||||
$response = $this->call('GET', sprintf('/force/%s', ForceStringsFromInteger::valueB()->value));
|
||||
$response = $this->json('GET', sprintf('/force/%s', ForceStringsFromInteger::valueB()->value));
|
||||
$response->assertOk();
|
||||
$response->assertExactJson([ForceStringsFromInteger::valueB()]);
|
||||
}
|
||||
|
||||
public function testRoutesWithEnumNotFound()
|
||||
{
|
||||
$response = $this->call('GET', '/force/6');
|
||||
$response = $this->json('GET', '/force/6');
|
||||
$response->assertNotFound();
|
||||
}
|
||||
|
||||
public function testRoutesWithEnumAsPrimaryKey()
|
||||
{
|
||||
$response = $this->call('GET', sprintf('/reports/%s', Days::none()->value));
|
||||
$response = $this->json('GET', sprintf('/reports/%s', Days::none()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/reports/%s', Days::mon()->value));
|
||||
$response = $this->json('GET', sprintf('/reports/%s', Days::mon()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/reports/%s', Days::tue()->value));
|
||||
$response = $this->json('GET', sprintf('/reports/%s', Days::tue()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/reports/%s', Days::fri()->value));
|
||||
$response = $this->json('GET', sprintf('/reports/%s', Days::fri()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/reports/%s', 9999));
|
||||
$response = $this->json('GET', sprintf('/reports/%s', 9999));
|
||||
$response->assertNotFound();
|
||||
}
|
||||
|
||||
public function testRoutesWithEnumAsPrimaryKeyWithoutCastEnums()
|
||||
{
|
||||
$response = $this->call('GET', sprintf('/alarms/%s', Days::none()->value));
|
||||
$response = $this->json('GET', sprintf('/alarms/%s', Days::none()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/alarms/%s', Days::mon()->value));
|
||||
$response = $this->json('GET', sprintf('/alarms/%s', Days::mon()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/alarms/%s', Days::tue()->value));
|
||||
$response = $this->json('GET', sprintf('/alarms/%s', Days::tue()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/alarms/%s', Days::fri()->value));
|
||||
$response = $this->json('GET', sprintf('/alarms/%s', Days::fri()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/alarms/%s', 9999));
|
||||
$response = $this->json('GET', sprintf('/alarms/%s', 9999));
|
||||
$response->assertNotFound();
|
||||
}
|
||||
|
||||
public function testRoutesWithEnumAsPrimaryKeyWithoutCastEnumsAndCast()
|
||||
{
|
||||
$response = $this->call('GET', sprintf('/journals/%s', Days::none()->value));
|
||||
$response = $this->json('GET', sprintf('/journals/%s', Days::none()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/journals/%s', Days::mon()->value));
|
||||
$response = $this->json('GET', sprintf('/journals/%s', Days::mon()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/journals/%s', Days::tue()->value));
|
||||
$response = $this->json('GET', sprintf('/journals/%s', Days::tue()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/journals/%s', Days::fri()->value));
|
||||
$response = $this->json('GET', sprintf('/journals/%s', Days::fri()->value));
|
||||
$response->assertOk();
|
||||
$response = $this->call('GET', sprintf('/journals/%s', 9999));
|
||||
$response = $this->json('GET', sprintf('/journals/%s', 9999));
|
||||
$response->assertNotFound();
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +225,7 @@ class BaseEnumRoutableTest extends TestCase
|
|||
|
||||
public function testRulesRequest()
|
||||
{
|
||||
$response = $this->call('GET', sprintf('/day-validation?day=%s', Days::fri()->value));
|
||||
$response = $this->json('GET', sprintf('/day-validation?day=%s', Days::fri()->value));
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
|
|
@ -242,6 +244,10 @@ class BaseEnumRoutableTest extends TestCase
|
|||
public function testNotRoutableEnum()
|
||||
{
|
||||
$response = $this->json('GET', sprintf('/notroutable/%s', '1'));
|
||||
$response->assertOk();
|
||||
$response->assertStatus(500);
|
||||
$this->assertEquals(
|
||||
new EnumNotRoutableException(),
|
||||
$response->exception
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue