From 41b423da383653978b85b914a5f347c1d0500d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Sun, 20 Feb 2022 20:58:57 +0100 Subject: [PATCH] initial --- .github/workflows/ci.yml | 3 -- README.md | 72 ++++++++++++++++++++++----- composer.json | 25 ++++------ docker-compose.yml | 12 ----- src/Exceptions/UndefinedCaseError.php | 16 ++++++ src/InvokableCases.php | 28 +++++++++++ src/REPLACEServiceProvider.php | 32 ------------ tests/Pest.php | 2 +- tests/Pest/EnumTest.php | 28 +++++++++++ tests/Pest/ExampleTest.php | 9 ---- tests/TestCase.php | 10 +--- 11 files changed, 146 insertions(+), 91 deletions(-) delete mode 100644 docker-compose.yml create mode 100644 src/Exceptions/UndefinedCaseError.php create mode 100644 src/InvokableCases.php delete mode 100644 src/REPLACEServiceProvider.php create mode 100644 tests/Pest/EnumTest.php delete mode 100644 tests/Pest/ExampleTest.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f60a40..33a7079 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,6 @@ name: CI env: COMPOSE_INTERACTIVE_NO_CLI: 1 PHP_CS_FIXER_IGNORE_ENV: 1 - MYSQL_PORT: 3307 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} on: @@ -21,8 +20,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Start docker containers - run: docker-compose up -d - name: Install composer dependencies run: composer require "illuminate/support:^${{ matrix.laravel }}.0" - name: Run tests diff --git a/README.md b/README.md index d390b5e..e4b8922 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,75 @@ -# REPLACE +# Enums -Simple and flexible package template. Supports Laravel 8 and 9. +A collection\* of enum helpers for PHP. -# Usage +\* Currently there's only one helper — [`InvokableCases`](#invokablecases) — but the goal of the package is to provide general purpose enum helpers. -- Replace all occurances of `REPLACE` (case sensitive) with the name of the package namespace. E.g. the `Foo` in `ArchTech\Foo`. - - Also do this for file names, e.g. `REPLACEServiceProvider.php`. -- Replace all occurances of `replace` with the name of the package on composer, e.g. the `bar` in `archtechx/bar`. -- If MySQL is not needed, remove `docker-compose.yml`, remove the line that runs docker from `./check`, and remove it from the `.github/ci.yml` file. - - If SQLite is wanted, change `DB_CONNECTION` in `phpunit.xml` to `sqlite`, and `DB_DATABASE` to `:memory:`. - ---- +You can read more about the idea on [Twitter](https://twitter.com/archtechx/status/1495158228757270528). I originally wanted to include that helper in [`archtechx/helpers`](https://github.com/archtechx/helpers), but it makes more sense to make this a separate dependency and use it *inside* the other package. ## Installation +Laravel 8 or 9 are required. PHP 8.1+ is required. + ```sh -composer require archtechx/replace +composer require archtechx/enums ``` ## Usage +### InvokableCases + +This helper lets you get the value of a backed enum by "invoking it" — either statically (`MyEnum::FOO()` instead of `MyEnum::FOO`), or as an instance (`$enum()`). + +That way, you can use enums as array keys: ```php -// ... +'statuses' => [ + TaskStatus::INCOMPLETE() => ['some configuration'], + TaskStatus::COMPLETED() => ['some configuration'], +], +``` + +Or just the underlying primitives for any other use cases: +```php +public function updateStatus(int $status): void; + +$task->updateStatus(TaskStatus::COMPLETED()); +``` + +Without [having to append](https://twitter.com/archtechx/status/1495158237137494019) `->value` to everything. + +This approach also has *decent* IDE support. You get autosuggestions while typing, and then you just append `()`: +```php +MyEnum::FOO; // => MyEnum instance +MyEnum::FOO(); // => 1 +``` + +#### Apply the trait on your enum +```php +use ArchTech\Enums\InvokableCases; + +enum TaskStatus: int +{ + use InvokableCases; + + case INCOMPLETE = 0; + case COMPLETED = 1; + case CANCELED = 2; +} +``` + +#### Use static calls to get the primitive value +```php +TaskStatus::INCOMPLETE(); // 0 +TaskStatus::COMPLETED(); // 1 +TaskStatus::CANCELED(); // 2 +``` + +#### Invoke instances to get the primitive value +```php +public function updateStatus(TaskStatus $status) +{ + $this->record->setStatus($status()); +} ``` ## Development diff --git a/composer.json b/composer.json index 8a685e0..57f1d2d 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { - "name": "archtechx/replace", - "description": "", + "name": "archtechx/enums", + "description": "Helpers that make PHP enums more lovable", "type": "library", "license": "MIT", "authors": [ @@ -11,17 +11,16 @@ ], "autoload": { "psr-4": { - "ArchTech\\REPLACE\\": "src/" + "ArchTech\\Enums\\": "src/" } }, "autoload-dev": { "psr-4": { - "ArchTech\\REPLACE\\Tests\\": "tests/" + "ArchTech\\Enums\\Tests\\": "tests/" } }, "require": { - "php": "^8.0", - "illuminate/support": "^8.24|^9.0" + "php": "^8.1" }, "require-dev": { "orchestra/testbench": "^6.9|^7.0", @@ -29,13 +28,11 @@ "pestphp/pest": "^1.2", "pestphp/pest-plugin-laravel": "^1.0" }, - "extra": { - "laravel": { - "providers": [ - "ArchTech\\REPLACE\\PackageServiceProvider" - ] - } - }, "minimum-stability": "dev", - "prefer-stable": true + "prefer-stable": true, + "config": { + "allow-plugins": { + "pestphp/pest-plugin": true + } + } } diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 45edba6..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: '3' -services: - mysql: - image: mysql:5.7 - environment: - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: main - MYSQL_USER: user - MYSQL_PASSWORD: password - MYSQL_TCP_PORT: ${MYSQL_PORT} - ports: - - "${MYSQL_PORT}:${MYSQL_PORT}" diff --git a/src/Exceptions/UndefinedCaseError.php b/src/Exceptions/UndefinedCaseError.php new file mode 100644 index 0000000..9d37551 --- /dev/null +++ b/src/Exceptions/UndefinedCaseError.php @@ -0,0 +1,16 @@ +value; + } + + /** Return the enum's value when it's called ::STATICALLY(). */ + public static function __callStatic($name, $args) + { + $cases = static::cases(); + + foreach ($cases as $case) { + if ($case->name === $name) { + return $case->value; + } + } + + throw new Exceptions\UndefinedCaseError(static::class, $name); + } +} diff --git a/src/REPLACEServiceProvider.php b/src/REPLACEServiceProvider.php deleted file mode 100644 index c819ff7..0000000 --- a/src/REPLACEServiceProvider.php +++ /dev/null @@ -1,32 +0,0 @@ -loadViewsFrom(__DIR__ . '/../assets/views', 'replace'); - - // $this->publishes([ - // __DIR__ . '/../assets/views' => resource_path('views/vendor/replace'), - // ], 'replace-views'); - - // $this->mergeConfigFrom( - // __DIR__ . '/../assets/replace.php', - // 'replace' - // ); - - // $this->publishes([ - // __DIR__ . '/../assets/replace.php' => config_path('replace.php'), - // ], 'replace-config'); - } -} diff --git a/tests/Pest.php b/tests/Pest.php index 9103936..68220b0 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -11,7 +11,7 @@ | */ -uses(ArchTech\REPLACE\Tests\TestCase::class)->in('Pest'); +uses(ArchTech\Enums\Tests\TestCase::class)->in('Pest'); /* |-------------------------------------------------------------------------- diff --git a/tests/Pest/EnumTest.php b/tests/Pest/EnumTest.php new file mode 100644 index 0000000..27b03d5 --- /dev/null +++ b/tests/Pest/EnumTest.php @@ -0,0 +1,28 @@ +toBe(0); + expect(Status::DONE())->toBe(1); +}); + +it('can be invoked as an instance', function () { + $status = Status::PENDING; + + expect($status())->toBe(0); + expect($status())->toBe($status->value); +}); + +it('throws an error when a nonexistent case is being used', function () { + Status::INVALID(); +})->expectException(UndefinedCaseError::class); + +enum Status: int +{ + use InvokableCases; + + case PENDING = 0; + case DONE = 1; +} diff --git a/tests/Pest/ExampleTest.php b/tests/Pest/ExampleTest.php deleted file mode 100644 index 5d10dd3..0000000 --- a/tests/Pest/ExampleTest.php +++ /dev/null @@ -1,9 +0,0 @@ -toBeTrue(); -}); - -it('fails', function () { - expect(false)->toBeTrue(); -}); diff --git a/tests/TestCase.php b/tests/TestCase.php index ee3c5db..bb466c9 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,16 +1,10 @@