Skip to content

Commit

Permalink
Merge branch 'release/2.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
cerbero90 committed Oct 30, 2024
2 parents 44846f2 + 6613a93 commit 2a05cbc
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 38 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,32 @@ Updates should follow the [Keep a CHANGELOG](https://keepachangelog.com/) princi
- Nothing


## 2.1.0 - 2024-10-30

### Added
- Method has() to the cases collection
- JsonSerializable and Stringable interfaces to the cases collection
- Methods isBackedByInteger() and isBackedByString() to the SelfAware trait

### Changed
- Allow any callable when setting the logic for magic methods
- Allow meta inheritance when getting meta names
- Improve generics in cases collection
- Simplify logic by negating methods in the Compares trait

### Deprecated
- Nothing

### Fixed
- Nothing

### Removed
- Nothing

### Security
- Nothing


## 2.0.0 - 2024-10-05

### Added
Expand Down
57 changes: 45 additions & 12 deletions src/CasesCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@
use BackedEnum;
use Countable;
use IteratorAggregate;
use JsonSerializable;
use Stringable;
use Traversable;

/**
* The collection of enum cases.
*
* @template TKey of array-key
* @template TValue
*
* @implements IteratorAggregate<TKey, TValue>
* @implements IteratorAggregate<array-key, TValue>
*/
class CasesCollection implements Countable, IteratorAggregate
class CasesCollection implements Countable, IteratorAggregate, JsonSerializable, Stringable
{
/**
* Whether the cases belong to a backed enum.
Expand All @@ -25,13 +26,31 @@ class CasesCollection implements Countable, IteratorAggregate
/**
* Instantiate the class.
*
* @param array<TKey, TValue> $cases
* @param array<array-key, TValue> $cases
*/
final public function __construct(protected array $cases)
final public function __construct(protected readonly array $cases)
{
$this->enumIsBacked = reset($cases) instanceof BackedEnum;
}

/**
* Turn the collection into a string.
*/
public function __toString(): string
{
return (string) json_encode($this->jsonSerialize());
}

/**
* Turn the collection into a JSON serializable array.
*
* @return list<string|int>
*/
public function jsonSerialize(): array
{
return $this->enumIsBacked ? $this->values() : $this->names();
}

/**
* Retrieve the count of cases.
*/
Expand All @@ -43,7 +62,7 @@ public function count(): int
/**
* Retrieve the iterable cases.
*
* @return Traversable<TKey, TValue>
* @return Traversable<array-key, TValue>
*/
public function getIterator(): Traversable
{
Expand All @@ -53,24 +72,38 @@ public function getIterator(): Traversable
/**
* Retrieve all the cases as a plain array.
*
* @return array<TKey, TValue>
* @return array<array-key, TValue>
*/
public function all(): array
{
return $this->cases;
}

/**
* Determine whether the collection contains the given case.
*/
public function has(mixed $case): bool
{
foreach ($this->cases as $instance) {
if ($instance->is($case)) {
return true;
}
}

return false;
}

/**
* Retrieve all the cases as a plain array recursively.
*
* @return array<TKey, mixed>
* @return array<array-key, mixed>
*/
public function toArray(): array
{
$array = [];

foreach ($this->cases as $key => $value) {
$array[$key] = $value instanceof self ? $value->toArray() : $value;
$array[$key] = $value instanceof static ? $value->toArray() : $value;
}

return $array;
Expand All @@ -79,7 +112,7 @@ public function toArray(): array
/**
* Retrieve the first case.
*
* @param (callable(TValue, TKey): bool)|null $callback
* @param (callable(TValue, array-key): bool)|null $callback
* @return ?TValue
*/
public function first(callable $callback = null): mixed
Expand Down Expand Up @@ -144,8 +177,8 @@ public function pluck(callable|string $value, callable|string $key = null): arra
*
* @template TMapValue
*
* @param callable(TValue, TKey): TMapValue $callback
* @return array<TKey, TMapValue>
* @param callable(TValue, array-key): TMapValue $callback
* @return array<array-key, TMapValue>
*/
public function map(callable $callback): array
{
Expand Down
16 changes: 2 additions & 14 deletions src/Concerns/Compares.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,7 @@ public static function has(mixed $target): bool
*/
public static function doesntHave(mixed $target): bool
{
foreach (self::cases() as $case) {
if ($case->is($target)) {
return false;
}
}

return true;
return !self::has($target);
}

/**
Expand Down Expand Up @@ -74,12 +68,6 @@ public function in(iterable $targets): bool
*/
public function notIn(iterable $targets): bool
{
foreach ($targets as $target) {
if ($this->is($target)) {
return false;
}
}

return true;
return !$this->in($targets);
}
}
20 changes: 18 additions & 2 deletions src/Concerns/SelfAware.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ public static function isBacked(): bool
return is_subclass_of(self::class, BackedEnum::class);
}

/**
* Determine whether the enum is backed by integer.
*/
public static function isBackedByInteger(): bool
{
return (new ReflectionEnum(self::class))->getBackingType()?->getName() === 'int';
}

/**
* Determine whether the enum is backed by string.
*/
public static function isBackedByString(): bool
{
return (new ReflectionEnum(self::class))->getBackingType()?->getName() === 'string';
}

/**
* Retrieve all the meta names of the enum.
*
Expand All @@ -41,12 +57,12 @@ public static function metaNames(): array
$meta = [];
$enum = new ReflectionEnum(self::class);

foreach ($enum->getAttributes(Meta::class) as $attribute) {
foreach ($enum->getAttributes(Meta::class, ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
array_push($meta, ...$attribute->newInstance()->names());
}

foreach ($enum->getCases() as $case) {
foreach ($case->getAttributes(Meta::class) as $attribute) {
foreach ($case->getAttributes(Meta::class, ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
array_push($meta, ...$attribute->newInstance()->names());
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/Enums.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Closure;

/**
* The global behavior for all enums.
* The enums manager.
*/
class Enums
{
Expand Down Expand Up @@ -35,31 +35,31 @@ class Enums
/**
* Set the logic to run when an inaccessible enum method is called.
*
* @param Closure(class-string $enum, string $name, array<array-key, mixed> $arguments): mixed $callback
* @param callable(class-string $enum, string $name, array<array-key, mixed> $arguments): mixed $callback
*/
public static function onStaticCall(Closure $callback): void
public static function onStaticCall(callable $callback): void
{
static::$onStaticCall = $callback;
static::$onStaticCall = $callback(...);
}

/**
* Set the logic to run when an inaccessible case method is called.
*
* @param Closure(object $case, string $name, array<array-key, mixed> $arguments): mixed $callback
* @param callable(object $case, string $name, array<array-key, mixed> $arguments): mixed $callback
*/
public static function onCall(Closure $callback): void
public static function onCall(callable $callback): void
{
static::$onCall = $callback;
static::$onCall = $callback(...);
}

/**
* Set the logic to run when a case is invoked.
*
* @param Closure(object $case, mixed ...$arguments): mixed $callback
* @param callable(object $case, mixed ...$arguments): mixed $callback
*/
public static function onInvoke(Closure $callback): void
public static function onInvoke(callable $callback): void
{
static::$onInvoke = $callback;
static::$onInvoke = $callback(...);
}

/**
Expand Down
8 changes: 8 additions & 0 deletions tests/BackedEnumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Cerbero\Enum\CasesCollection;
use Cerbero\Enum\BackedEnum;
use Cerbero\Enum\Enums;
use Cerbero\Enum\PureEnum;
use Pest\Expectation;

it('determines whether the enum is pure')
Expand All @@ -13,6 +14,13 @@
->expect(BackedEnum::isBacked())
->toBeTrue();

it('determines whether the enum is backed by integer or string', function() {
expect(BackedEnum::isBackedByInteger())->toBeTrue();
expect(BackedEnum::isBackedByString())->toBeFalse();
expect(PureEnum::isBackedByInteger())->toBeFalse();
expect(PureEnum::isBackedByString())->toBeFalse();
});

it('retrieves all the names of the cases')
->expect(BackedEnum::names())
->toBe(['one', 'two', 'three']);
Expand Down
30 changes: 30 additions & 0 deletions tests/CasesCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,41 @@
use Cerbero\Enum\PureEnum;
use Pest\Expectation;

it('turns into a JSON with pure cases', function() {
expect((string) new CasesCollection(PureEnum::cases()))
->toBe('["one","two","three"]');
});

it('turns into a JSON with backed cases', function() {
expect((string) new CasesCollection(BackedEnum::cases()))
->toBe('[1,2,3]');
});

it('retrieves all the cases')
->expect(new CasesCollection(PureEnum::cases()))
->all()
->toBe([PureEnum::one, PureEnum::two, PureEnum::three]);

it('determines whether a pure collection contains an item', function() {
$collection = new CasesCollection(PureEnum::cases());

expect($collection->has(PureEnum::one))->toBeTrue();
expect($collection->has('one'))->toBeTrue();
expect($collection->has(BackedEnum::one))->toBeFalse();
expect($collection->has('four'))->toBeFalse();
expect($collection->has(1))->toBeFalse();
});

it('determines whether a backed collection contains an item', function() {
$collection = new CasesCollection(BackedEnum::cases());

expect($collection->has(BackedEnum::one))->toBeTrue();
expect($collection->has(1))->toBeTrue();
expect($collection->has(PureEnum::one))->toBeFalse();
expect($collection->has(4))->toBeFalse();
expect($collection->has('one'))->toBeFalse();
});

it('retrieves the count of all the cases')
->expect(new CasesCollection(PureEnum::cases()))
->count()
Expand Down

0 comments on commit 2a05cbc

Please sign in to comment.