refactor: improve code quality by importing classes, optimizing imports, and upgrading PHP version to 8.3

This commit is contained in:
Yoga Pangestu 2026-04-01 13:01:03 +07:00
parent 02464ef9b8
commit 86bc954edb
24 changed files with 123 additions and 65 deletions

View File

@ -5,6 +5,7 @@
use App\Enums\NotifStyle;
use App\Enums\Sex;
use App\Filament\Support\SystemNotification;
use App\Models\User;
use Carbon\Carbon;
use Filament\Auth\Pages\EditProfile;
use Filament\Forms\Components\DatePicker;
@ -308,7 +309,7 @@ protected function handleRecordUpdate(Model $record, array $data): Model
$record->update($data);
/** @var \App\Models\User $record */
/** @var User $record */
if ($studentData && $record->student()->exists()) {
$record->student->update($studentData);
} elseif ($studentData) {

View File

@ -4,6 +4,7 @@
use App\Filament\Support\SystemNotification;
use App\Models\AssignmentPin;
use App\Models\User;
use Filament\Actions\Action;
use Illuminate\Support\Facades\Auth;
@ -25,7 +26,7 @@ protected function setUp(): void
->tooltip(fn (array $arguments, $livewire) => in_array($arguments['record'], $livewire->pinnedIds) ? 'Lepas pin' : 'Pin tugas ini')
->action(function (array $arguments, $livewire) {
$assignmentId = $arguments['record'];
/** @var \App\Models\User|null $user */
/** @var User|null $user */
$user = Auth::user();
$studentProfile = $user?->student;

View File

@ -10,6 +10,7 @@
use App\Models\AssignmentSubmission;
use App\Models\Student;
use App\Models\StudyGroup;
use App\Models\User;
use Filament\Resources\Pages\Page;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
@ -64,7 +65,7 @@ public function statusCards(): array
#[Computed]
public function student(): Student
{
/** @var \App\Models\User|null $user */
/** @var User|null $user */
$user = Auth::user();
return $user?->student;

View File

@ -3,6 +3,7 @@
namespace App\Filament\Support;
use App\Enums\NotifStyle;
use App\Models\User;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Auth;
@ -215,7 +216,7 @@ protected static function applyStyle(Notification $notification, string $status)
public static function getNotifStyle(): NotifStyle
{
try {
/** @var \App\Models\User|null $user */
/** @var User|null $user */
$user = Auth::user();
return $user?->settings?->notif_style ?? NotifStyle::Cheerful;
@ -237,7 +238,7 @@ public static function getMessage(string $cheerful, string $formal): string
*/
public static function getThemeSettings(): object
{
/** @var \App\Models\User|null $user */
/** @var User|null $user */
$user = Auth::user();
$settings = $user?->settings;
@ -262,7 +263,7 @@ public static function getThemeSettings(): object
*/
public static function getPrimaryColorValues(): array
{
/** @var \App\Models\User|null $user */
/** @var User|null $user */
$user = Auth::user();
$colorName = $user?->settings?->primary_color ?? 'emerald';

View File

@ -2,6 +2,7 @@
namespace App\Http\Middleware;
use App\Models\User;
use Closure;
use Filament\Facades\Filament;
use Filament\Support\Colors\Color;
@ -21,7 +22,7 @@ class DynamicFilamentTheme
*/
public function handle(Request $request, Closure $next): Response
{
/** @var \App\Models\User $user */
/** @var User $user */
$user = Filament::auth()->user();
if ($user && $user->settings) {

View File

@ -4,6 +4,7 @@
use App\Enums\IsActive;
use App\Enums\NotifStyle;
use Database\Factories\UserFactory;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Database\Eloquent\Attributes\Scope;
@ -19,7 +20,7 @@
class User extends Authenticatable implements FilamentUser
{
/** @use HasFactory<\Database\Factories\UserFactory> */
/** @use HasFactory<UserFactory> */
use HasFacehashAvatar, HasFactory, HasRoles, Notifiable, SoftDeletes;
protected $guarded = ['id'];

View File

@ -1,6 +1,9 @@
<?php
use App\Providers\AppServiceProvider;
use App\Providers\Filament\AdminPanelProvider;
return [
App\Providers\AppServiceProvider::class,
App\Providers\Filament\AdminPanelProvider::class,
AppServiceProvider::class,
AdminPanelProvider::class,
];

View File

@ -6,7 +6,7 @@
"keywords": ["laravel", "framework"],
"license": "MIT",
"require": {
"php": "^8.2",
"php": "^8.3",
"achyutn/filament-log-viewer": "^2.1",
"asmit/filament-upload": "^2.0",
"bezhansalleh/filament-shield": "^4.1",

10
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "e14d9ea016573532b8ed300ea844516d",
"content-hash": "92fb103b5f9644130b3b06649f64d427",
"packages": [
{
"name": "achyutn/filament-log-viewer",
@ -13852,12 +13852,12 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": "^8.2"
"php": "^8.3"
},
"platform-dev": [],
"plugin-api-version": "2.6.0"
"platform-dev": {},
"plugin-api-version": "2.9.0"
}

View File

@ -1,5 +1,7 @@
<?php
use App\Models\User;
return [
/*
@ -62,7 +64,7 @@
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
'model' => env('AUTH_MODEL', User::class),
],
// 'users' => [

View File

@ -1,6 +1,7 @@
<?php
use Illuminate\Support\Str;
use Pdo\Mysql;
return [
@ -59,7 +60,7 @@
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
(PHP_VERSION_ID >= 80500 ? \Pdo\Mysql::ATTR_SSL_CA : \PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),
(PHP_VERSION_ID >= 80500 ? Mysql::ATTR_SSL_CA : PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
@ -79,7 +80,7 @@
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
(PHP_VERSION_ID >= 80500 ? \Pdo\Mysql::ATTR_SSL_CA : \PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),
(PHP_VERSION_ID >= 80500 ? Mysql::ATTR_SSL_CA : PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],

View File

@ -1,6 +1,10 @@
<?php
declare(strict_types=1);
use BezhanSalleh\FilamentShield\Resources\Roles\RoleResource;
use Filament\Pages\Dashboard;
use Filament\Widgets\AccountWidget;
use Filament\Widgets\FilamentInfoWidget;
return [
@ -165,7 +169,7 @@
'resources' => [
'subject' => 'model',
'manage' => [
\BezhanSalleh\FilamentShield\Resources\Roles\RoleResource::class => [
RoleResource::class => [
'viewAny',
'view',
'create',
@ -193,7 +197,7 @@
'subject' => 'class',
'prefix' => 'view',
'exclude' => [
\Filament\Pages\Dashboard::class,
Dashboard::class,
],
],
@ -212,8 +216,8 @@
'subject' => 'class',
'prefix' => 'view',
'exclude' => [
\Filament\Widgets\AccountWidget::class,
\Filament\Widgets\FilamentInfoWidget::class,
AccountWidget::class,
FilamentInfoWidget::class,
],
],

View File

@ -1,5 +1,31 @@
<?php
use App\MediaLibrary\CustomPathGenerator;
use Spatie\ImageOptimizer\Optimizers\Avifenc;
use Spatie\ImageOptimizer\Optimizers\Cwebp;
use Spatie\ImageOptimizer\Optimizers\Gifsicle;
use Spatie\ImageOptimizer\Optimizers\Jpegoptim;
use Spatie\ImageOptimizer\Optimizers\Optipng;
use Spatie\ImageOptimizer\Optimizers\Pngquant;
use Spatie\ImageOptimizer\Optimizers\Svgo;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Avif;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Image;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Svg;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Video;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Webp;
use Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob;
use Spatie\MediaLibrary\Downloaders\DefaultDownloader;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\MediaLibrary\MediaCollections\Models\Observers\MediaObserver;
use Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob;
use Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred;
use Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator;
use Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer;
use Spatie\MediaLibrary\Support\FileRemover\DefaultFileRemover;
use Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator;
use Spatie\MediaLibraryPro\Models\TemporaryUpload;
return [
/*
@ -39,12 +65,12 @@
/*
* The fully qualified class name of the media model.
*/
'media_model' => Spatie\MediaLibrary\MediaCollections\Models\Media::class,
'media_model' => Media::class,
/*
* The fully qualified class name of the media observer.
*/
'media_observer' => Spatie\MediaLibrary\MediaCollections\Models\Observers\MediaObserver::class,
'media_observer' => MediaObserver::class,
/*
* When enabled, media collections will be serialised using the default
@ -59,7 +85,7 @@
*
* This model is only used in Media Library Pro (https://medialibrary.pro)
*/
'temporary_upload_model' => Spatie\MediaLibraryPro\Models\TemporaryUpload::class,
'temporary_upload_model' => TemporaryUpload::class,
/*
* When enabled, Media Library Pro will only process temporary uploads that were uploaded
@ -76,17 +102,17 @@
/*
* This is the class that is responsible for naming generated files.
*/
'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class,
'file_namer' => DefaultFileNamer::class,
/*
* The class that contains the strategy for determining a media file's path.
*/
'path_generator' => App\MediaLibrary\CustomPathGenerator::class,
'path_generator' => CustomPathGenerator::class,
/*
* The class that contains the strategy for determining how to remove files.
*/
'file_remover_class' => Spatie\MediaLibrary\Support\FileRemover\DefaultFileRemover::class,
'file_remover_class' => DefaultFileRemover::class,
/*
* Here you can specify which path generator should be used for the given class.
@ -101,7 +127,7 @@
* When urls to files get generated, this class will be called. Use the default
* if your files are stored locally above the site root or on s3.
*/
'url_generator' => Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator::class,
'url_generator' => DefaultUrlGenerator::class,
/*
* Moves media on updating to keep path consistent. Enable it only with a custom
@ -121,34 +147,34 @@
* the optimizers that will be used by default.
*/
'image_optimizers' => [
Spatie\ImageOptimizer\Optimizers\Jpegoptim::class => [
Jpegoptim::class => [
'-m85', // set maximum quality to 85%
'--force', // ensure that progressive generation is always done also if a little bigger
'--strip-all', // this strips out all text information such as comments and EXIF data
'--all-progressive', // this will make sure the resulting image is a progressive one
],
Spatie\ImageOptimizer\Optimizers\Pngquant::class => [
Pngquant::class => [
'--force', // required parameter for this package
],
Spatie\ImageOptimizer\Optimizers\Optipng::class => [
Optipng::class => [
'-i0', // this will result in a non-interlaced, progressive scanned image
'-o2', // this set the optimization level to two (multiple IDAT compression trials)
'-quiet', // required parameter for this package
],
Spatie\ImageOptimizer\Optimizers\Svgo::class => [
Svgo::class => [
'--disable=cleanupIDs', // disabling because it is known to cause troubles
],
Spatie\ImageOptimizer\Optimizers\Gifsicle::class => [
Gifsicle::class => [
'-b', // required parameter for this package
'-O3', // this produces the slowest but best results
],
Spatie\ImageOptimizer\Optimizers\Cwebp::class => [
Cwebp::class => [
'-m 6', // for the slowest compression method in order to get the best compression.
'-pass 10', // for maximizing the amount of analysis pass.
'-mt', // multithreading for some speed improvements.
'-q 90', // quality factor that brings the least noticeable changes.
],
Spatie\ImageOptimizer\Optimizers\Avifenc::class => [
Avifenc::class => [
'-a cq-level=23', // constant quality level, lower values mean better quality and greater file size (0-63).
'-j all', // number of jobs (worker threads, "all" uses all available cores).
'--min 0', // min quantizer for color (0-63).
@ -164,12 +190,12 @@
* These generators will be used to create an image of media files.
*/
'image_generators' => [
Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Avif::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class,
Image::class,
Webp::class,
Avif::class,
Pdf::class,
Svg::class,
Video::class,
],
/*
@ -209,8 +235,8 @@
* your custom jobs extend the ones provided by the package.
*/
'jobs' => [
'perform_conversions' => Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob::class,
'generate_responsive_images' => Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob::class,
'perform_conversions' => PerformConversionsJob::class,
'generate_responsive_images' => GenerateResponsiveImagesJob::class,
],
/*
@ -218,7 +244,7 @@
* This is particularly useful when the url of the image is behind a firewall and
* need to add additional flags, possibly using curl.
*/
'media_downloader' => Spatie\MediaLibrary\Downloaders\DefaultDownloader::class,
'media_downloader' => DefaultDownloader::class,
/*
* When using the addMediaFromUrl method the SSL is verified by default.
@ -255,7 +281,7 @@
*
* https://docs.spatie.be/laravel-medialibrary/v9/advanced-usage/generating-responsive-images
*/
'width_calculator' => Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator::class,
'width_calculator' => FileSizeOptimizedWidthCalculator::class,
/*
* By default rendering media to a responsive image will add some javascript and a tiny placeholder.
@ -268,7 +294,7 @@
* This class will generate the tiny placeholder used for progressive image loading. By default
* the media library will use a tiny blurred jpg image.
*/
'tiny_placeholder_generator' => Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred::class,
'tiny_placeholder_generator' => Blurred::class,
],
/*

View File

@ -1,5 +1,9 @@
<?php
use Spatie\Permission\DefaultTeamResolver;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
return [
'models' => [
@ -13,7 +17,7 @@
* `Spatie\Permission\Contracts\Permission` contract.
*/
'permission' => Spatie\Permission\Models\Permission::class,
'permission' => Permission::class,
/*
* When using the "HasRoles" trait from this package, we need to know which
@ -24,7 +28,7 @@
* `Spatie\Permission\Contracts\Role` contract.
*/
'role' => Spatie\Permission\Models\Role::class,
'role' => Role::class,
],
@ -136,7 +140,7 @@
/*
* The class to use to resolve the permissions team id
*/
'team_resolver' => \Spatie\Permission\DefaultTeamResolver::class,
'team_resolver' => DefaultTeamResolver::class,
/*
* Passport Client Credentials Grant
@ -183,7 +187,7 @@
* When permissions or roles are updated the cache is flushed automatically.
*/
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
'expiration_time' => DateInterval::createFromDateString('24 hours'),
/*
* The cache key used to store all permissions.

View File

@ -2,11 +2,12 @@
namespace Database\Factories;
use App\Models\ClassSession;
use App\Models\Course;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\ClassSession>
* @extends Factory<ClassSession>
*/
class ClassSessionFactory extends Factory
{

View File

@ -2,10 +2,11 @@
namespace Database\Factories;
use App\Models\Course;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Course>
* @extends Factory<Course>
*/
class CourseFactory extends Factory
{

View File

@ -3,10 +3,11 @@
namespace Database\Factories;
use App\Models\Course;
use App\Models\CourseSchedule;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\CourseSchedule>
* @extends Factory<CourseSchedule>
*/
class CourseScheduleFactory extends Factory
{

View File

@ -4,10 +4,11 @@
use App\Models\ClassSession;
use App\Models\Course;
use App\Models\Material;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Material>
* @extends Factory<Material>
*/
class MaterialFactory extends Factory
{

View File

@ -2,11 +2,12 @@
namespace Database\Factories;
use App\Models\Student;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Student>
* @extends Factory<Student>
*/
class StudentFactory extends Factory
{

View File

@ -2,11 +2,12 @@
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
* @extends Factory<User>
*/
class UserFactory extends Factory
{

View File

@ -3,6 +3,7 @@
namespace Database\Seeders;
use BezhanSalleh\FilamentShield\Support\Utils;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\PermissionRegistrar;
@ -394,9 +395,9 @@ protected static function makeRolesWithPermissions(string $rolesWithPermissions)
return;
}
/** @var \Illuminate\Database\Eloquent\Model $roleModel */
/** @var Model $roleModel */
$roleModel = Utils::getRoleModel();
/** @var \Illuminate\Database\Eloquent\Model $permissionModel */
/** @var Model $permissionModel */
$permissionModel = Utils::getPermissionModel();
$tenancyEnabled = false;
@ -439,7 +440,7 @@ public static function makeDirectPermissions(string $directPermissions): void
return;
}
/** @var \Illuminate\Database\Eloquent\Model $permissionModel */
/** @var Model $permissionModel */
$permissionModel = Utils::getPermissionModel();
foreach ($permissions as $permission) {

View File

@ -13,6 +13,7 @@
use App\Models\StudyGroup;
use App\Models\User;
use App\Settings\GeneralSettings;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
@ -69,7 +70,7 @@
$assignment = Assignment::factory()->create();
expect($assignment->course)->toBeInstanceOf(Course::class);
expect($assignment->assignmentSubmissions())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\HasMany::class);
expect($assignment->assignmentSubmissions())->toBeInstanceOf(HasMany::class);
$assignment->delete();
expect($assignment->refresh()->trashed())->toBeTrue();

View File

@ -7,6 +7,7 @@
use App\Models\StudyGroup;
use App\Models\User;
use App\Settings\GeneralSettings;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
@ -67,7 +68,7 @@
expect($group->leader)->toBeInstanceOf(Student::class);
expect($group->courses()->count())->toBe(1);
expect($group->students())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsToMany::class);
expect($group->students())->toBeInstanceOf(BelongsToMany::class);
$group->delete();
expect($group->refresh()->trashed())->toBeTrue();

View File

@ -1,5 +1,8 @@
<?php
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
/*
|--------------------------------------------------------------------------
| Test Case
@ -11,8 +14,8 @@
|
*/
pest()->extend(Tests\TestCase::class)
->use(Illuminate\Foundation\Testing\RefreshDatabase::class)
pest()->extend(TestCase::class)
->use(RefreshDatabase::class)
->in('Feature');
/*