Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ jobs:
- name: Lint PHP files
run: find src/ tests/ -name "*.php" -exec php -l {} \;

- name: Execute PHPUnit
run: vendor/bin/phpunit
- name: Execute Pest
run: vendor/bin/pest
if: ${{ !env.CC_TOKEN || (matrix.stability != 'prefer-stable' && matrix.php != '8.2') }}

- name: Execute PHPUnit for codeclimate
run: vendor/bin/phpunit --coverage-clover=coverage.xml
- name: Execute Pest for codeclimate
run: vendor/bin/pest --coverage-clover=coverage.xml
if: ${{ env.CC_TOKEN && matrix.stability == 'prefer-stable' && matrix.php == '8.2' }}

- name: Upload coverage to codeclimate
Expand Down
20 changes: 10 additions & 10 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,12 @@
"php": "^8.1"
},
"require-dev": {
"composer/composer": "^2.5",
"composer/composer": "2.8.9",
"henzeb/enumhancer-ide-helper": "main-dev",
"larastan/larastan": "^2.11",
"mockery/mockery": "^1.5",
"orchestra/testbench": "^v7.18|^8.0|^9",
"phpstan/phpstan": "^1.9|^2",
"phpunit/phpunit": "^10|^11"
"orchestra/testbench": "^8|^9|^10",
"pestphp/pest": "^2.0|^3.0",
"phpstan/phpstan": "^2.0"
},
"autoload": {
"files": [
Expand All @@ -92,15 +91,16 @@
}
},
"scripts": {
"test": "vendor/bin/phpunit",
"test-coverage-txt": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text",
"test-coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html coverage",
"test-dox": "vendor/bin/phpunit --testdox"
"test": "vendor/bin/pest",
"test-coverage-txt": "XDEBUG_MODE=coverage vendor/bin/pest --coverage --coverage-text",
"test-coverage": "XDEBUG_MODE=coverage vendor/bin/pest --coverage --coverage-html coverage",
"test-dox": "vendor/bin/pest --testdox"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"infection/extension-installer": true
"infection/extension-installer": true,
"pestphp/pest-plugin": true
}
},
"extra": {
Expand Down
6 changes: 3 additions & 3 deletions src/PHPStan/Constants/BitmaskConstantAlwaysUsed.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
namespace Henzeb\Enumhancer\PHPStan\Constants;

use Henzeb\Enumhancer\Helpers\EnumImplements;
use PHPStan\Reflection\ConstantReflection;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtension;

class BitmaskConstantAlwaysUsed implements AlwaysUsedClassConstantsExtension
{

public function isAlwaysUsed(ConstantReflection $constant): bool
public function isAlwaysUsed(ClassConstantReflection $constant): bool
{
if ($constant->getName() !== \strtolower('bit_values')) {
if (\strtolower($constant->getName()) !== 'bit_values') {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class BitmaskModifierConstantAlwaysUsed implements AlwaysUsedClassConstantsExten

public function isAlwaysUsed(ConstantReflection $constant): bool
{
if ($constant->getName() !== strtolower('bit_modifier')) {
if (strtolower($constant->getName()) !== 'bit_modifier') {
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/PHPStan/Constants/DefaultConstantAlwaysUsed.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
namespace Henzeb\Enumhancer\PHPStan\Constants;

use Henzeb\Enumhancer\Helpers\EnumImplements;
use PHPStan\Reflection\ConstantReflection;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtension;

class DefaultConstantAlwaysUsed implements AlwaysUsedClassConstantsExtension
{
public function isAlwaysUsed(ConstantReflection $constant): bool
public function isAlwaysUsed(ClassConstantReflection $constant): bool
{
$constantName = $constant->getName();

Expand Down
4 changes: 2 additions & 2 deletions src/PHPStan/Constants/MapperConstantAlwaysUsed.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
namespace Henzeb\Enumhancer\PHPStan\Constants;

use Henzeb\Enumhancer\Helpers\EnumImplements;
use PHPStan\Reflection\ConstantReflection;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtension;
use function str_starts_with;
use function strtolower;

class MapperConstantAlwaysUsed implements AlwaysUsedClassConstantsExtension
{
public function isAlwaysUsed(ConstantReflection $constant): bool
public function isAlwaysUsed(ClassConstantReflection $constant): bool
{
$class = $constant->getDeclaringClass();

Expand Down
25 changes: 15 additions & 10 deletions src/PHPStan/Constants/Rules/DefaultConstantRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\Enum\EnumCaseObjectType;
use ReflectionException;

Expand Down Expand Up @@ -56,21 +57,25 @@ protected function validate(?ClassReflection $reflectedClass, string $constantNa

if ($implementsDefault && !$valueFromEnum) {
$return = [
sprintf(
'Enumhancer: enum is implementing `Defaults`, '
. 'but constant `%s` is not referencing to one of its own cases.',
$constantName
)
RuleErrorBuilder::message(
sprintf(
'Enumhancer: enum is implementing `Defaults`, '
. 'but constant `%s` is not referencing to one of its own cases.',
$constantName
)
)->build()
];
}

if (!$implementsDefault && $valueFromEnum) {
$return = [
sprintf(
'Enumhancer: Constant `%s` is not going to be used, '
. 'because enum is not implementing `Defaults`',
$constantName
)
RuleErrorBuilder::message(
sprintf(
'Enumhancer: Constant `%s` is not going to be used, '
. 'because enum is not implementing `Defaults`',
$constantName
)
)->build()
];
}

Expand Down
29 changes: 19 additions & 10 deletions src/PHPStan/Constants/Rules/MapperConstantRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use PHPStan\Reflection\MissingConstantFromReflectionException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantStringType;
use function strtolower;
Expand Down Expand Up @@ -67,19 +68,23 @@ protected function validate(?ClassReflection $class, string $constantName): arra

if (!$implementsMappers && $isValid) {
$return = [
sprintf(
'Enumhancer: `%s` is not going to be used because enum is not implementing `Mappers`',
$constantName,
)
RuleErrorBuilder::message(
sprintf(
'Enumhancer: `%s` is not going to be used because enum is not implementing `Mappers`',
$constantName,
)
)->build()
];
}

if ($implementsMappers && !$isValid) {
$return = [
sprintf(
'Enumhancer: The specified `%s` map is invalid',
$constantName,
)
RuleErrorBuilder::message(
sprintf(
'Enumhancer: The specified `%s` map is invalid',
$constantName,
)
)->build()
];
}

Expand All @@ -99,8 +104,12 @@ protected function isValidValue(

if ($valueType instanceof ConstantStringType) {
$class = $valueType->getValue();
$isValid = $valueType->isClassStringType()->yes()
&& $this->reflectionProvider->getClass($class)->isSubclassOf(Mapper::class);
try {
$classReflection = $this->reflectionProvider->getClass($class);
$isValid = $classReflection->isSubclassOf(Mapper::class);
} catch (\PHPStan\Broker\ClassNotFoundException) {
$isValid = false;
}
}

return $isValid;
Expand Down
5 changes: 4 additions & 1 deletion src/PHPStan/Constants/Rules/StrictConstantRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Node\ClassConstantsNode;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;

/**
* @phpstan-implements Rule<ClassConstantsNode>
Expand Down Expand Up @@ -35,7 +36,9 @@ public function processNode(Node $node, Scope $scope): array

if ($class->getConstant($constantName)->getValueType()->isBoolean()->no()) {
return [
sprintf('Enumhancer: constant `%s` should be a boolean.', $constantName)
RuleErrorBuilder::message(
sprintf('Enumhancer: constant `%s` should be a boolean.', $constantName)
)->build()
];
}

Expand Down
4 changes: 2 additions & 2 deletions src/PHPStan/Constants/StrictConstantAlwaysUsed.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
namespace Henzeb\Enumhancer\PHPStan\Constants;

use Henzeb\Enumhancer\Helpers\EnumImplements;
use PHPStan\Reflection\ConstantReflection;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtension;

class StrictConstantAlwaysUsed implements AlwaysUsedClassConstantsExtension
{

public function isAlwaysUsed(ConstantReflection $constant): bool
public function isAlwaysUsed(ClassConstantReflection $constant): bool
{
if (\strtolower($constant->getName()) !== 'strict') {
return false;
Expand Down
18 changes: 18 additions & 0 deletions tests/Fixtures/Models/CastsBasicEnumsNoPropertyModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Henzeb\Enumhancer\Tests\Fixtures\Models;

use Illuminate\Database\Eloquent\Model;
use Henzeb\Enumhancer\Tests\Fixtures\SubsetUnitEnum;
use Henzeb\Enumhancer\Laravel\Concerns\CastsBasicEnumerations;

class CastsBasicEnumsNoPropertyModel extends Model
{
use CastsBasicEnumerations;

// No keepEnumCase property - this will test the property_exists fallback

protected $casts = [
'unitEnum' => SubsetUnitEnum::class,
];
}
29 changes: 29 additions & 0 deletions tests/Pest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
|--------------------------------------------------------------------------
| Test Case
|--------------------------------------------------------------------------
|
| The closure you provide to your test functions is always bound to a specific PHPUnit test
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
| need to change it using the "pest()" function to bind a different classes or traits.
|
*/

use PHPUnit\Framework\TestCase;

ini_set('memory_limit', '512M');
uses(TestCase::class)->in('Unit');

/*
|--------------------------------------------------------------------------
| Expectations
|--------------------------------------------------------------------------
|
| When you're writing tests, you often need to check that values meet certain conditions. The
| "expect()" function gives you access to a set of "expectations" methods that you can use
| to assert different things. Of course, you may extend the Expectation API at any time.
|
*/

72 changes: 72 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Henzeb\Enumhancer\Tests;

use Henzeb\Enumhancer\Helpers\EnumReporter;
use Henzeb\Enumhancer\Laravel\Providers\EnumhancerServiceProvider;
use Henzeb\Enumhancer\Tests\Fixtures\EnhancedBackedEnum;
use Henzeb\Enumhancer\Tests\Fixtures\EnhancedIntBackedEnum;
use Henzeb\Enumhancer\Tests\Fixtures\SimpleEnum;
use Henzeb\Enumhancer\Tests\Fixtures\UnitEnums\Defaults\DefaultsEnum;

class TestCase extends \Orchestra\Testbench\TestCase
{
protected function setUp(): void
{
EnumReporter::set(null);
parent::setUp();
}

protected function getPackageProviders($app)
{
return [EnumhancerServiceProvider::class];
}

protected function defineRoutes($router)
{
// For SubstituteEnumsTest
$router->middleware('api')->get('/simpleapi/{status}',
function (SimpleEnum $status) {
test()->assertEquals(SimpleEnum::Open, $status);
}
);
}

protected function defineWebRoutes($router)
{
// For SubstituteEnumsTest
$router->get('/noparams',
function () {
return null;
}
);

$router->get('/backed/{status}',
function (EnhancedBackedEnum $status) {
return $status->name;
}
);

$router->get('/intbacked/{status}',
function (EnhancedIntBackedEnum $status) {
}
);

$router->get('/simple/{status}',
function (SimpleEnum $status) {
}
);

$router->get('/optional/{status?}',
function (SimpleEnum|null $status = null) {
return $status?->name;
}
);

$router->get('/default/{status?}',
function (DefaultsEnum $status) {
test()->assertEquals(DefaultsEnum::Default, $status);
}
);
}
}
Loading