Repository: barryvdh/laravel-ide-helper (php)

Issue:
Default values as enums cases
### Versions:
- ide-helper Version: 2.12.3
- Laravel Version: 10.19.0
- PHP Version: 8.2.8

### Description:

In case we want to add a default value using an enum typed argument on a model query scope like so:

```php
<?php

class MyModel extends Model
{
    public function scopeHasAbility(Builder $query, Authenticatable $user, ?CrudAction $ability = CrudAction::Read)
    {
        // code here...
    }
}
```

This will run fine in PHP 8+ but IDE helper models docblock generator command will complain with the following error:

![image](https://github.com/barryvdh/laravel-ide-helper/assets/2331052/52e1552e-f432-4df3-885e-0f90bb367f20)

Error comes from this line: https://github.com/barryvdh/laravel-ide-helper/blob/0801d002e48d7ead2b0a0169c04f44f72800738a/src/Console/ModelsCommand.php#L1103

### Steps To Reproduce:

- Add code from description
- Run `php artisan ide-helper:models -w`


Pull request:
Add support for enum default arguments using enum cases
## Summary

Fixes #1463 

## Type of change

<!-- Please delete options that are not relevant. -->

- [x] Bug fix (non-breaking change which fixes an issue)

### Checklist
- [x] Existing tests have been adapted and/or new tests have been added
- [x] Add a CHANGELOG.md entry
- [x] Update the README.md
- [x] Code style has been fixed via `composer fix-style`


Patch:
diff --git a/.github/workflows/run-static-analysis.yml b/.github/workflows/run-static-analysis.yml
index 1085dfe..c8c29bb 100644
--- a/.github/workflows/run-static-analysis.yml
+++ b/.github/workflows/run-static-analysis.yml
@@ -17,7 +17,7 @@ jobs:
             - name: Setup PHP
               uses: shivammathur/setup-php@v2
               with:
-                php-version: 8.0
+                php-version: 8.1
                 coverage: none
                 extensions: pdo_sqlite
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 16fa904..d638d2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file.
 ### Changed
 - Removed support for Laravel 8 and therefore for PHP < 8.0 [#1504 / mfn](https://github.com/barryvdh/laravel-ide-helper/pull/1504)
 
+
+### Added
+- Add support for enum default arguments using enum cases. [#1464 / d8vjork](https://github.com/barryvdh/laravel-ide-helper/pull/1464)
+
 2024-02-05, 2.14.0
 ------------------
 
diff --git a/composer.json b/composer.json
index 537d760..18e3902 100644
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,7 @@
         "ext-json": "*",
         "barryvdh/reflection-docblock": "^2.0.6",
         "composer/class-map-generator": "^1.0",
-        "doctrine/dbal": "^2.6 || ^3",
+        "doctrine/dbal": "^2.6 || ^3.1.4",
         "illuminate/console": "^9 || ^10",
         "illuminate/filesystem": "^9 || ^10",
         "illuminate/support": "^9 || ^10",
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index f6a5b14..84de223 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -16,4 +16,9 @@
       <code>\Storage</code>
     </UndefinedClass>
   </file>
+  <file src="src/Console/ModelsCommand.php">
+    <UndefinedClass occurrences="1">
+      <code>\UnitEnum</code>
+    </UndefinedClass>
+  </file>
 </files>
diff --git a/src/Console/ModelsCommand.php b/src/Console/ModelsCommand.php
index c2ce4a6..13735c2 100644
--- a/src/Console/ModelsCommand.php
+++ b/src/Console/ModelsCommand.php
@@ -1099,6 +1099,8 @@ class ModelsCommand extends Command
                     $default = 'null';
                 } elseif (is_int($default)) {
                     //$default = $default;
+                } elseif ($default instanceof \UnitEnum) {
+                    $default = '\\' . get_class($default) . '::' . $default->name;
                 } else {
                     $default = "'" . trim($default) . "'";
                 }


Test patch:
diff --git a/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Enums/PostStatus.php b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Enums/PostStatus.php
new file mode 100644
index 0000000..afe6b9b
--- /dev/null
+++ b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Enums/PostStatus.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums;
+
+enum PostStatus
+{
+    case Published;
+
+    case Unpublished;
+
+    case Archived;
+}
\ No newline at end of file
diff --git a/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Models/Post.php b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Models/Post.php
new file mode 100644
index 0000000..58318ec
--- /dev/null
+++ b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Models/Post.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Models;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Builder;
+use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus;
+
+class Post extends Model
+{
+    public function scopeHasStatus(Builder $query, ?PostStatus $status = PostStatus::Published)
+    {
+        // 
+    }
+}
diff --git a/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Test.php b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Test.php
new file mode 100644
index 0000000..0eb640d
--- /dev/null
+++ b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/Test.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults;
+
+use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
+use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
+
+class Test extends AbstractModelsCommand
+{
+    public function test(): void
+    {
+        if (!version_compare(PHP_VERSION, '8.1', '>=')) {
+            $this->markTestSkipped(
+                'This test only works in PHP >= 8.1'
+            );
+        }
+
+        $command = $this->app->make(ModelsCommand::class);
+
+        $tester = $this->runCommand($command, [
+            '--write' => true,
+        ]);
+
+        $this->assertSame(0, $tester->getStatusCode());
+        $this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
+        $this->assertMatchesMockedSnapshot();
+    }
+}
diff --git a/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/__snapshots__/Test__test__1.php b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/__snapshots__/Test__test__1.php
new file mode 100644
index 0000000..b4229da
--- /dev/null
+++ b/tests/Console/ModelsCommand/GenerateBasicPhpDocWithEnumDefaults/__snapshots__/Test__test__1.php
@@ -0,0 +1,172 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Models;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Builder;
+use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus;
+
+/**
+ * Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Models\Post
+ *
+ * @property integer $id
+ * @property string|null $char_nullable
+ * @property string $char_not_nullable
+ * @property string|null $string_nullable
+ * @property string $string_not_nullable
+ * @property string|null $text_nullable
+ * @property string $text_not_nullable
+ * @property string|null $medium_text_nullable
+ * @property string $medium_text_not_nullable
+ * @property string|null $long_text_nullable
+ * @property string $long_text_not_nullable
+ * @property integer|null $integer_nullable
+ * @property integer $integer_not_nullable
+ * @property integer|null $tiny_integer_nullable
+ * @property integer $tiny_integer_not_nullable
+ * @property integer|null $small_integer_nullable
+ * @property integer $small_integer_not_nullable
+ * @property integer|null $medium_integer_nullable
+ * @property integer $medium_integer_not_nullable
+ * @property integer|null $big_integer_nullable
+ * @property integer $big_integer_not_nullable
+ * @property integer|null $unsigned_integer_nullable
+ * @property integer $unsigned_integer_not_nullable
+ * @property integer|null $unsigned_tiny_integer_nullable
+ * @property integer $unsigned_tiny_integer_not_nullable
+ * @property integer|null $unsigned_small_integer_nullable
+ * @property integer $unsigned_small_integer_not_nullable
+ * @property integer|null $unsigned_medium_integer_nullable
+ * @property integer $unsigned_medium_integer_not_nullable
+ * @property integer|null $unsigned_big_integer_nullable
+ * @property integer $unsigned_big_integer_not_nullable
+ * @property float|null $float_nullable
+ * @property float $float_not_nullable
+ * @property float|null $double_nullable
+ * @property float $double_not_nullable
+ * @property string|null $decimal_nullable
+ * @property string $decimal_not_nullable
+ * @property string|null $unsigned_decimal_nullable
+ * @property string $unsigned_decimal_not_nullable
+ * @property integer|null $boolean_nullable
+ * @property integer $boolean_not_nullable
+ * @property string|null $enum_nullable
+ * @property string $enum_not_nullable
+ * @property string|null $json_nullable
+ * @property string $json_not_nullable
+ * @property string|null $jsonb_nullable
+ * @property string $jsonb_not_nullable
+ * @property string|null $date_nullable
+ * @property string $date_not_nullable
+ * @property string|null $datetime_nullable
+ * @property string $datetime_not_nullable
+ * @property string|null $datetimetz_nullable
+ * @property string $datetimetz_not_nullable
+ * @property string|null $time_nullable
+ * @property string $time_not_nullable
+ * @property string|null $timetz_nullable
+ * @property string $timetz_not_nullable
+ * @property string|null $timestamp_nullable
+ * @property string $timestamp_not_nullable
+ * @property string|null $timestamptz_nullable
+ * @property string $timestamptz_not_nullable
+ * @property integer|null $year_nullable
+ * @property integer $year_not_nullable
+ * @property mixed|null $binary_nullable
+ * @property mixed $binary_not_nullable
+ * @property string|null $uuid_nullable
+ * @property string $uuid_not_nullable
+ * @property string|null $ipaddress_nullable
+ * @property string $ipaddress_not_nullable
+ * @property string|null $macaddress_nullable
+ * @property string $macaddress_not_nullable
+ * @property \Illuminate\Support\Carbon|null $created_at
+ * @property \Illuminate\Support\Carbon|null $updated_at
+ * @method static Builder|Post hasStatus(?\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus $status = \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus::Published)
+ * @method static Builder|Post newModelQuery()
+ * @method static Builder|Post newQuery()
+ * @method static Builder|Post query()
+ * @method static Builder|Post whereBigIntegerNotNullable($value)
+ * @method static Builder|Post whereBigIntegerNullable($value)
+ * @method static Builder|Post whereBinaryNotNullable($value)
+ * @method static Builder|Post whereBinaryNullable($value)
+ * @method static Builder|Post whereBooleanNotNullable($value)
+ * @method static Builder|Post whereBooleanNullable($value)
+ * @method static Builder|Post whereCharNotNullable($value)
+ * @method static Builder|Post whereCharNullable($value)
+ * @method static Builder|Post whereCreatedAt($value)
+ * @method static Builder|Post whereDateNotNullable($value)
+ * @method static Builder|Post whereDateNullable($value)
+ * @method static Builder|Post whereDatetimeNotNullable($value)
+ * @method static Builder|Post whereDatetimeNullable($value)
+ * @method static Builder|Post whereDatetimetzNotNullable($value)
+ * @method static Builder|Post whereDatetimetzNullable($value)
+ * @method static Builder|Post whereDecimalNotNullable($value)
+ * @method static Builder|Post whereDecimalNullable($value)
+ * @method static Builder|Post whereDoubleNotNullable($value)
+ * @method static Builder|Post whereDoubleNullable($value)
+ * @method static Builder|Post whereEnumNotNullable($value)
+ * @method static Builder|Post whereEnumNullable($value)
+ * @method static Builder|Post whereFloatNotNullable($value)
+ * @method static Builder|Post whereFloatNullable($value)
+ * @method static Builder|Post whereId($value)
+ * @method static Builder|Post whereIntegerNotNullable($value)
+ * @method static Builder|Post whereIntegerNullable($value)
+ * @method static Builder|Post whereIpaddressNotNullable($value)
+ * @method static Builder|Post whereIpaddressNullable($value)
+ * @method static Builder|Post whereJsonNotNullable($value)
+ * @method static Builder|Post whereJsonNullable($value)
+ * @method static Builder|Post whereJsonbNotNullable($value)
+ * @method static Builder|Post whereJsonbNullable($value)
+ * @method static Builder|Post whereLongTextNotNullable($value)
+ * @method static Builder|Post whereLongTextNullable($value)
+ * @method static Builder|Post whereMacaddressNotNullable($value)
+ * @method static Builder|Post whereMacaddressNullable($value)
+ * @method static Builder|Post whereMediumIntegerNotNullable($value)
+ * @method static Builder|Post whereMediumIntegerNullable($value)
+ * @method static Builder|Post whereMediumTextNotNullable($value)
+ * @method static Builder|Post whereMediumTextNullable($value)
+ * @method static Builder|Post whereSmallIntegerNotNullable($value)
+ * @method static Builder|Post whereSmallIntegerNullable($value)
+ * @method static Builder|Post whereStringNotNullable($value)
+ * @method static Builder|Post whereStringNullable($value)
+ * @method static Builder|Post whereTextNotNullable($value)
+ * @method static Builder|Post whereTextNullable($value)
+ * @method static Builder|Post whereTimeNotNullable($value)
+ * @method static Builder|Post whereTimeNullable($value)
+ * @method static Builder|Post whereTimestampNotNullable($value)
+ * @method static Builder|Post whereTimestampNullable($value)
+ * @method static Builder|Post whereTimestamptzNotNullable($value)
+ * @method static Builder|Post whereTimestamptzNullable($value)
+ * @method static Builder|Post whereTimetzNotNullable($value)
+ * @method static Builder|Post whereTimetzNullable($value)
+ * @method static Builder|Post whereTinyIntegerNotNullable($value)
+ * @method static Builder|Post whereTinyIntegerNullable($value)
+ * @method static Builder|Post whereUnsignedBigIntegerNotNullable($value)
+ * @method static Builder|Post whereUnsignedBigIntegerNullable($value)
+ * @method static Builder|Post whereUnsignedDecimalNotNullable($value)
+ * @method static Builder|Post whereUnsignedDecimalNullable($value)
+ * @method static Builder|Post whereUnsignedIntegerNotNullable($value)
+ * @method static Builder|Post whereUnsignedIntegerNullable($value)
+ * @method static Builder|Post whereUnsignedMediumIntegerNotNullable($value)
+ * @method static Builder|Post whereUnsignedMediumIntegerNullable($value)
+ * @method static Builder|Post whereUnsignedSmallIntegerNotNullable($value)
+ * @method static Builder|Post whereUnsignedSmallIntegerNullable($value)
+ * @method static Builder|Post whereUnsignedTinyIntegerNotNullable($value)
+ * @method static Builder|Post whereUnsignedTinyIntegerNullable($value)
+ * @method static Builder|Post whereUpdatedAt($value)
+ * @method static Builder|Post whereUuidNotNullable($value)
+ * @method static Builder|Post whereUuidNullable($value)
+ * @method static Builder|Post whereYearNotNullable($value)
+ * @method static Builder|Post whereYearNullable($value)
+ * @mixin \Eloquent
+ */
+class Post extends Model
+{
+    public function scopeHasStatus(Builder $query, ?PostStatus $status = PostStatus::Published)
+    {
+        // 
+    }
+}