diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d5d9251..a76485f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,8 @@ jobs: strategy: matrix: include: + - php: 8.4 + laravel: ^11.0 - php: 8.3 laravel: ^11.0 - php: 8.2 diff --git a/composer.json b/composer.json index deffd7b..f37357e 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,9 @@ }, "require-dev": { "orchestra/testbench": ">=6.15", - "squizlabs/php_codesniffer": "^3.5", - "phpunit/phpunit": "<11" + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "<11", + "squizlabs/php_codesniffer": "^3.5" }, "autoload": { "psr-4": { @@ -32,6 +33,7 @@ "test": "./vendor/bin/phpunit --no-coverage", "phpsniff": "vendor/bin/phpcs --standard=\"PSR12\" ./src --ignore=./src/resources/*", "phpfix": "vendor/bin/phpcbf --standard=\"PSR12\" ./src --ignore=./src/resources/*", + "phpstan": "./vendor/bin/phpstan", "post-autoload-dump": [ "@php ./vendor/bin/testbench package:discover --ansi" ] diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..f5821d4 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,6 @@ +parameters: + level: 8 + paths: + - src + ignoreErrors: + - identifier: missingType.generics diff --git a/src/AmpersandServiceProvider.php b/src/AmpersandServiceProvider.php index 94437c3..e7f408a 100644 --- a/src/AmpersandServiceProvider.php +++ b/src/AmpersandServiceProvider.php @@ -12,7 +12,7 @@ class AmpersandServiceProvider extends ServiceProvider { - public function boot() + public function boot(): void { if ($this->app->runningInConsole()) { $this->publishes([ @@ -24,7 +24,7 @@ public function boot() } } - public function register() + public function register(): void { $this->setup(); $this->registerRepositories(); @@ -33,20 +33,20 @@ public function register() $this->app->register(RouteServiceProvider::class); } - private function setup() + private function setup(): void { $this->loadViewsFrom(__DIR__ . '/resources/views', 'ampersand'); $this->mergeConfigFrom(__DIR__ . '/config/ampersand.php', 'ampersand'); // Add a disk to the filesystem - $this->app['config']->set('filesystems.disks.ampersand::posts', [ + config()->set('filesystems.disks.ampersand::posts', [ 'driver' => 'local', 'root' => config('ampersand.posts_path') ]); // Overload sheets config to avoid local conflicts - $this->app['config']->set('sheets.collections', [ + config()->set('sheets.collections', [ 'posts' => [ 'disk' => 'ampersand::posts', 'sheet_class' => Post::class, @@ -57,12 +57,12 @@ private function setup() ]); } - private function registerRepositories() + private function registerRepositories(): void { $this->app->singleton(PostRepository::class); } - private function registerCommands() + private function registerCommands(): void { $this->commands([ NewPost::class diff --git a/src/Commands/NewPost.php b/src/Commands/NewPost.php index ed2c320..ed4b795 100644 --- a/src/Commands/NewPost.php +++ b/src/Commands/NewPost.php @@ -20,7 +20,7 @@ public function handle(): void $file = sprintf('%s.%s.md', $date->format('Y-m-d'), Str::slug($title)); $content = file_get_contents(__DIR__ . '/../resources/stubs/post.md'); - $content = Str::of($content)->replace('%title%', $title) + $content = Str::of((string) $content)->replace('%title%', $title) ->replace('%date%', $date); $directory = config('ampersand.posts_path'); diff --git a/src/Http/Controllers/PostController.php b/src/Http/Controllers/PostController.php index c307dc1..f96d491 100644 --- a/src/Http/Controllers/PostController.php +++ b/src/Http/Controllers/PostController.php @@ -2,6 +2,7 @@ namespace Olssonm\Ampersand\Http\Controllers; +use Illuminate\Http\Response; use Olssonm\Ampersand\Models\Post; use Olssonm\Ampersand\Repositories\PostRepository; @@ -14,9 +15,9 @@ public function __construct(PostRepository $postRepository) $this->postRepository = $postRepository; } - public function index() + public function index(): Response { - return view('ampersand::index', [ + return response()->view('ampersand::index', [ 'posts' => $this->postRepository->paginate( config('ampersand.per_page'), config('ampersand.page_indicator'), @@ -24,9 +25,9 @@ public function index() ]); } - public function show(Post $post) + public function show(Post $post): Response { - return view('ampersand::show', [ + return response()->view('ampersand::show', [ 'post' => $post ]); } diff --git a/src/Models/Post.php b/src/Models/Post.php index 5e7ddf2..258ae6c 100644 --- a/src/Models/Post.php +++ b/src/Models/Post.php @@ -2,10 +2,15 @@ namespace Olssonm\Ampersand\Models; +use AllowDynamicProperties; use Carbon\Carbon; use Olssonm\Ampersand\Repositories\PostRepository; use Olssonm\Ampersand\Services\Model; +/** + * @property string $slug + */ +#[AllowDynamicProperties] class Post extends Model { public function getRouteKey(): string @@ -28,8 +33,10 @@ public function getDateAttribute(): Carbon return Carbon::parse($this->attributes['date']); } - public static function __callStatic($name, $arguments) + /** @phpstan-ignore-next-line */ + public static function __callStatic(string $name, array $arguments): mixed { + /** @phpstan-ignore-next-line */ return call_user_func_array([app(PostRepository::class), $name], $arguments); } } diff --git a/src/Repositories/PostRepository.php b/src/Repositories/PostRepository.php index 9c3e2b6..bbeae59 100644 --- a/src/Repositories/PostRepository.php +++ b/src/Repositories/PostRepository.php @@ -20,12 +20,13 @@ public function find(string $slug): Post { $post = $this->all()->where('slug', $slug)->first(); + /** @phpstan-ignore argument.type */ throw_if(!$post, (new ModelNotFoundException())->setModel(Post::class, $slug)); return $post; } - public function paginate($perPage = 10, $pageName = 'page'): LengthAwarePaginator + public function paginate(int $perPage = 10, string $pageName = 'page'): LengthAwarePaginator { $page = LengthAwarePaginator::resolveCurrentPage($pageName, 1); diff --git a/src/Services/Model.php b/src/Services/Model.php index a3a160d..0e91665 100644 --- a/src/Services/Model.php +++ b/src/Services/Model.php @@ -9,10 +9,12 @@ abstract class Model extends Sheet implements UrlRoutable { + /** @phpstan-ignore return.missing */ public function resolveRouteBinding($value, $field = null) { } + /** @phpstan-ignore return.missing */ public function resolveChildRouteBinding($childType, $value, $field) { }