Skip to content

Commit 6aac342

Browse files
authored
Feature: phpstan & rector (#75)
* Add PHPDoc annotations and improve type safety * Add PHPDoc annotations and improve PHPStan configuration * Run Rector to apply Laravel-focused upgrades and improve type safety * Add generic type constraints in PHPDoc for improved type safety * Add PHPDoc annotation for `HasDrafts` mixin to improve type clarity
1 parent 9f65ff7 commit 6aac342

27 files changed

+408
-318
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
],
1919
"require": {
2020
"php": "^8.0",
21+
"driftingly/rector-laravel": "^2.1",
2122
"illuminate/contracts": "^11.0|^12.0",
2223
"spatie/laravel-package-tools": "^1.9.2"
2324
},

database/factories/PostFactory.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,26 @@
44

55
use Oddvalue\LaravelDrafts\Tests\app\Models\Post;
66

7+
/**
8+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<Post>
9+
*/
710
class PostFactory extends \Illuminate\Database\Eloquent\Factories\Factory
811
{
912
protected $model = Post::class;
1013

1114
/**
12-
* @inheritDoc
15+
* @return array<string, mixed>
16+
* @phpstan-ignore method.childReturnType
1317
*/
14-
public function definition()
18+
public function definition(): array
1519
{
1620
return [
1721
'title' => $this->faker->sentence,
1822
'is_current' => true,
1923
];
2024
}
2125

22-
public function draft()
26+
public function draft(): static
2327
{
2428
return $this->state(function () {
2529
return [
@@ -29,7 +33,7 @@ public function draft()
2933
});
3034
}
3135

32-
public function published()
36+
public function published(): static
3337
{
3438
return $this->state(function () {
3539
return [

database/factories/PostSectionFactory.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44

55
use Oddvalue\LaravelDrafts\Tests\app\Models\PostSection;
66

7+
/**
8+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<PostSection>
9+
*/
710
class PostSectionFactory extends \Illuminate\Database\Eloquent\Factories\Factory
811
{
912
protected $model = PostSection::class;
1013

1114
/**
12-
* @inheritDoc
15+
* @return array<string, mixed>
16+
* @phpstan-ignore method.childReturnType
1317
*/
14-
public function definition()
18+
public function definition(): array
1519
{
1620
return [
1721
'content' => $this->faker->paragraph,

database/factories/SoftDeletingPostFactory.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ class SoftDeletingPostFactory extends PostFactory
99
protected $model = SoftDeletingPost::class;
1010

1111
/**
12-
* @inheritDoc
12+
* @return array<string, mixed>
1313
*/
14-
public function definition()
14+
public function definition(): array
1515
{
1616
return [
1717
'title' => $this->faker->sentence,
1818
];
1919
}
2020

21-
public function draft()
21+
public function draft(): static
2222
{
2323
return $this->state(function () {
2424
return [
@@ -28,7 +28,7 @@ public function draft()
2828
});
2929
}
3030

31-
public function published()
31+
public function published(): static
3232
{
3333
return $this->state(function () {
3434
return [

database/factories/TagFactory.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44

55
use Oddvalue\LaravelDrafts\Tests\app\Models\Tag;
66

7+
/**
8+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<Tag>
9+
*/
710
class TagFactory extends \Illuminate\Database\Eloquent\Factories\Factory
811
{
912
protected $model = Tag::class;
1013

1114
/**
12-
* @inheritDoc
15+
* @return array<string, mixed>
16+
* @phpstan-ignore method.childReturnType
1317
*/
14-
public function definition()
18+
public function definition(): array
1519
{
1620
return [
1721
'name' => $this->faker->word(),

phpstan-baseline.neon

Lines changed: 0 additions & 193 deletions
This file was deleted.

phpstan.neon.dist

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
includes:
2-
- phpstan-baseline.neon
3-
41
parameters:
5-
level: 4
2+
level: 10
63
paths:
74
- src
85
- config
@@ -11,3 +8,77 @@ parameters:
118
tmpDir: build/phpstan
129
checkOctaneCompatibility: true
1310
checkModelProperties: true
11+
ignoreErrors:
12+
# Trait method calls in closures - PHPStan doesn't recognize trait methods on $model parameter
13+
-
14+
message: '#Call to an undefined method Illuminate\\Database\\Eloquent\\Model::(getIsCurrentColumn|setPublisher|generateUuid|getIsPublishedColumn|publish|newRevision|setLive|revisions|getUuidColumn|isCurrent|drafts|getQualifiedIsPublishedColumn)\(\)#'
15+
paths:
16+
- src/Concerns/*.php
17+
- src/Scopes/*.php
18+
reportUnmatched: false
19+
# Method chaining on dynamic relations
20+
-
21+
message: '#Cannot call method (current|excludeRevision|withDrafts|withoutCurrent|onlyDrafts|published|merge|pluck|take|whereNotIn|delete|get|each|sync|create|getAttributes|getDraftableAttributes|where|first|replicate) on mixed#'
22+
paths:
23+
- src/Concerns/*.php
24+
reportUnmatched: false
25+
# Access to undefined constants in trait context
26+
-
27+
message: '#Access to undefined constant#'
28+
paths:
29+
- src/Concerns/*.php
30+
reportUnmatched: false
31+
# Method return types in trait context
32+
-
33+
message: '#Method Oddvalue\\LaravelDrafts\\Tests\\app\\Models\\[A-Za-z]+::[a-zA-Z]+\(\) (should return|return type)#'
34+
paths:
35+
- src/Concerns/*.php
36+
reportUnmatched: false
37+
# HasFactory generic type - these models define factory types via newFactory() method
38+
-
39+
message: '#Class Oddvalue\\LaravelDrafts\\Tests\\app\\Models\\[A-Za-z]+ uses generic trait Illuminate\\Database\\Eloquent\\Factories\\HasFactory but does not specify its types: TFactory#'
40+
paths:
41+
- tests/app/Models/*.php
42+
reportUnmatched: false
43+
# ArrayShape attribute
44+
-
45+
message: '#Attribute class JetBrains\\PhpStorm\\ArrayShape does not exist#'
46+
paths:
47+
- src/Concerns/*.php
48+
reportUnmatched: false
49+
# Argument type issues in trait context
50+
-
51+
message: '#Parameter .* expects .*, (mixed|array|Closure\|string|class-string\|object) given#'
52+
paths:
53+
- src/Concerns/*.php
54+
reportUnmatched: false
55+
# Method not found errors in Scopes
56+
-
57+
message: '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder::(withDrafts|withoutDrafts)#'
58+
paths:
59+
- src/Scopes/*.php
60+
reportUnmatched: false
61+
# withoutGlobalScope argument type in macros
62+
-
63+
message: '#Parameter \#1 \$scope of method Illuminate\\Database\\Eloquent\\Builder.*::withoutGlobalScope\(\) expects.*Illuminate\\Database\\Eloquent\\Builder.*given#'
64+
paths:
65+
- src/Scopes/*.php
66+
reportUnmatched: false
67+
# HasMany relation methods
68+
-
69+
message: '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany.*::(withDrafts|onlyDrafts|published)\(\)#'
70+
paths:
71+
- src/Concerns/*.php
72+
reportUnmatched: false
73+
# array_map callback type
74+
-
75+
message: '#Parameter \#1 \$callback of function array_map expects#'
76+
paths:
77+
- src/Concerns/*.php
78+
reportUnmatched: false
79+
# where() argument types in scopes
80+
-
81+
message: '#Parameter \#1 \$column of method Illuminate\\Database\\Eloquent\\Builder.*::where\(\) expects#'
82+
paths:
83+
- src/Scopes/*.php
84+
reportUnmatched: false

0 commit comments

Comments
 (0)