diff --git a/README.md b/README.md index c81306400..85935d9a9 100644 --- a/README.md +++ b/README.md @@ -223,10 +223,18 @@ We test Moox using: Please make sure you use the same tools in VS Code (our [VS Code Extension Pack](https://marketplace.visualstudio.com/items?itemName=adrolli.tallui-laravel-livewire-tailwind) covers this) or do the checks manually before committing to the dev-branch: -- PHPStan: `composer analyse ` or `./vendor/bin/phpstan analyse`, for packages `../../vendor/bin/phpstan analyse` -- Pest: `composer test ` or `./vendor/bin/pest`, for packages `../../vendor/bin/pest` -- Coverage: `composer test-coverage ` or `./vendor/bin/pest --coverage`, for packages `../../vendor/bin/pest --coverage` -- Pint: `composer format ` or `./vendor/bin/pint`, for packages `../../vendor/bin/pint` +- Use `composer lint` to do a dry run of Pint, aliased as `test:lint` +- Use `composer analyse` to run PHPStan, aliased as `analyze` and `test:types` +- Use `composer test` to run the complete test suite +- Use `composer test:refactor` to do a dry run of Rector +- Use `composer test:arch` to run the architecture tests +- Use `composer test:type-coverage` to run the type coverage tests +- Use `composer test:unit` to run pest parallel with coverage +- Use `composer test:coverage` to run pest with coverage +- Use `composer refactor` to run Rector (ATTENTION CHANGES FILES), aliased as `rector` +- Use `composer format` to run Pint (ATTENTION CHANGES FILES), aliased as `pint` + +For more information, please see [composer.json](composer.json). ## Admin Navigation diff --git a/app/Console/Commands/BatchJobCommand.php b/app/Console/Commands/BatchJobCommand.php index e1bd540ea..e2e03c490 100644 --- a/app/Console/Commands/BatchJobCommand.php +++ b/app/Console/Commands/BatchJobCommand.php @@ -16,7 +16,7 @@ public function __construct() parent::__construct(); } - public function handle() + public function handle(): void { $this->info('Starting Moox Batch Job'); diff --git a/app/Console/Commands/DemoJobCommand.php b/app/Console/Commands/DemoJobCommand.php index bfa9e9118..16822126f 100644 --- a/app/Console/Commands/DemoJobCommand.php +++ b/app/Console/Commands/DemoJobCommand.php @@ -16,7 +16,7 @@ public function __construct() parent::__construct(); } - public function handle() + public function handle(): void { $this->info('Starting Moox Demo Job'); diff --git a/app/Console/Commands/FailJobCommand.php b/app/Console/Commands/FailJobCommand.php index 9b18f12dc..6da110a54 100644 --- a/app/Console/Commands/FailJobCommand.php +++ b/app/Console/Commands/FailJobCommand.php @@ -16,7 +16,7 @@ public function __construct() parent::__construct(); } - public function handle() + public function handle(): void { $this->info('Starting Moox Fail Job'); diff --git a/app/Console/Commands/LongJobCommand.php b/app/Console/Commands/LongJobCommand.php index 027a60485..758fd55d5 100644 --- a/app/Console/Commands/LongJobCommand.php +++ b/app/Console/Commands/LongJobCommand.php @@ -16,7 +16,7 @@ public function __construct() parent::__construct(); } - public function handle() + public function handle(): void { $this->info('Starting Moox Long Job'); diff --git a/app/Console/Commands/ShortJobCommand.php b/app/Console/Commands/ShortJobCommand.php index d58b7d03c..72fedfc93 100644 --- a/app/Console/Commands/ShortJobCommand.php +++ b/app/Console/Commands/ShortJobCommand.php @@ -16,7 +16,7 @@ public function __construct() parent::__construct(); } - public function handle() + public function handle(): void { $this->info('Starting Moox Short Job'); diff --git a/app/Console/Commands/TimeoutJobCommand.php b/app/Console/Commands/TimeoutJobCommand.php index b19456376..72e39bdd0 100644 --- a/app/Console/Commands/TimeoutJobCommand.php +++ b/app/Console/Commands/TimeoutJobCommand.php @@ -16,7 +16,7 @@ public function __construct() parent::__construct(); } - public function handle() + public function handle(): void { $this->info('Starting Moox Timeout Job'); diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 1946dc58e..74afac99a 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -4,6 +4,7 @@ use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; +use Override; class Kernel extends ConsoleKernel { @@ -12,6 +13,7 @@ class Kernel extends ConsoleKernel * * @return void */ + #[Override] protected function schedule(Schedule $schedule) { $schedule->command('moox:batchjob')->daily(); @@ -26,6 +28,7 @@ protected function schedule(Schedule $schedule) * * @return void */ + #[Override] protected function commands() { $this->load(__DIR__.'/Commands'); diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 82a37e400..6e028d966 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -3,6 +3,7 @@ namespace App\Exceptions; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Override; use Throwable; class Handler extends ExceptionHandler @@ -10,7 +11,7 @@ class Handler extends ExceptionHandler /** * A list of exception types with their corresponding custom log levels. * - * @var array, \Psr\Log\LogLevel::*> + * @var array, \Psr\Log\LogLevel::*> */ protected $levels = [ // @@ -19,7 +20,7 @@ class Handler extends ExceptionHandler /** * A list of the exception types that are not reported. * - * @var array> + * @var array> */ protected $dontReport = [ // @@ -38,12 +39,11 @@ class Handler extends ExceptionHandler /** * Register the exception handling callbacks for the application. - * - * @return void */ - public function register() + #[Override] + public function register(): void { - $this->reportable(function (Throwable $e) { + $this->reportable(function (Throwable $e): void { // }); } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index a0a2a8a34..ce1176ddb 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -9,5 +9,7 @@ class Controller extends BaseController { - use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + use AuthorizesRequests; + use DispatchesJobs; + use ValidatesRequests; } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 007968811..83ad743bf 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -2,7 +2,29 @@ namespace App\Http; +use App\Http\Middleware\Authenticate; +use App\Http\Middleware\EncryptCookies; +use App\Http\Middleware\PreventRequestsDuringMaintenance; +use App\Http\Middleware\RedirectIfAuthenticated; +use App\Http\Middleware\TrimStrings; +use App\Http\Middleware\TrustProxies; +use App\Http\Middleware\ValidateSignature; +use App\Http\Middleware\VerifyCsrfToken; +use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; +use Illuminate\Auth\Middleware\Authorize; +use Illuminate\Auth\Middleware\EnsureEmailIsVerified; +use Illuminate\Auth\Middleware\RequirePassword; +use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Foundation\Http\Kernel as HttpKernel; +use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; +use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use Illuminate\Http\Middleware\HandleCors; +use Illuminate\Http\Middleware\SetCacheHeaders; +use Illuminate\Routing\Middleware\SubstituteBindings; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Session\Middleware\AuthenticateSession; +use Illuminate\Session\Middleware\StartSession; +use Illuminate\View\Middleware\ShareErrorsFromSession; class Kernel extends HttpKernel { @@ -15,12 +37,12 @@ class Kernel extends HttpKernel */ protected $middleware = [ // \App\Http\Middleware\TrustHosts::class, - \App\Http\Middleware\TrustProxies::class, - \Illuminate\Http\Middleware\HandleCors::class, - \App\Http\Middleware\PreventRequestsDuringMaintenance::class, - \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, - \App\Http\Middleware\TrimStrings::class, - \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + TrustProxies::class, + HandleCors::class, + PreventRequestsDuringMaintenance::class, + ValidatePostSize::class, + TrimStrings::class, + ConvertEmptyStringsToNull::class, ]; /** @@ -30,18 +52,18 @@ class Kernel extends HttpKernel */ protected $middlewareGroups = [ 'web' => [ - \App\Http\Middleware\EncryptCookies::class, - \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, - \Illuminate\Session\Middleware\StartSession::class, - \Illuminate\View\Middleware\ShareErrorsFromSession::class, - \App\Http\Middleware\VerifyCsrfToken::class, - \Illuminate\Routing\Middleware\SubstituteBindings::class, + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + SubstituteBindings::class, ], 'api' => [ // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', - \Illuminate\Routing\Middleware\SubstituteBindings::class, + SubstituteBindings::class, ], ]; @@ -53,15 +75,15 @@ class Kernel extends HttpKernel * @var array */ protected $routeMiddleware = [ - 'auth' => \App\Http\Middleware\Authenticate::class, - 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, - 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, - 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, - 'can' => \Illuminate\Auth\Middleware\Authorize::class, - 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, - 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, - 'signed' => \App\Http\Middleware\ValidateSignature::class, - 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, - 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'auth' => Authenticate::class, + 'auth.basic' => AuthenticateWithBasicAuth::class, + 'auth.session' => AuthenticateSession::class, + 'cache.headers' => SetCacheHeaders::class, + 'can' => Authorize::class, + 'guest' => RedirectIfAuthenticated::class, + 'password.confirm' => RequirePassword::class, + 'signed' => ValidateSignature::class, + 'throttle' => ThrottleRequests::class, + 'verified' => EnsureEmailIsVerified::class, ]; } diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 704089a7f..ff1e547ca 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -3,19 +3,24 @@ namespace App\Http\Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware; +use Illuminate\Http\Request; +use Override; class Authenticate extends Middleware { /** * Get the path the user should be redirected to when they are not authenticated. * - * @param \Illuminate\Http\Request $request + * @param Request $request * @return string|null */ + #[Override] protected function redirectTo($request) { if (! $request->expectsJson()) { return route('login'); } + + return response()->json(['message' => 'Unauthenticated.'], 401); } } diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 4e7c24b7e..3f02a8932 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -4,7 +4,9 @@ use App\Providers\RouteServiceProvider; use Closure; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\Http\Response; use Illuminate\Support\Facades\Auth; class RedirectIfAuthenticated @@ -12,13 +14,13 @@ class RedirectIfAuthenticated /** * Handle an incoming request. * - * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next + * @param Closure(Request):((Response|RedirectResponse)) $next * @param string|null ...$guards - * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse + * @return Response|RedirectResponse */ public function handle(Request $request, Closure $next, ...$guards) { - $guards = empty($guards) ? [null] : $guards; + $guards = $guards === [] ? [null] : $guards; foreach ($guards as $guard) { if (Auth::guard($guard)->check()) { diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php index 7186414c6..202f448d8 100644 --- a/app/Http/Middleware/TrustHosts.php +++ b/app/Http/Middleware/TrustHosts.php @@ -3,6 +3,7 @@ namespace App\Http\Middleware; use Illuminate\Http\Middleware\TrustHosts as Middleware; +use Override; class TrustHosts extends Middleware { @@ -11,6 +12,7 @@ class TrustHosts extends Middleware * * @return array */ + #[Override] public function hosts() { return [ diff --git a/app/Jobs/BatchJob.php b/app/Jobs/BatchJob.php index e9e4f71bb..10e2ccdd3 100644 --- a/app/Jobs/BatchJob.php +++ b/app/Jobs/BatchJob.php @@ -11,7 +11,10 @@ class BatchJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; public function handle(): void { diff --git a/app/Jobs/DemoJob.php b/app/Jobs/DemoJob.php index 2f09bd3f3..f87f5af9d 100644 --- a/app/Jobs/DemoJob.php +++ b/app/Jobs/DemoJob.php @@ -11,25 +11,33 @@ class DemoJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 10; - $this->timeout = 120; - $this->maxExceptions = 3; - $this->backoff = 240; - } - - public function handle() + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 10; + + /** + * @var int + */ + public $timeout = 120; + + /** + * @var int + */ + public $maxExceptions = 3; + + /** + * @var int + */ + public $backoff = 240; + + public function handle(): void { $count = 0; $steps = 10; @@ -37,7 +45,7 @@ public function handle() while ($count < $final) { $this->setProgress($count); - $count = $count + $steps; + $count += $steps; sleep(10); } } diff --git a/app/Jobs/FailJob.php b/app/Jobs/FailJob.php index 24d3dda7f..396ce1bc7 100644 --- a/app/Jobs/FailJob.php +++ b/app/Jobs/FailJob.php @@ -13,25 +13,34 @@ class FailJob implements ShouldQueue { - use Batchable, Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 10; - $this->timeout = 10; - $this->maxExceptions = 3; - $this->backoff = 20; - } - - public function handle() + use Batchable; + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 10; + + /** + * @var int + */ + public $timeout = 10; + + /** + * @var int + */ + public $maxExceptions = 3; + + /** + * @var int + */ + public $backoff = 20; + + public function handle(): never { throw new Exception('This job is meant to fail.'); } diff --git a/app/Jobs/LongJob.php b/app/Jobs/LongJob.php index dd6235c43..78e48b13d 100644 --- a/app/Jobs/LongJob.php +++ b/app/Jobs/LongJob.php @@ -11,25 +11,33 @@ class LongJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 10; - $this->timeout = 1200; - $this->maxExceptions = 3; - $this->backoff = 2400; - } - - public function handle() + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 10; + + /** + * @var int + */ + public $timeout = 1200; + + /** + * @var int + */ + public $maxExceptions = 3; + + /** + * @var int + */ + public $backoff = 2400; + + public function handle(): void { $count = 0; $steps = 1; @@ -37,7 +45,7 @@ public function handle() while ($count < $final) { $this->setProgress($count); - $count = $count + $steps; + $count += $steps; sleep(20); } } diff --git a/app/Jobs/ShortJob.php b/app/Jobs/ShortJob.php index 37df038ac..a0890aedf 100644 --- a/app/Jobs/ShortJob.php +++ b/app/Jobs/ShortJob.php @@ -12,25 +12,34 @@ class ShortJob implements ShouldQueue { - use Batchable, Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 10; - $this->timeout = 10; - $this->maxExceptions = 3; - $this->backoff = 20; - } - - public function handle() + use Batchable; + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 10; + + /** + * @var int + */ + public $timeout = 10; + + /** + * @var int + */ + public $maxExceptions = 3; + + /** + * @var int + */ + public $backoff = 20; + + public function handle(): void { if ($this->batch()->cancelled()) { return; @@ -42,7 +51,7 @@ public function handle() while ($count < $final) { $this->setProgress($count); - $count = $count + $steps; + $count += $steps; } } } diff --git a/app/Jobs/TimeoutJob.php b/app/Jobs/TimeoutJob.php index cfb1278c9..ea2abec29 100644 --- a/app/Jobs/TimeoutJob.php +++ b/app/Jobs/TimeoutJob.php @@ -11,25 +11,33 @@ class TimeoutJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 3; - $this->timeout = 10; - $this->maxExceptions = 1; - $this->backoff = 5; - } - - public function handle() + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 3; + + /** + * @var int + */ + public $timeout = 10; + + /** + * @var int + */ + public $maxExceptions = 1; + + /** + * @var int + */ + public $backoff = 5; + + public function handle(): void { $count = 0; $steps = 10; @@ -37,7 +45,7 @@ public function handle() while ($count < $final) { $this->setProgress($count); - $count = $count + $steps; + $count += $steps; sleep(2); } } diff --git a/app/Models/User.php b/app/Models/User.php index d944b6494..1e2ded0ee 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -12,12 +12,15 @@ class User extends Authenticatable implements FilamentUser { - use HasFactory, HasRoles, Notifiable, TwoFactorAuthenticatable; + use HasFactory; + use HasRoles; + use Notifiable; + use TwoFactorAuthenticatable; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'name', 'email', 'password', @@ -26,7 +29,7 @@ class User extends Authenticatable implements FilamentUser /** * The attributes that should be hidden for serialization. * - * @var array + * @var list */ protected $hidden = [ 'password', diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index ee8ca5bcd..7f6750785 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,25 +3,23 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; +use Override; class AppServiceProvider extends ServiceProvider { /** * Register any application services. - * - * @return void */ - public function register() + #[Override] + public function register(): void { // } /** * Bootstrap any application services. - * - * @return void */ - public function boot() + public function boot(): void { // } diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php index 395c518bc..2be04f5d9 100644 --- a/app/Providers/BroadcastServiceProvider.php +++ b/app/Providers/BroadcastServiceProvider.php @@ -9,10 +9,8 @@ class BroadcastServiceProvider extends ServiceProvider { /** * Bootstrap any application services. - * - * @return void */ - public function boot() + public function boot(): void { Broadcast::routes(); diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index ab8b2cf77..0b02ade37 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -6,6 +6,7 @@ use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; +use Override; class EventServiceProvider extends ServiceProvider { @@ -22,10 +23,9 @@ class EventServiceProvider extends ServiceProvider /** * Register any events for your application. - * - * @return void */ - public function boot() + #[Override] + public function boot(): void { // } @@ -35,6 +35,7 @@ public function boot() * * @return bool */ + #[Override] public function shouldDiscoverEvents() { return false; diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 3c6d705b7..5b1d1ec84 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -6,11 +6,12 @@ use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DispatchServingFilamentEvent; -use Filament\Pages; +use Filament\Pages\Dashboard; use Filament\Panel; use Filament\PanelProvider; use Filament\Support\Colors\Color; -use Filament\Widgets; +use Filament\Widgets\AccountWidget; +use Filament\Widgets\FilamentInfoWidget; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken; @@ -18,8 +19,34 @@ use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Moox\Audit\AuditPlugin; +use Moox\Builder\FullItemPlugin; +use Moox\Builder\ItemPlugin; +use Moox\Builder\NestedTaxonomyPlugin; +use Moox\Builder\SimpleItemPlugin; +use Moox\Builder\SimpleTaxonomyPlugin; +use Moox\Category\CategoryPlugin; +use Moox\Expiry\ExpiryPlugin; +use Moox\Jobs\JobsBatchesPlugin; +use Moox\Jobs\JobsFailedPlugin; +use Moox\Jobs\JobsPlugin; +use Moox\Jobs\JobsWaitingPlugin; +use Moox\Locate\AreaPlugin; +use Moox\LoginLink\LoginLinkPlugin; +use Moox\Notification\NotificationPlugin; +use Moox\Page\PagePlugin; +use Moox\Passkey\PasskeyPlugin; +use Moox\Security\ResetPasswordPlugin; use Moox\Security\Services\RequestPasswordReset; +use Moox\Tag\TagPlugin; +use Moox\Training\TrainingDatePlugin; +use Moox\Training\TrainingInvitationPlugin; +use Moox\Training\TrainingPlugin; +use Moox\Training\TrainingTypePlugin; use Moox\User\Services\Login; +use Moox\User\UserPlugin; +use Moox\UserDevice\UserDevicePlugin; +use Moox\UserSession\UserSessionPlugin; class AdminPanelProvider extends PanelProvider { @@ -42,12 +69,12 @@ public function panel(Panel $panel): Panel ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources') ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages') ->pages([ - Pages\Dashboard::class, + Dashboard::class, ]) ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets') ->widgets([ - Widgets\AccountWidget::class, - Widgets\FilamentInfoWidget::class, + AccountWidget::class, + FilamentInfoWidget::class, ]) ->middleware([ EncryptCookies::class, @@ -68,59 +95,59 @@ public function panel(Panel $panel): Panel // Development GravatarPlugin::make(), - \Moox\Audit\AuditPlugin::make(), - \Moox\Locate\AreaPlugin::make(), + AuditPlugin::make(), + AreaPlugin::make(), // \Moox\Locate\CountryPlugin::make(), // \Moox\Locate\LanguagePlugin::make(), // \Moox\Locate\TimezonePlugin::make(), // Builder plugin - \Moox\Builder\SimpleTaxonomyPlugin::make(), - \Moox\Builder\NestedTaxonomyPlugin::make(), - \Moox\Builder\ItemPlugin::make(), - \Moox\Builder\FullItemPlugin::make(), - \Moox\Builder\SimpleItemPlugin::make(), + SimpleTaxonomyPlugin::make(), + NestedTaxonomyPlugin::make(), + ItemPlugin::make(), + FullItemPlugin::make(), + SimpleItemPlugin::make(), // CMS plugin - \Moox\Page\PagePlugin::make(), - \Moox\Category\CategoryPlugin::make(), - \Moox\Tag\TagPlugin::make(), + PagePlugin::make(), + CategoryPlugin::make(), + TagPlugin::make(), // Notification plugin - \Moox\Notification\NotificationPlugin::make(), + NotificationPlugin::make(), // Audit plugin - \Moox\Audit\AuditPlugin::make(), + AuditPlugin::make(), // Jobs plugins - \Moox\Jobs\JobsPlugin::make(), - \Moox\Jobs\JobsWaitingPlugin::make(), - \Moox\Jobs\JobsFailedPlugin::make(), - \Moox\Jobs\JobsBatchesPlugin::make(), + JobsPlugin::make(), + JobsWaitingPlugin::make(), + JobsFailedPlugin::make(), + JobsBatchesPlugin::make(), // Sync Plugins // \Moox\Sync\SyncPlugin::make(), // \Moox\Sync\PlatformPlugin::make(), // User plugins - \Moox\User\UserPlugin::make(), - \Moox\UserDevice\UserDevicePlugin::make(), - \Moox\LoginLink\LoginLinkPlugin::make(), - \Moox\UserSession\UserSessionPlugin::make(), - \Moox\Passkey\PasskeyPlugin::make(), - \Moox\Security\ResetPasswordPlugin::make(), + UserPlugin::make(), + UserDevicePlugin::make(), + LoginLinkPlugin::make(), + UserSessionPlugin::make(), + PasskeyPlugin::make(), + ResetPasswordPlugin::make(), // Expiry plugin - \Moox\Expiry\ExpiryPlugin::make(), + ExpiryPlugin::make(), // Training plugins - \Moox\Training\TrainingPlugin::make(), - \Moox\Training\TrainingInvitationPlugin::make(), - \Moox\Training\TrainingDatePlugin::make(), - \Moox\Training\TrainingTypePlugin::make(), + TrainingPlugin::make(), + TrainingInvitationPlugin::make(), + TrainingDatePlugin::make(), + TrainingTypePlugin::make(), // Builder plugin - \Moox\Builder\ItemPlugin::make(), + ItemPlugin::make(), ]); } diff --git a/app/Providers/Filament/PressPanelProvider.php b/app/Providers/Filament/PressPanelProvider.php index 412fe984b..c5ff35bcc 100644 --- a/app/Providers/Filament/PressPanelProvider.php +++ b/app/Providers/Filament/PressPanelProvider.php @@ -5,7 +5,7 @@ use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DispatchServingFilamentEvent; -use Filament\Pages; +use Filament\Pages\Dashboard; use Filament\Panel; use Filament\PanelProvider; use Filament\Support\Colors\Color; @@ -16,9 +16,48 @@ use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Moox\Audit\AuditPlugin; +use Moox\Expiry\ExpiryPlugin; +use Moox\Jobs\JobsBatchesPlugin; +use Moox\Jobs\JobsFailedPlugin; +use Moox\Jobs\JobsPlugin; +use Moox\Jobs\JobsWaitingPlugin; +use Moox\LoginLink\LoginLinkPlugin; +use Moox\Notification\NotificationPlugin; +use Moox\Passkey\PasskeyPlugin; use Moox\Press\Services\Login; +use Moox\Press\WpCategoryPlugin; +use Moox\Press\WpCommentMetaPlugin; +use Moox\Press\WpCommentPlugin; +use Moox\Press\WpMediaPlugin; +use Moox\Press\WpOptionPlugin; +use Moox\Press\WpPagePlugin; +use Moox\Press\WpPostMetaPlugin; +use Moox\Press\WpPostPlugin; +use Moox\Press\WpTagPlugin; +use Moox\Press\WpTermMetaPlugin; +use Moox\Press\WpTermPlugin; +use Moox\Press\WpTermRelationshipPlugin; +use Moox\Press\WpTermTaxonomyPlugin; +use Moox\Press\WpUserMetaPlugin; +use Moox\Press\WpUserPlugin; +use Moox\PressTrainings\WpTrainingPlugin; +use Moox\PressTrainings\WpTrainingsTopicPlugin; +use Moox\PressWiki\WpWikiCompanyTopicPlugin; +use Moox\PressWiki\WpWikiDepartmentTopicPlugin; +use Moox\PressWiki\WpWikiLetterTopicPlugin; +use Moox\PressWiki\WpWikiLocationTopicPlugin; +use Moox\PressWiki\WpWikiPlugin; +use Moox\PressWiki\WpWikiTopicPlugin; +use Moox\Security\ResetPasswordPlugin; use Moox\Security\Services\RequestPasswordReset; use Moox\Security\Services\ResetPassword; +use Moox\Training\TrainingDatePlugin; +use Moox\Training\TrainingInvitationPlugin; +use Moox\Training\TrainingPlugin; +use Moox\Training\TrainingTypePlugin; +use Moox\UserDevice\UserDevicePlugin; +use Moox\UserSession\UserSessionPlugin; class PressPanelProvider extends PanelProvider { @@ -37,7 +76,7 @@ public function panel(Panel $panel): Panel ->discoverResources(in: app_path('Filament/Press/Resources'), for: 'App\\Filament\\Press\\Resources') ->discoverPages(in: app_path('Filament/Press/Pages'), for: 'App\\Filament\\Press\\Pages') ->pages([ - Pages\Dashboard::class, + Dashboard::class, ]) ->discoverWidgets(in: app_path('Filament/Press/Widgets'), for: 'App\\Filament\\Press\\Widgets') ->widgets([ @@ -59,66 +98,66 @@ public function panel(Panel $panel): Panel ]) ->plugins([ // Press plugins - \Moox\Press\WpPostPlugin::make(), - \Moox\Press\WpPagePlugin::make(), - \Moox\Press\WpMediaPlugin::make(), - \Moox\Press\WpCategoryPlugin::make(), - \Moox\Press\WpTagPlugin::make(), - \Moox\Press\WpCommentPlugin::make(), + WpPostPlugin::make(), + WpPagePlugin::make(), + WpMediaPlugin::make(), + WpCategoryPlugin::make(), + WpTagPlugin::make(), + WpCommentPlugin::make(), // Press system plugins - \Moox\Press\WpOptionPlugin::make(), - \Moox\Press\WpUserMetaPlugin::make(), - \Moox\Press\WpPostMetaPlugin::make(), - \Moox\Press\WpCommentMetaPlugin::make(), - \Moox\Press\WpTermMetaPlugin::make(), - \Moox\Press\WpTermPlugin::make(), - \Moox\Press\WpTermTaxonomyPlugin::make(), - \Moox\Press\WpTermRelationshipPlugin::make(), + WpOptionPlugin::make(), + WpUserMetaPlugin::make(), + WpPostMetaPlugin::make(), + WpCommentMetaPlugin::make(), + WpTermMetaPlugin::make(), + WpTermPlugin::make(), + WpTermTaxonomyPlugin::make(), + WpTermRelationshipPlugin::make(), // Notification plugin - \Moox\Notification\NotificationPlugin::make(), + NotificationPlugin::make(), // Audit plugin - \Moox\Audit\AuditPlugin::make(), + AuditPlugin::make(), // Jobs plugins - \Moox\Jobs\JobsPlugin::make(), - \Moox\Jobs\JobsWaitingPlugin::make(), - \Moox\Jobs\JobsFailedPlugin::make(), - \Moox\Jobs\JobsBatchesPlugin::make(), + JobsPlugin::make(), + JobsWaitingPlugin::make(), + JobsFailedPlugin::make(), + JobsBatchesPlugin::make(), // Sync Plugins // \Moox\Sync\SyncPlugin::make(), // \Moox\Sync\PlatformPlugin::make(), // User plugins - \Moox\Press\WpUserPlugin::make(), - \Moox\UserDevice\UserDevicePlugin::make(), - \Moox\LoginLink\LoginLinkPlugin::make(), - \Moox\UserSession\UserSessionPlugin::make(), - \Moox\Passkey\PasskeyPlugin::make(), - \Moox\Security\ResetPasswordPlugin::make(), + WpUserPlugin::make(), + UserDevicePlugin::make(), + LoginLinkPlugin::make(), + UserSessionPlugin::make(), + PasskeyPlugin::make(), + ResetPasswordPlugin::make(), // Expiry plugin - \Moox\Expiry\ExpiryPlugin::make(), + ExpiryPlugin::make(), // Training plugins - \Moox\Training\TrainingPlugin::make(), - \Moox\Training\TrainingInvitationPlugin::make(), - \Moox\Training\TrainingDatePlugin::make(), - \Moox\Training\TrainingTypePlugin::make(), + TrainingPlugin::make(), + TrainingInvitationPlugin::make(), + TrainingDatePlugin::make(), + TrainingTypePlugin::make(), // Musste kurz raus, sorry ;-) - \Moox\PressWiki\WpWikiPlugin::make(), - \Moox\PressWiki\WpWikiTopicPlugin::make(), - \Moox\PressWiki\WpWikiLetterTopicPlugin::make(), - \Moox\PressWiki\WpWikiCompanyTopicPlugin::make(), - \Moox\PressWiki\WpWikiDepartmentTopicPlugin::make(), - \Moox\PressWiki\WpWikiLocationTopicPlugin::make(), + WpWikiPlugin::make(), + WpWikiTopicPlugin::make(), + WpWikiLetterTopicPlugin::make(), + WpWikiCompanyTopicPlugin::make(), + WpWikiDepartmentTopicPlugin::make(), + WpWikiLocationTopicPlugin::make(), - \Moox\PressTrainings\WpTrainingPlugin::make(), - \Moox\PressTrainings\WpTrainingsTopicPlugin::make(), + WpTrainingPlugin::make(), + WpTrainingsTopicPlugin::make(), ]); } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 52dabc11a..ad96369d3 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -7,6 +7,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\Route; +use Override; class RouteServiceProvider extends ServiceProvider { @@ -21,14 +22,13 @@ class RouteServiceProvider extends ServiceProvider /** * Define your route model bindings, pattern filters, and other route configuration. - * - * @return void */ - public function boot() + #[Override] + public function boot(): void { $this->configureRateLimiting(); - $this->routes(function () { + $this->routes(function (): void { Route::middleware('api') ->prefix('api') ->group(base_path('routes/api.php')); @@ -45,8 +45,6 @@ public function boot() */ protected function configureRateLimiting() { - RateLimiter::for('api', function (Request $request) { - return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); - }); + RateLimiter::for('api', fn (Request $request) => Limit::perMinute(60)->by($request->user()?->id ?: $request->ip())); } } diff --git a/composer.json b/composer.json index 1fe5209f3..a8b8c4db8 100644 --- a/composer.json +++ b/composer.json @@ -51,15 +51,16 @@ }, "require-dev": { "fakerphp/faker": "^1.23.1", + "larastan/larastan": "^3.0", "laravel/pint": "^1.0", "laravel/sail": "^1.26", "nunomaduro/collision": "^8.0", - "larastan/larastan": "^3.0", "pestphp/pest": "^3.0", "pestphp/pest-plugin-laravel": "^3.0", "pestphp/pest-plugin-livewire": "^3.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^2.0", + "rector/rector": "^2.0", "spatie/laravel-ignition": "^2.3", "spatie/laravel-ray": "^1.33" }, @@ -90,10 +91,28 @@ "post-create-project-cmd": [ "@php artisan key:generate --ansi" ], - "analyse": "vendor/bin/phpstan analyse", - "test": "vendor/bin/pest", - "test-coverage": "vendor/bin/pest --coverage", - "format": "vendor/bin/pint" + "analyse": "./vendor/bin/phpstan analyze --memory-limit 512m", + "analyze": "@analyse", + "pint": "vendor/bin/pint", + "format": "@pint", + "lint": "@pint --test", + "rector": "vendor/bin/rector", + "refactor": "@rector", + "pest": "vendor/bin/pest", + "test:coverage": "@pest --coverage", + "test:lint": "@lint", + "test:refactor": "@rector --dry-run", + "test:types": "@analyse", + "test:arch": "@pest --filter=arch", + "test:type-coverage": "@pest --type-coverage --min=100", + "test:unit": "@pest --parallel --coverage --exactly=99.4", + "test": [ + "@test:lint", + "@test:refactor", + "@test:types", + "@test:type-coverage", + "@test:unit" + ] }, "extra": { "laravel": { diff --git a/config/app.php b/config/app.php index 7886ebe38..554f8cf25 100644 --- a/config/app.php +++ b/config/app.php @@ -1,6 +1,33 @@ [ 'users' => [ 'driver' => 'eloquent', - 'model' => \Moox\User\Models\User::class, + 'model' => User::class, ], 'wpusers' => [ 'driver' => 'eloquent', - 'model' => \Moox\Press\Models\WpUser::class, + 'model' => WpUser::class, ], ], diff --git a/config/builder.php b/config/builder.php index 2e79b672e..a51bf94e0 100644 --- a/config/builder.php +++ b/config/builder.php @@ -1,5 +1,18 @@ [ 'light-item' => [ - 'class' => \Moox\Builder\Presets\LightItemPreset::class, + 'class' => LightItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], 'simple-item' => [ - 'class' => \Moox\Builder\Presets\SimpleItemPreset::class, + 'class' => SimpleItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], 'soft-delete-item' => [ - 'class' => \Moox\Builder\Presets\SoftDeleteItemPreset::class, + 'class' => SoftDeleteItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], 'full-item' => [ - 'class' => \Moox\Builder\Presets\FullItemPreset::class, + 'class' => FullItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], 'static-language' => [ - 'class' => \App\Builder\Presets\StaticLanguagePreset::class, + 'class' => StaticLanguagePreset::class, 'generators' => ['model', 'migration', 'resource'], ], ], @@ -94,9 +106,7 @@ [ 'field' => 'publish_at', 'operator' => '<=', - 'value' => function () { - return now(); - }, + 'value' => fn () => now(), ], [ 'field' => 'deleted_at', @@ -112,9 +122,7 @@ [ 'field' => 'publish_at', 'operator' => '>', - 'value' => function () { - return now(); - }, + 'value' => fn () => now(), ], [ 'field' => 'deleted_at', @@ -165,17 +173,17 @@ 'taxonomies' => [ 'categories' => [ 'label' => 'Categories', - 'model' => \Moox\Category\Models\Category::class, + 'model' => Category::class, 'table' => 'categorizables', 'relationship' => 'categorizable', 'foreignKey' => 'categorizable_id', 'relatedKey' => 'category_id', - 'createForm' => \Moox\Category\Forms\TaxonomyCreateForm::class, + 'createForm' => TaxonomyCreateForm::class, 'hierarchical' => true, ], 'tags' => [ 'label' => 'Tags', - 'model' => \Moox\Tag\Models\Tag::class, + 'model' => Tag::class, 'table' => 'taggables', 'relationship' => 'taggable', 'foreignKey' => 'taggable_id', @@ -228,9 +236,7 @@ [ 'field' => 'publish_at', 'operator' => '<=', - 'value' => function () { - return now(); - }, + 'value' => fn () => now(), ], [ 'field' => 'deleted_at', @@ -246,9 +252,7 @@ [ 'field' => 'publish_at', 'operator' => '>', - 'value' => function () { - return now(); - }, + 'value' => fn () => now(), ], [ 'field' => 'deleted_at', @@ -299,17 +303,17 @@ 'taxonomies' => [ 'categories' => [ 'label' => 'Categories', - 'model' => \Moox\Category\Models\Category::class, + 'model' => Category::class, 'table' => 'categorizables', 'relationship' => 'categorizable', 'foreignKey' => 'categorizable_id', 'relatedKey' => 'category_id', - 'createForm' => \Moox\Category\Forms\TaxonomyCreateForm::class, + 'createForm' => TaxonomyCreateForm::class, 'hierarchical' => true, ], 'tags' => [ 'label' => 'Tags', - 'model' => \Moox\Tag\Models\Tag::class, + 'model' => Tag::class, 'table' => 'taggables', 'relationship' => 'taggable', 'foreignKey' => 'taggable_id', @@ -420,17 +424,17 @@ 'taxonomies' => [ 'categories' => [ 'label' => 'Categories', - 'model' => \Moox\Category\Models\Category::class, + 'model' => Category::class, 'table' => 'categorizables', 'relationship' => 'categorizable', 'foreignKey' => 'categorizable_id', 'relatedKey' => 'category_id', - 'createForm' => \Moox\Category\Forms\TaxonomyCreateForm::class, + 'createForm' => TaxonomyCreateForm::class, 'hierarchical' => true, ], 'tags' => [ 'label' => 'Tags', - 'model' => \Moox\Tag\Models\Tag::class, + 'model' => Tag::class, 'table' => 'taggables', 'relationship' => 'taggable', 'foreignKey' => 'taggable_id', @@ -502,17 +506,17 @@ 'taxonomies' => [ 'categories' => [ 'label' => 'Categories', - 'model' => \Moox\Category\Models\Category::class, + 'model' => Category::class, 'table' => 'categorizables', 'relationship' => 'categorizable', 'foreignKey' => 'categorizable_id', 'relatedKey' => 'category_id', - 'createForm' => \Moox\Category\Forms\TaxonomyCreateForm::class, + 'createForm' => TaxonomyCreateForm::class, 'hierarchical' => true, ], 'tags' => [ 'label' => 'Tags', - 'model' => \Moox\Tag\Models\Tag::class, + 'model' => Tag::class, 'table' => 'taggables', 'relationship' => 'taggable', 'foreignKey' => 'taggable_id', @@ -534,18 +538,18 @@ 'relations' => [ 'rooms' => [ 'label' => 'Rooms', - 'model' => \Moox\Room\Models\Room::class, + 'model' => Room::class, 'table' => 'roomables', 'type' => 'has-many', 'relationship' => 'roomable', 'foreignKey' => 'roomable_id', 'relatedKey' => 'room_id', - 'createForm' => \Moox\Brand\Forms\RelationCreateForm::class, + 'createForm' => RelationCreateForm::class, 'hierarchical' => true, ], 'bookings' => [ 'label' => 'Bookings', - 'model' => \Moox\Booking\Models\Booking::class, + 'model' => Booking::class, 'table' => 'bookings', 'type' => 'has-many', 'relationship' => 'bookable', @@ -610,7 +614,7 @@ | */ - 'user_model' => \Moox\User\Models\User::class, + 'user_model' => User::class, /* |-------------------------------------------------------------------------- diff --git a/config/expiry.php b/config/expiry.php index d5bfda281..831bde5c4 100644 --- a/config/expiry.php +++ b/config/expiry.php @@ -1,5 +1,9 @@ 'deleted_at', 'operator' => '=', 'value' => null], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'articles' => [ 'label' => 'trans//core::core.articles', @@ -86,9 +87,7 @@ ], ['field' => 'deleted_at', 'operator' => '=', 'value' => null], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'tasks' => [ 'label' => 'trans//core::core.tasks', @@ -101,9 +100,7 @@ ], ['field' => 'deleted_at', 'operator' => '=', 'value' => null], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'no-user' => [ 'label' => 'trans//core::expiry.no_assignee', @@ -116,9 +113,7 @@ ], ['field' => 'deleted_at', 'operator' => '=', 'value' => null], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'no-date' => [ 'label' => 'trans//core::expiry.no_expiry_date', @@ -131,9 +126,7 @@ ], ['field' => 'deleted_at', 'operator' => '=', 'value' => null], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], ], ], @@ -196,7 +189,7 @@ | */ - 'user_model' => \Moox\Press\Models\WpUser::class, + 'user_model' => WpUser::class, 'default_notified_to' => 1, /* @@ -261,7 +254,7 @@ */ 'collect_expiries_jobs' => [ - Moox\Expiry\Jobs\CollectExpiries::class, + CollectExpiries::class, // Add more jobs here if needed. ], @@ -276,7 +269,7 @@ | */ - 'expiry_action' => Moox\Expiry\Actions\CustomExpiryAction::class, + 'expiry_action' => CustomExpiryAction::class, 'expiry_action_enable' => true, 'expiry_action_name' => 'Custom Expiry Action', 'expiry_view_action_color' => 'primary', diff --git a/config/filament-shield.php b/config/filament-shield.php index 7602db22e..fa325da5b 100644 --- a/config/filament-shield.php +++ b/config/filament-shield.php @@ -1,7 +1,8 @@ [ 'should_register_navigation' => true, @@ -14,7 +15,7 @@ ], 'auth_provider_model' => [ - 'fqcn' => 'Moox\\User\\Models\\User', + 'fqcn' => User::class, ], 'super_admin' => [ diff --git a/config/login-link.php b/config/login-link.php index 2bc3170d7..73001dedb 100644 --- a/config/login-link.php +++ b/config/login-link.php @@ -1,5 +1,7 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, 'Moox Users' => \Moox\User\Models\User::class, ], diff --git a/config/moox.php b/config/moox.php index 23d86b4a0..bb958aca6 100644 --- a/config/moox.php +++ b/config/moox.php @@ -12,7 +12,7 @@ | */ - 'custom_views' => explode(',', env('CUSTOM_VIEWS', 'example')), + 'custom_views' => explode(',', (string) env('CUSTOM_VIEWS', 'example')), 'custom_routes' => env('CUSTOM_ROUTES'), ]; diff --git a/config/passkey.php b/config/passkey.php index eb47530e3..b6df1affc 100644 --- a/config/passkey.php +++ b/config/passkey.php @@ -1,5 +1,8 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, 'Moox Users' => \Moox\User\Models\User::class, ], @@ -111,6 +113,6 @@ | */ - 'device_model' => \Moox\UserDevice\Models\UserDevice::class, + 'device_model' => UserDevice::class, ]; diff --git a/config/permission.php b/config/permission.php index f7c8f5a9d..f831d3f28 100644 --- a/config/permission.php +++ b/config/permission.php @@ -1,5 +1,8 @@ [ @@ -13,7 +16,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 +27,7 @@ * `Spatie\Permission\Contracts\Role` contract. */ - 'role' => Spatie\Permission\Models\Role::class, + 'role' => Role::class, ], @@ -142,7 +145,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. diff --git a/config/press.php b/config/press.php index e9114e7dd..e8eaa96ad 100644 --- a/config/press.php +++ b/config/press.php @@ -1,5 +1,8 @@ Moox\Press\Models\WpUser::class, + 'wpModel' => WpUser::class, /* |-------------------------------------------------------------------------- @@ -1272,7 +1274,7 @@ 'password' => [ 'validation' => [ - 'rules' => Illuminate\Validation\Rules\Password::min(20) + 'rules' => Password::min(20) ->max(64) ->mixedCase() ->numbers() diff --git a/config/security.php b/config/security.php index cbf458d88..0a8123b30 100644 --- a/config/security.php +++ b/config/security.php @@ -1,5 +1,7 @@ [ - 'model' => Moox\User\Models\User::class, + 'model' => User::class, ], /* diff --git a/config/sync.php b/config/sync.php index d717a7641..1e8a9b740 100644 --- a/config/sync.php +++ b/config/sync.php @@ -1,5 +1,17 @@ '\Moox\Sync\Models\Sync', - 'resource' => '\Moox\Sync\Resources\SyncResource', - 'api_controller' => '\Moox\Sync\Http\Controllers\Api\SyncController', + 'model' => Sync::class, + 'resource' => SyncResource::class, + 'api_controller' => SyncController::class, ], 'Platform' => [ 'api' => [ @@ -189,9 +200,9 @@ 'destroy', ], ], - 'model' => '\Moox\Sync\Models\Platform', - 'resource' => '\Moox\Sync\Resources\PlatformResource', - 'api_controller' => '\Moox\Sync\Http\Controllers\Api\PlatformController', + 'model' => Platform::class, + 'resource' => PlatformResource::class, + 'api_controller' => PlatformController::class, ], ], @@ -281,8 +292,8 @@ */ 'models_with_platform_relations' => [ - 'App\Models\User', - 'Moox\User\Models\User', + User::class, + \Moox\User\Models\User::class, 'Moox\Press\Models\User', // Add any other models here ], @@ -302,8 +313,8 @@ */ 'models_with_syncable_relations' => [ - 'Moox\User\Models\User', - 'Moox\Press\Models\WpUser' => [ + \Moox\User\Models\User::class, + WpUser::class => [ 'Moox\UserSession\Models\Session', ], // Add any other models here @@ -377,7 +388,7 @@ */ 'transformer_bindings' => [ - \Moox\Press\Models\WpUser::class => \Moox\Press\Transformer\WpUserTransformer::class, + WpUser::class => WpUserTransformer::class, ], /* @@ -392,7 +403,7 @@ */ 'sync_bindings' => [ - \Moox\Press\Models\WpUser::class => \Moox\Press\Handlers\WpUserSyncHandler::class, + WpUser::class => WpUserSyncHandler::class, ], /* @@ -468,7 +479,7 @@ 'file_sync_max_size_http' => 2 * 1024 * 1024, // 5 MB 'file_sync_max_size_rsync' => 50 * 1024 * 1024, // 50 MB, not implemented yet - 'file_sync_chunk_size_http' => 1 * 1024 * 1024, // 1 MB + 'file_sync_chunk_size_http' => 1024 * 1024, // 1 MB /* |-------------------------------------------------------------------------- @@ -535,6 +546,6 @@ */ 'file_sync_resolver' => [ - \Moox\Press\Models\WpUser::class => \Moox\Press\Resolver\WpUserFileResolver::class, + WpUser::class => WpUserFileResolver::class, ], ]; diff --git a/config/tag.php b/config/tag.php index e8d87c09c..6774242df 100644 --- a/config/tag.php +++ b/config/tag.php @@ -1,5 +1,7 @@ \App\Models\User::class, + 'user_model' => User::class, /* |-------------------------------------------------------------------------- diff --git a/config/trainings.php b/config/trainings.php index d2c677de6..6a66e8b89 100644 --- a/config/trainings.php +++ b/config/trainings.php @@ -1,5 +1,7 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, ], /* diff --git a/config/user-device.php b/config/user-device.php index db64b3796..f721f1aa4 100644 --- a/config/user-device.php +++ b/config/user-device.php @@ -1,5 +1,7 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, 'Moox Users' => \Moox\User\Models\User::class, ], diff --git a/config/user-session.php b/config/user-session.php index c9059e362..d8e5ba56d 100644 --- a/config/user-session.php +++ b/config/user-session.php @@ -1,5 +1,9 @@ 'user_id', 'operator' => '=', - 'value' => function () { - return auth()->user()->id; - }, + 'value' => fn () => auth()->user()->id, ], ], ], @@ -78,7 +79,7 @@ [ 'field' => 'user_type', 'operator' => '=', - 'value' => 'Moox\User\Models\User', + 'value' => User::class, // TODO: Not implemented yet 'hide-if-not-exists' => true, ], @@ -91,7 +92,7 @@ [ 'field' => 'user_type', 'operator' => '=', - 'value' => 'Moox\Press\Models\WpUser', + 'value' => WpUser::class, // TODO: Not implemented yet 'hide-if-not-exists' => true, ], @@ -144,9 +145,9 @@ */ 'user_models' => [ 'App Users' => \App\Models\User::class, - 'Moox Users' => \Moox\User\Models\User::class, + 'Moox Users' => User::class, ], - 'device_model' => \Moox\UserDevice\Models\UserDevice::class, + 'device_model' => UserDevice::class, /* | Session expiry for different scopes, currently not implemented! diff --git a/config/user.php b/config/user.php index b44e314fa..446d33bc7 100644 --- a/config/user.php +++ b/config/user.php @@ -1,5 +1,7 @@ [ 'validation' => [ - 'rules' => Illuminate\Validation\Rules\Password::min(20) + 'rules' => Password::min(20) ->max(64) ->mixedCase() ->numbers() diff --git a/packages/audit/src/Commands/InstallCommand.php b/packages/audit/src/Commands/InstallCommand.php index 6d14353b8..2c036382f 100644 --- a/packages/audit/src/Commands/InstallCommand.php +++ b/packages/audit/src/Commands/InstallCommand.php @@ -34,7 +34,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -80,6 +80,7 @@ public function publishConfiguration(): void return; } + warning('The Audit config already exist. The config will not be published.'); } } @@ -92,6 +93,7 @@ public function publishMigrations(): void return; } + info('Publishing Audit Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'activitylog-migrations']); } @@ -128,22 +130,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -184,12 +186,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/audit/src/Resources/AuditResource.php b/packages/audit/src/Resources/AuditResource.php index 62f456bbf..b1008294d 100644 --- a/packages/audit/src/Resources/AuditResource.php +++ b/packages/audit/src/Resources/AuditResource.php @@ -18,16 +18,19 @@ use Moox\Audit\Resources\AuditResource\Pages\ViewAudit; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; +use Override; use Spatie\Activitylog\Models\Activity; class AuditResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = Activity::class; protected static ?string $navigationIcon = 'gmdi-troubleshoot'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -126,6 +129,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -176,6 +180,7 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ @@ -183,6 +188,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -191,31 +197,37 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('audit.resources.audit.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('audit.resources.audit.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('audit.resources.audit.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('audit.resources.audit.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('audit.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('audit.navigation_sort') + 1; diff --git a/packages/builder/config/builder.php b/packages/builder/config/builder.php index 45678b3ba..ce59e9ea4 100644 --- a/packages/builder/config/builder.php +++ b/packages/builder/config/builder.php @@ -1,5 +1,47 @@ [ 'fields' => [ - 'boolean' => \Moox\Builder\Blocks\Fields\Boolean::class, - 'builder' => \Moox\Builder\Blocks\Fields\Builder::class, - 'checkbox-list' => \Moox\Builder\Blocks\Fields\CheckboxList::class, - 'color-picker' => \Moox\Builder\Blocks\Fields\ColorPicker::class, - 'date' => \Moox\Builder\Blocks\Fields\Date::class, - 'date-time' => \Moox\Builder\Blocks\Fields\DateTime::class, - 'file-upload' => \Moox\Builder\Blocks\Fields\FileUpload::class, - 'hidden' => \Moox\Builder\Blocks\Fields\Hidden::class, - 'image' => \Moox\Builder\Blocks\Fields\Image::class, - 'key-value' => \Moox\Builder\Blocks\Fields\KeyValue::class, - 'markdown-editor' => \Moox\Builder\Blocks\Fields\MarkdownEditor::class, - 'multi-select' => \Moox\Builder\Blocks\Fields\MultiSelect::class, - 'number' => \Moox\Builder\Blocks\Fields\Number::class, - 'radio' => \Moox\Builder\Blocks\Fields\Radio::class, - 'relationship' => \Moox\Builder\Blocks\Fields\Relationship::class, - 'repeater' => \Moox\Builder\Blocks\Fields\Repeater::class, - 'rich-editor' => \Moox\Builder\Blocks\Fields\RichEditor::class, - 'select' => \Moox\Builder\Blocks\Fields\Select::class, - 'tags-input' => \Moox\Builder\Blocks\Fields\TagsInput::class, - 'text' => \Moox\Builder\Blocks\Fields\Text::class, - 'textarea' => \Moox\Builder\Blocks\Fields\TextArea::class, - 'toggle' => \Moox\Builder\Blocks\Fields\Toggle::class, - 'toggle-buttons' => \Moox\Builder\Blocks\Fields\ToggleButtons::class, + 'boolean' => Boolean::class, + 'builder' => Builder::class, + 'checkbox-list' => CheckboxList::class, + 'color-picker' => ColorPicker::class, + 'date' => Date::class, + 'date-time' => DateTime::class, + 'file-upload' => FileUpload::class, + 'hidden' => Hidden::class, + 'image' => Image::class, + 'key-value' => KeyValue::class, + 'markdown-editor' => MarkdownEditor::class, + 'multi-select' => MultiSelect::class, + 'number' => Number::class, + 'radio' => Radio::class, + 'relationship' => Relationship::class, + 'repeater' => Repeater::class, + 'rich-editor' => RichEditor::class, + 'select' => Select::class, + 'tags-input' => TagsInput::class, + 'text' => Text::class, + 'textarea' => TextArea::class, + 'toggle' => Toggle::class, + 'toggle-buttons' => ToggleButtons::class, ], 'features' => [ - 'custom-demo' => \Moox\Builder\Blocks\Features\CustomDemo::class, - 'simple-status' => \Moox\Builder\Blocks\Features\SimpleStatus::class, - 'simple-type' => \Moox\Builder\Blocks\Features\SimpleType::class, - 'tabs' => \Moox\Builder\Blocks\Features\Tabs::class, + 'custom-demo' => CustomDemo::class, + 'simple-status' => SimpleStatus::class, + 'simple-type' => SimpleType::class, + 'tabs' => Tabs::class, ], 'sections' => [ - 'simple-address' => \Moox\Builder\Blocks\Sections\SimpleAddressSection::class, + 'simple-address' => SimpleAddressSection::class, ], 'singles' => [ - 'light' => \Moox\Builder\Blocks\Singles\Light::class, - 'simple' => \Moox\Builder\Blocks\Singles\Simple::class, - 'soft-delete' => \Moox\Builder\Blocks\Singles\SoftDelete::class, + 'light' => Light::class, + 'simple' => Simple::class, + 'soft-delete' => SoftDelete::class, ], ], @@ -74,7 +116,7 @@ 'path' => '%BasePath%\Models', 'namespace' => '%BaseNamespace%\\Models', 'template' => __DIR__.'/../src/Templates/Entity/model.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\ModelGenerator::class, + 'generator' => ModelGenerator::class, ], 'resource' => [ 'path' => '%BasePath%\Resources', @@ -86,28 +128,28 @@ 'Edit' => __DIR__.'/../src/Templates/Entity/pages/edit.php.stub', 'View' => __DIR__.'/../src/Templates/Entity/pages/view.php.stub', ], - 'generator' => \Moox\Builder\Generators\Entity\ResourceGenerator::class, + 'generator' => ResourceGenerator::class, ], 'migration' => [ 'path' => 'database\migrations', 'template' => __DIR__.'/../src/Templates/Entity/migration.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\MigrationGenerator::class, + 'generator' => MigrationGenerator::class, ], 'plugin' => [ 'path' => '%BasePath%\Filament\Plugins', 'namespace' => '%BaseNamespace%\\Filament\\Plugins', 'template' => __DIR__.'/../src/Templates/Entity/plugin.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\PluginGenerator::class, + 'generator' => PluginGenerator::class, ], 'translation' => [ 'path' => 'lang\%locale%\entities', 'template' => __DIR__.'/../src/Templates/Entity/translation.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\TranslationGenerator::class, + 'generator' => TranslationGenerator::class, ], 'config' => [ 'path' => 'config\entities', 'template' => __DIR__.'/../src/Templates/Entity/config.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\ConfigGenerator::class, + 'generator' => ConfigGenerator::class, ], ], ], @@ -119,7 +161,7 @@ 'path' => '%BasePath%\Models', 'namespace' => '%BaseNamespace%\\Models', 'template' => __DIR__.'/../src/Templates/Entity/model.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\ModelGenerator::class, + 'generator' => ModelGenerator::class, ], 'resource' => [ 'path' => '%BasePath%\Resources', @@ -131,28 +173,28 @@ 'Edit' => __DIR__.'/../src/Templates/Entity/pages/edit.php.stub', 'View' => __DIR__.'/../src/Templates/Entity/pages/view.php.stub', ], - 'generator' => \Moox\Builder\Generators\Entity\ResourceGenerator::class, + 'generator' => ResourceGenerator::class, ], 'plugin' => [ 'path' => '%BasePath%\Filament\Plugins', 'namespace' => '%BaseNamespace%\\Filament\\Plugins', 'template' => __DIR__.'/../src/Templates/Entity/plugin.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\PluginGenerator::class, + 'generator' => PluginGenerator::class, ], 'migration' => [ 'path' => 'database\migrations', 'template' => __DIR__.'/../src/Templates/Entity/migration.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\MigrationGenerator::class, + 'generator' => MigrationGenerator::class, ], 'translation' => [ 'path' => 'lang\%locale%\entities', 'template' => __DIR__.'/../src/Templates/Entity/translation.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\TranslationGenerator::class, + 'generator' => TranslationGenerator::class, ], 'config' => [ 'path' => 'config\entities', 'template' => __DIR__.'/../src/Templates/Entity/config.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\ConfigGenerator::class, + 'generator' => ConfigGenerator::class, ], ], ], @@ -211,7 +253,7 @@ 'path' => '%BasePath%\Models', 'namespace' => '%BaseNamespace%\\Models', 'template' => __DIR__.'/../src/Templates/Entity/model.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\ModelGenerator::class, + 'generator' => ModelGenerator::class, ], 'resource' => [ 'path' => '%BasePath%\Resources', @@ -223,17 +265,17 @@ 'Edit' => __DIR__.'/../src/Templates/Entity/pages/edit.php.stub', 'View' => __DIR__.'/../src/Templates/Entity/pages/view.php.stub', ], - 'generator' => \Moox\Builder\Generators\Entity\ResourceGenerator::class, + 'generator' => ResourceGenerator::class, ], 'translation' => [ 'path' => 'lang\%locale%\previews', 'template' => __DIR__.'/../src/Templates/Entity/translation.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\TranslationGenerator::class, + 'generator' => TranslationGenerator::class, ], 'config' => [ 'path' => 'config\previews', 'template' => __DIR__.'/../src/Templates/Entity/config.php.stub', - 'generator' => \Moox\Builder\Generators\Entity\ConfigGenerator::class, + 'generator' => ConfigGenerator::class, ], ], 'should_migrate' => true, @@ -252,19 +294,19 @@ 'presets' => [ 'light-item' => [ - 'class' => \Moox\Builder\Presets\LightItemPreset::class, + 'class' => LightItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], 'simple-item' => [ - 'class' => \Moox\Builder\Presets\SimpleItemPreset::class, + 'class' => SimpleItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], 'soft-delete-item' => [ - 'class' => \Moox\Builder\Presets\SoftDeleteItemPreset::class, + 'class' => SoftDeleteItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], 'full-item' => [ - 'class' => \Moox\Builder\Presets\FullItemPreset::class, + 'class' => FullItemPreset::class, 'generators' => ['model', 'migration', 'resource'], ], ], diff --git a/packages/builder/resources/lang/hr/translations.php b/packages/builder/resources/lang/hr/translations.php index a145e7504..565609582 100644 --- a/packages/builder/resources/lang/hr/translations.php +++ b/packages/builder/resources/lang/hr/translations.php @@ -1,16 +1,7 @@ '', - 'plural' => '', - 'breadcrumb' => '', - 'title' => '', - 'navigation_label' => '', - 'navigation_group' => '', - 'totalone' => '', - 'totaltwo' => '', - 'totalthree' => '', - 'name' => 'Ime', - 'started_at' => 'Pokrenuto', - 'failed' => 'neuspjelo', -]; +return array ( + 'name' => 'Ime', + 'started_at' => 'Pokrenuto', + 'failed' => 'neuspjelo', +); diff --git a/packages/builder/src/Blocks/AbstractBlock.php b/packages/builder/src/Blocks/AbstractBlock.php index be8bebacc..a862df0d1 100644 --- a/packages/builder/src/Blocks/AbstractBlock.php +++ b/packages/builder/src/Blocks/AbstractBlock.php @@ -129,13 +129,13 @@ abstract class AbstractBlock protected ?object $context = null; - /** @var array */ + /** @var array */ protected array $requiredBlocks = []; - /** @var array */ + /** @var array */ protected array $containsBlocks = []; - /** @var array */ + /** @var array */ protected array $incompatibleBlocks = []; protected array $constructorParameters = []; @@ -204,6 +204,7 @@ public function getUseStatements(string $path, ?string $subPath = null): array if (! isset($current[$part])) { return []; } + $current = $current[$part]; } @@ -230,6 +231,7 @@ public function getTraits(string $path): array if (! isset($current[$part])) { return []; } + $current = $current[$part]; } @@ -312,9 +314,11 @@ protected function addCast(string $cast): self if (! isset($this->casts['model'])) { $this->casts['model'] = []; } + if (! is_array($this->casts['model'])) { $this->casts['model'] = [$this->casts['model']]; } + $this->casts['model'][] = $cast; return $this; @@ -354,7 +358,7 @@ protected function addTrait(string $context, string $trait): self protected function addMethod(string $context, string $method, string $type = ''): self { - if ($type) { + if ($type !== '' && $type !== '0') { $this->methods[$context][$type][] = $method; } else { $this->methods[$context][] = $method; @@ -400,7 +404,7 @@ protected function addAction(string $context, string $action): self protected function addPageAction(string $page, string $action, string $position = ''): self { - if ($position) { + if ($position !== '' && $position !== '0') { $this->actions['pages'][$page][$position][] = $action; } else { $this->actions['pages'][$page][] = $action; @@ -468,7 +472,7 @@ public function resolveBlockDependencies(array $blocks): array foreach ($block->includedBlocks as $includedBlock) { $resolvedBlocks = array_filter( $resolvedBlocks, - fn ($b) => ! ($b instanceof $includedBlock) + fn ($b): bool => ! ($b instanceof $includedBlock) ); } } @@ -538,7 +542,7 @@ public function getOptions(): array protected function flattenArray(array $array): array { $result = []; - array_walk_recursive($array, function ($value) use (&$result) { + array_walk_recursive($array, function ($value) use (&$result): void { if (is_string($value)) { $result[] = $value; } @@ -564,17 +568,17 @@ public function getTableActions(): array public function getPageActions(string $page): array { - return $this->getActions("pages.{$page}"); + return $this->getActions('pages.'.$page); } public function getHeaderActions(string $page): array { - return $this->getActions("pages.{$page}.header"); + return $this->getActions(sprintf('pages.%s.header', $page)); } public function getFooterActions(string $page): array { - return $this->getActions("pages.{$page}.footer"); + return $this->getActions(sprintf('pages.%s.footer', $page)); } public function getActions(string $path): array @@ -586,6 +590,7 @@ public function getActions(string $path): array if (! isset($current[$part])) { return []; } + $current = $current[$part]; } @@ -789,7 +794,7 @@ protected function addSection(string $name, int $order = 0): SectionBuilder public function getSections(): array { - Log::info('Getting sections for: '.get_class($this)); + Log::info('Getting sections for: '.static::class); Log::info('Current sections structure', ['sections' => $this->sections]); // Migrate old fields to sections if they exist @@ -816,6 +821,7 @@ protected function addFormField(string $field): void if (! isset($this->sections['form'])) { $this->addSection('form')->withFields([]); } + $this->sections['form']['fields'][] = $field; } @@ -825,6 +831,7 @@ protected function addMetaField(string $field): void if (! isset($this->sections['meta'])) { $this->addSection('meta')->asMeta()->withFields([]); } + $this->sections['meta']['fields'][] = $field; } diff --git a/packages/builder/src/Blocks/Features/CustomDemo.php b/packages/builder/src/Blocks/Features/CustomDemo.php index 667b946b9..a1a238058 100644 --- a/packages/builder/src/Blocks/Features/CustomDemo.php +++ b/packages/builder/src/Blocks/Features/CustomDemo.php @@ -7,6 +7,9 @@ use Moox\Builder\Blocks\AbstractBlock; use Moox\Builder\Blocks\Singles\Simple; use Moox\Builder\Blocks\Singles\SoftDelete; +use Moox\Core\Traits\Publish\SinglePublishInListPage; +use Moox\Core\Traits\Publish\SinglePublishInModel; +use Moox\Core\Traits\Publish\SinglePublishInResource; class CustomDemo extends AbstractBlock { @@ -42,9 +45,9 @@ public function __construct( ], ]; - $this->traits['model'] = ['Moox\Core\Traits\Publish\SinglePublishInModel']; - $this->traits['resource'] = ['Moox\Core\Traits\Publish\SinglePublishInResource']; - $this->traits['pages']['list'] = ['Moox\Core\Traits\Publish\SinglePublishInListPage']; + $this->traits['model'] = [SinglePublishInModel::class]; + $this->traits['resource'] = [SinglePublishInResource::class]; + $this->traits['pages']['list'] = [SinglePublishInListPage::class]; $this->methods['model'] = [ 'scopes' => [ diff --git a/packages/builder/src/Blocks/Features/SimpleStatus.php b/packages/builder/src/Blocks/Features/SimpleStatus.php index e7039e1ef..81ebdb067 100644 --- a/packages/builder/src/Blocks/Features/SimpleStatus.php +++ b/packages/builder/src/Blocks/Features/SimpleStatus.php @@ -29,13 +29,13 @@ public function __construct( ], ]; - $options = '['.implode(', ', array_map(fn ($value) => "'$value' => '$value'", $this->enum)).']'; + $options = '['.implode(', ', array_map(fn ($value): string => sprintf("'%s' => '%s'", $value, $value), $this->enum)).']'; $this->addSection('status') ->asMeta() ->hideHeader() ->withFields([ - 'Select::make(\''.$this->name.'\') + "Select::make('".$this->name.'\') ->label(\''.$this->label.'\') ->placeholder(__(\'core::core.status\')) ->options('.$options.') @@ -43,14 +43,14 @@ public function __construct( ]); $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')" + sprintf("TextColumn::make('%s')", $this->name) .($this->sortable ? '->sortable()' : '') .($this->searchable ? '->searchable()' : '') .($this->toggleable ? '->toggleable()' : ''), ]; $this->migrations['fields'] = [ - "\$table->enum('{$this->name}', ['".implode("', '", $enum)."'])" + sprintf("\$table->enum('%s', ['", $this->name).implode("', '", $enum)."'])" .($this->nullable ? '->nullable()' : ''), ]; @@ -67,7 +67,7 @@ public function __construct( 'icon' => 'gmdi-filter-list', 'query' => [], ], - ...array_map(fn ($status) => [ + ...array_map(fn ($status): array => [ 'label' => $status, 'icon' => 'gmdi-filter-list', 'query' => [ diff --git a/packages/builder/src/Blocks/Features/SimpleType.php b/packages/builder/src/Blocks/Features/SimpleType.php index 47550c7c7..3624c89bb 100644 --- a/packages/builder/src/Blocks/Features/SimpleType.php +++ b/packages/builder/src/Blocks/Features/SimpleType.php @@ -20,7 +20,7 @@ public function __construct( ) { parent::__construct($name, $label, $description, $nullable); - $options = '['.implode(', ', array_map(fn ($value) => "'$value' => '$value'", $this->enum)).']'; + $options = '['.implode(', ', array_map(fn ($value): string => sprintf("'%s' => '%s'", $value, $value), $this->enum)).']'; $this->useStatements['resource'] = [ 'forms' => ['use Filament\Forms\Components\Select;'], @@ -35,7 +35,7 @@ public function __construct( ->asMeta() ->hideHeader() ->withFields([ - 'Select::make(\''.$this->name.'\') + "Select::make('".$this->name.'\') ->label(\''.$this->label.'\') ->placeholder(__(\'core::core.type\')) ->options('.$options.') @@ -43,14 +43,14 @@ public function __construct( ]); $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')" + sprintf("TextColumn::make('%s')", $this->name) .($this->sortable ? '->sortable()' : '') .($this->searchable ? '->searchable()' : '') .($this->toggleable ? '->toggleable()' : ''), ]; $this->migrations['fields'] = [ - "\$table->enum('{$this->name}', ['".implode("', '", $enum)."'])" + sprintf("\$table->enum('%s', ['", $this->name).implode("', '", $enum)."'])" .($this->nullable ? '->nullable()' : ''), ]; @@ -67,7 +67,7 @@ public function __construct( 'icon' => 'gmdi-filter-list', 'query' => [], ], - ...array_map(fn ($type) => [ + ...array_map(fn ($type): array => [ 'label' => $type, 'icon' => 'gmdi-filter-list', 'query' => [ diff --git a/packages/builder/src/Blocks/Features/Tabs.php b/packages/builder/src/Blocks/Features/Tabs.php index ecd534924..3d3a34b47 100644 --- a/packages/builder/src/Blocks/Features/Tabs.php +++ b/packages/builder/src/Blocks/Features/Tabs.php @@ -3,6 +3,8 @@ namespace Moox\Builder\Blocks\Features; use Moox\Builder\Blocks\AbstractBlock; +use Moox\Core\Traits\Tabs\TabsInListPage; +use Moox\Core\Traits\Tabs\TabsInResource; class Tabs extends AbstractBlock { @@ -13,8 +15,8 @@ public function __construct( ) { parent::__construct($name, $label, $description); - $this->traits['resource'] = ['Moox\Core\Traits\Tabs\TabsInResource']; - $this->traits['pages']['list'] = ['Moox\Core\Traits\Tabs\TabsInListPage']; + $this->traits['resource'] = [TabsInResource::class]; + $this->traits['pages']['list'] = [TabsInListPage::class]; $this->methods['pages']['list']['mount'] = '$this->mountTabsInListPage();'; diff --git a/packages/builder/src/Blocks/Fields/Boolean.php b/packages/builder/src/Blocks/Fields/Boolean.php index df03b8174..38b79132b 100644 --- a/packages/builder/src/Blocks/Fields/Boolean.php +++ b/packages/builder/src/Blocks/Fields/Boolean.php @@ -38,17 +38,17 @@ public function __construct( ]; $this->filters['resource'] = [ - "BooleanFilter::make('{$this->name}')", + sprintf("BooleanFilter::make('%s')", $this->name), ]; $this->migrations['fields'] = [ - "\$table->boolean('{$this->name}')" + sprintf("\$table->boolean('%s')", $this->name) .($this->nullable ? '->nullable()' : '') .($this->default ? '->default(true)' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => $this->default ? 'true' : 'fake()->boolean()', + $this->name => $this->default ? 'true' : 'fake()->boolean()', ]; } } diff --git a/packages/builder/src/Blocks/Fields/Builder.php b/packages/builder/src/Blocks/Fields/Builder.php index 5fe678654..b40dfd1ce 100644 --- a/packages/builder/src/Blocks/Fields/Builder.php +++ b/packages/builder/src/Blocks/Fields/Builder.php @@ -47,16 +47,16 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->json('{$this->name}')" + sprintf("\$table->json('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => '[]', + $this->name => '[]', ]; $this->casts['model'] = [ - "'{$this->name}' => 'array'", + sprintf("'%s' => 'array'", $this->name), ]; } } diff --git a/packages/builder/src/Blocks/Fields/CheckboxList.php b/packages/builder/src/Blocks/Fields/CheckboxList.php index aeecbb195..2fd76cfaa 100644 --- a/packages/builder/src/Blocks/Fields/CheckboxList.php +++ b/packages/builder/src/Blocks/Fields/CheckboxList.php @@ -43,12 +43,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->json('{$this->name}')" + sprintf("\$table->json('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->randomElements('.var_export($this->options, true).', 2)', + $this->name => 'fake()->randomElements('.var_export($this->options, true).', 2)', ]; } } diff --git a/packages/builder/src/Blocks/Fields/ColorPicker.php b/packages/builder/src/Blocks/Fields/ColorPicker.php index 10816a715..8aeba817c 100644 --- a/packages/builder/src/Blocks/Fields/ColorPicker.php +++ b/packages/builder/src/Blocks/Fields/ColorPicker.php @@ -31,16 +31,16 @@ public function __construct( ]); $this->tableColumns['resource'] = [ - "ColorColumn::make('{$this->name}')", + sprintf("ColorColumn::make('%s')", $this->name), ]; $this->migrations['fields'] = [ - "\$table->string('{$this->name}', 7)" + sprintf("\$table->string('%s', 7)", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->hexColor()', + $this->name => 'fake()->hexColor()', ]; } } diff --git a/packages/builder/src/Blocks/Fields/Date.php b/packages/builder/src/Blocks/Fields/Date.php index 43bf03f43..52a7a2a0e 100644 --- a/packages/builder/src/Blocks/Fields/Date.php +++ b/packages/builder/src/Blocks/Fields/Date.php @@ -38,16 +38,16 @@ public function __construct( ]; $this->filters['resource'] = [ - "DateFilter::make('{$this->name}')", + sprintf("DateFilter::make('%s')", $this->name), ]; $this->migrations['fields'] = [ - "\$table->date('{$this->name}')" + sprintf("\$table->date('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->date()', + $this->name => 'fake()->date()', ]; } } diff --git a/packages/builder/src/Blocks/Fields/DateTime.php b/packages/builder/src/Blocks/Fields/DateTime.php index 331d59d3b..d5164bf46 100644 --- a/packages/builder/src/Blocks/Fields/DateTime.php +++ b/packages/builder/src/Blocks/Fields/DateTime.php @@ -33,9 +33,9 @@ public function __construct( $this->useStatements = [ 'resource' => [ - 'forms' => ["use Filament\Forms\Components\\{$componentClass};"], + 'forms' => [sprintf('use Filament\Forms\Components\%s;', $componentClass)], 'columns' => ['use Filament\Tables\Columns\TextColumn;'], - 'filters' => ["use Filament\Tables\Filters\\{$filterClass};"], + 'filters' => [sprintf('use Filament\Tables\Filters\%s;', $filterClass)], ], ]; @@ -47,22 +47,22 @@ public function __construct( ]; $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')" + sprintf("TextColumn::make('%s')", $this->name) .'->{'.$this->type.'}()' .($this->sortable ? '->sortable()' : ''), ]; $this->filters['resource'] = [ - "{$filterClass}::make('{$this->name}')", + sprintf("%s::make('%s')", $filterClass, $this->name), ]; $this->migrations['fields'] = [ - "\$table->{$this->type}('{$this->name}')" + sprintf("\$table->%s('%s')", $this->type, $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => match ($this->type) { + $this->name => match ($this->type) { 'date' => 'fake()->date()', 'time' => 'fake()->time()', default => 'fake()->dateTime()', diff --git a/packages/builder/src/Blocks/Fields/FileUpload.php b/packages/builder/src/Blocks/Fields/FileUpload.php index ec41cf935..628a10122 100644 --- a/packages/builder/src/Blocks/Fields/FileUpload.php +++ b/packages/builder/src/Blocks/Fields/FileUpload.php @@ -33,21 +33,21 @@ public function __construct( ->directory('{$this->directory}')" .($this->multiple ? '->multiple()' : '') .($this->acceptedFileTypes ? "->acceptedFileTypes(['".implode("','", $this->acceptedFileTypes)."'])" : '') - ."->maxSize({$this->maxSize})" + .sprintf('->maxSize(%d)', $this->maxSize) .($this->nullable ? '' : '->required()'), ]; $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')", + sprintf("TextColumn::make('%s')", $this->name), ]; $this->migrations['fields'] = [ - '$table->'.($this->multiple ? 'json' : 'string')."('{$this->name}')" + '$table->'.($this->multiple ? 'json' : 'string').sprintf("('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => $this->multiple + $this->name => $this->multiple ? '[]' : "''", ]; diff --git a/packages/builder/src/Blocks/Fields/Hidden.php b/packages/builder/src/Blocks/Fields/Hidden.php index eb61299e9..05ef6b0ca 100644 --- a/packages/builder/src/Blocks/Fields/Hidden.php +++ b/packages/builder/src/Blocks/Fields/Hidden.php @@ -24,7 +24,7 @@ public function __construct( ]; $this->formFields['resource'] = [ - "Hidden::make('{$this->name}')", + sprintf("Hidden::make('%s')", $this->name), ]; $this->tableColumns['resource'] = [ @@ -33,12 +33,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->string('{$this->name}')" + sprintf("\$table->string('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->word()', + $this->name => 'fake()->word()', ]; } } diff --git a/packages/builder/src/Blocks/Fields/KeyValue.php b/packages/builder/src/Blocks/Fields/KeyValue.php index 8d4ca4d10..daea10016 100644 --- a/packages/builder/src/Blocks/Fields/KeyValue.php +++ b/packages/builder/src/Blocks/Fields/KeyValue.php @@ -32,8 +32,8 @@ public function __construct( "KeyValue::make('{$this->name}') ->label('{$this->label}')" .($this->nullable ? '' : '->required()') - .(! $this->keyLabel ? '->disableKeyLabel()' : '') - .(! $this->valueLabel ? '->disableValueLabel()' : '') + .($this->keyLabel ? '' : '->disableKeyLabel()') + .($this->valueLabel ? '' : '->disableValueLabel()') .($this->reorderable ? '->reorderable()' : '') .($this->keyOptions ? '->keyOptions('.var_export($this->keyOptions, true).')' : ''), ]; @@ -49,16 +49,16 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->json('{$this->name}')" + sprintf("\$table->json('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => '[]', + $this->name => '[]', ]; $this->casts['model'] = [ - "'{$this->name}' => 'array'", + sprintf("'%s' => 'array'", $this->name), ]; } } diff --git a/packages/builder/src/Blocks/Fields/MarkdownEditor.php b/packages/builder/src/Blocks/Fields/MarkdownEditor.php index e1376b9f7..5d67fa6ca 100644 --- a/packages/builder/src/Blocks/Fields/MarkdownEditor.php +++ b/packages/builder/src/Blocks/Fields/MarkdownEditor.php @@ -39,12 +39,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->text('{$this->name}')" + sprintf("\$table->text('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->paragraphs(3, true)', + $this->name => 'fake()->paragraphs(3, true)', ]; } } diff --git a/packages/builder/src/Blocks/Fields/MultiSelect.php b/packages/builder/src/Blocks/Fields/MultiSelect.php index c1feee741..9a8c8c8bb 100644 --- a/packages/builder/src/Blocks/Fields/MultiSelect.php +++ b/packages/builder/src/Blocks/Fields/MultiSelect.php @@ -43,12 +43,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->json('{$this->name}')" + sprintf("\$table->json('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->randomElements('.var_export($this->options, true).', 2)', + $this->name => 'fake()->randomElements('.var_export($this->options, true).', 2)', ]; } } diff --git a/packages/builder/src/Blocks/Fields/Number.php b/packages/builder/src/Blocks/Fields/Number.php index 78e21cc60..b180d1dc9 100644 --- a/packages/builder/src/Blocks/Fields/Number.php +++ b/packages/builder/src/Blocks/Fields/Number.php @@ -33,9 +33,9 @@ public function __construct( ->label('{$this->label}') ->numeric()" .($this->nullable ? '' : '->required()') - .($this->min !== null ? "->minValue({$this->min})" : '') - .($this->max !== null ? "->maxValue({$this->max})" : '') - .($this->step !== null ? "->step({$this->step})" : ''), + .($this->min !== null ? sprintf('->minValue(%d)', $this->min) : '') + .($this->max !== null ? sprintf('->maxValue(%d)', $this->max) : '') + .($this->step !== null ? sprintf('->step(%s)', $this->step) : ''), ]; $this->tableColumns['resource'] = [ @@ -44,16 +44,16 @@ public function __construct( ]; $this->filters['resource'] = [ - "NumberFilter::make('{$this->name}')", + sprintf("NumberFilter::make('%s')", $this->name), ]; $this->migrations['fields'] = [ - '$table->'.($this->isFloat ? 'float' : 'integer')."('{$this->name}')" + '$table->'.($this->isFloat ? 'float' : 'integer').sprintf("('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => $this->isFloat ? 'fake()->randomFloat(2)' : 'fake()->randomNumber()', + $this->name => $this->isFloat ? 'fake()->randomFloat(2)' : 'fake()->randomNumber()', ]; } } diff --git a/packages/builder/src/Blocks/Fields/Radio.php b/packages/builder/src/Blocks/Fields/Radio.php index 78e2aee72..7946a9975 100644 --- a/packages/builder/src/Blocks/Fields/Radio.php +++ b/packages/builder/src/Blocks/Fields/Radio.php @@ -35,7 +35,7 @@ public function __construct( ]; $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')", + sprintf("TextColumn::make('%s')", $this->name), ]; $this->filters['resource'] = [ @@ -44,12 +44,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->string('{$this->name}')" + sprintf("\$table->string('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->randomElement('.var_export(array_keys($this->options), true).')', + $this->name => 'fake()->randomElement('.var_export(array_keys($this->options), true).')', ]; } } diff --git a/packages/builder/src/Blocks/Fields/Relationship.php b/packages/builder/src/Blocks/Fields/Relationship.php index bf32e5074..ee91a649e 100644 --- a/packages/builder/src/Blocks/Fields/Relationship.php +++ b/packages/builder/src/Blocks/Fields/Relationship.php @@ -48,7 +48,7 @@ public function __construct( ]; $this->migrations['fields'] = $this->relationshipType === 'belongsTo' - ? ["\$table->foreignId('{$this->name}_id')->constrained()".($this->nullable ? '->nullable()' : '')] + ? [sprintf("\$table->foreignId('%s_id')->constrained()", $this->name).($this->nullable ? '->nullable()' : '')] : []; $this->methods['model']['relations'] = [ diff --git a/packages/builder/src/Blocks/Fields/Repeater.php b/packages/builder/src/Blocks/Fields/Repeater.php index 5a9b244c4..3a38dcb42 100644 --- a/packages/builder/src/Blocks/Fields/Repeater.php +++ b/packages/builder/src/Blocks/Fields/Repeater.php @@ -36,8 +36,8 @@ public function __construct( .($this->nullable ? '' : '->required()') .($this->collapsible ? '->collapsible()' : '') .($this->cloneable ? '->cloneable()' : '') - .($this->minItems ? "->minItems({$this->minItems})" : '') - .($this->maxItems ? "->maxItems({$this->maxItems})" : ''), + .($this->minItems ? sprintf('->minItems(%s)', $this->minItems) : '') + .($this->maxItems ? sprintf('->maxItems(%s)', $this->maxItems) : ''), ]; $this->tableColumns['resource'] = [ @@ -51,16 +51,16 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->json('{$this->name}')" + sprintf("\$table->json('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => '[]', + $this->name => '[]', ]; $this->casts['model'] = [ - "'{$this->name}' => 'array'", + sprintf("'%s' => 'array'", $this->name), ]; } } diff --git a/packages/builder/src/Blocks/Fields/RichEditor.php b/packages/builder/src/Blocks/Fields/RichEditor.php index 5a7e47a56..921eaeffa 100644 --- a/packages/builder/src/Blocks/Fields/RichEditor.php +++ b/packages/builder/src/Blocks/Fields/RichEditor.php @@ -39,16 +39,16 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->text('{$this->name}')" + sprintf("\$table->text('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->paragraphs(3, true)', + $this->name => 'fake()->paragraphs(3, true)', ]; $this->casts['model'] = [ - "'{$this->name}' => 'string'", + sprintf("'%s' => 'string'", $this->name), ]; } } diff --git a/packages/builder/src/Blocks/Fields/Select.php b/packages/builder/src/Blocks/Fields/Select.php index a8411b8ee..277e5d9ba 100644 --- a/packages/builder/src/Blocks/Fields/Select.php +++ b/packages/builder/src/Blocks/Fields/Select.php @@ -24,9 +24,9 @@ public function __construct( $this->useStatements = [ 'resource' => [ - 'forms' => ["use Filament\Forms\Components\\{$componentClass};"], + 'forms' => [sprintf('use Filament\Forms\Components\%s;', $componentClass)], 'columns' => ['use Filament\Tables\Columns\TextColumn;'], - 'filters' => ["use Filament\Tables\Filters\\{$filterClass};"], + 'filters' => [sprintf('use Filament\Tables\Filters\%s;', $filterClass)], ], ]; @@ -39,7 +39,7 @@ public function __construct( ]; $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')" + sprintf("TextColumn::make('%s')", $this->name) .($this->multiple ? '->listWithLineBreaks()' : ''), ]; @@ -49,12 +49,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - '$table->'.($this->multiple ? 'json' : 'string')."('{$this->name}')" + '$table->'.($this->multiple ? 'json' : 'string').sprintf("('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => $this->multiple + $this->name => $this->multiple ? 'fake()->randomElements('.var_export(array_keys($this->options), true).', 2)' : 'fake()->randomElement('.var_export(array_keys($this->options), true).')', ]; diff --git a/packages/builder/src/Blocks/Fields/TagsInput.php b/packages/builder/src/Blocks/Fields/TagsInput.php index 7d0144880..90fb107c1 100644 --- a/packages/builder/src/Blocks/Fields/TagsInput.php +++ b/packages/builder/src/Blocks/Fields/TagsInput.php @@ -31,7 +31,7 @@ public function __construct( ->label('{$this->label}')" .($this->nullable ? '' : '->required()') .($this->suggestions ? '->suggestions('.var_export($this->suggestions, true).')' : '') - .($this->separator ? "->separator('{$this->separator}')" : ''), + .($this->separator ? sprintf("->separator('%s')", $this->separator) : ''), ]; $this->tableColumns['resource'] = [ @@ -40,23 +40,23 @@ public function __construct( ]; $this->filters['resource'] = [ - "MultiSelectFilter::make('{$this->name}')" + sprintf("MultiSelectFilter::make('%s')", $this->name) .($this->suggestions ? '->options('.var_export($this->suggestions, true).')' : ''), ]; $this->migrations['fields'] = [ - "\$table->json('{$this->name}')" + sprintf("\$table->json('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => $this->suggestions + $this->name => $this->suggestions ? 'fake()->randomElements('.var_export($this->suggestions, true).', 2)' : '[fake()->word(), fake()->word()]', ]; $this->casts['model'] = [ - "'{$this->name}' => 'array'", + sprintf("'%s' => 'array'", $this->name), ]; } } diff --git a/packages/builder/src/Blocks/Fields/Text.php b/packages/builder/src/Blocks/Fields/Text.php index b10218ac7..82e3d54b4 100644 --- a/packages/builder/src/Blocks/Fields/Text.php +++ b/packages/builder/src/Blocks/Fields/Text.php @@ -40,23 +40,23 @@ public function __construct( ]); $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')" + sprintf("TextColumn::make('%s')", $this->name) .($this->sortable ? '->sortable()' : '') .($this->searchable ? '->searchable()' : '') .($this->toggleable ? '->toggleable()' : ''), ]; $this->migrations['fields'] = [ - "\$table->string('{$this->name}', {$this->length})" + sprintf("\$table->string('%s', %d)", $this->name, $this->length) .($this->nullable ? '->nullable()' : ''), ]; if ($this->unique) { - $this->migrations['indexes'][] = "\$table->unique('{$this->name}')"; + $this->migrations['indexes'][] = sprintf("\$table->unique('%s')", $this->name); } $this->factories['model']['definitions'] = [ - "{$this->name}" => "fake()->text({$this->length})", + $this->name => sprintf('fake()->text(%d)', $this->length), ]; $this->filters['resource'] = [ diff --git a/packages/builder/src/Blocks/Fields/TextArea.php b/packages/builder/src/Blocks/Fields/TextArea.php index 71dc138be..de5b2aed7 100644 --- a/packages/builder/src/Blocks/Fields/TextArea.php +++ b/packages/builder/src/Blocks/Fields/TextArea.php @@ -31,8 +31,8 @@ public function __construct( ->withFields(["Textarea::make('{$this->name}') ->label('{$this->label}')" .($this->nullable ? '' : '->required()') - .($this->maxLength ? "->maxLength({$this->maxLength})" : '') - .($this->rows ? "->rows({$this->rows})" : ''), + .($this->maxLength ? sprintf('->maxLength(%s)', $this->maxLength) : '') + .($this->rows ? sprintf('->rows(%s)', $this->rows) : ''), ]); $this->tableColumns['resource'] = [ @@ -43,12 +43,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->text('{$this->name}')" + sprintf("\$table->text('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->paragraphs(2, true)', + $this->name => 'fake()->paragraphs(2, true)', ]; } } diff --git a/packages/builder/src/Blocks/Fields/Toggle.php b/packages/builder/src/Blocks/Fields/Toggle.php index 798c57dee..3799ca082 100644 --- a/packages/builder/src/Blocks/Fields/Toggle.php +++ b/packages/builder/src/Blocks/Fields/Toggle.php @@ -32,8 +32,8 @@ public function __construct( ->label('{$this->label}')" .($this->nullable ? '' : '->required()') .($this->default ? '->default(true)' : '') - .($this->onColor ? "->onColor('{$this->onColor}')" : '') - .($this->offColor ? "->offColor('{$this->offColor}')" : ''), + .($this->onColor ? sprintf("->onColor('%s')", $this->onColor) : '') + .($this->offColor ? sprintf("->offColor('%s')", $this->offColor) : ''), ]; $this->tableColumns['resource'] = [ @@ -42,17 +42,17 @@ public function __construct( ]; $this->filters['resource'] = [ - "BooleanFilter::make('{$this->name}')", + sprintf("BooleanFilter::make('%s')", $this->name), ]; $this->migrations['fields'] = [ - "\$table->boolean('{$this->name}')" + sprintf("\$table->boolean('%s')", $this->name) .($this->nullable ? '->nullable()' : '') .($this->default ? '->default(true)' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => $this->default ? 'true' : 'fake()->boolean()', + $this->name => $this->default ? 'true' : 'fake()->boolean()', ]; } } diff --git a/packages/builder/src/Blocks/Fields/ToggleButtons.php b/packages/builder/src/Blocks/Fields/ToggleButtons.php index 8dc1053bb..6194dfa80 100644 --- a/packages/builder/src/Blocks/Fields/ToggleButtons.php +++ b/packages/builder/src/Blocks/Fields/ToggleButtons.php @@ -33,7 +33,7 @@ public function __construct( ]; $this->tableColumns['resource'] = [ - "TextColumn::make('{$this->name}')", + sprintf("TextColumn::make('%s')", $this->name), ]; $this->filters['resource'] = [ @@ -42,12 +42,12 @@ public function __construct( ]; $this->migrations['fields'] = [ - "\$table->string('{$this->name}')" + sprintf("\$table->string('%s')", $this->name) .($this->nullable ? '->nullable()' : ''), ]; $this->factories['model']['definitions'] = [ - "{$this->name}" => 'fake()->randomElement('.var_export(array_keys($this->options), true).')', + $this->name => 'fake()->randomElement('.var_export(array_keys($this->options), true).')', ]; } } diff --git a/packages/builder/src/Blocks/Sections/SimpleAddressSection.php b/packages/builder/src/Blocks/Sections/SimpleAddressSection.php index 69d6118a5..89fd5acd8 100644 --- a/packages/builder/src/Blocks/Sections/SimpleAddressSection.php +++ b/packages/builder/src/Blocks/Sections/SimpleAddressSection.php @@ -5,6 +5,7 @@ namespace Moox\Builder\Blocks\Sections; use Moox\Builder\Blocks\AbstractBlock; +use Override; final class SimpleAddressSection extends AbstractBlock { @@ -33,17 +34,18 @@ public function __construct( ]); $this->migrations['fields'] = [ - "\$table->string('street', {$this->length})" + sprintf("\$table->string('street', %d)", $this->length) .($this->nullable ? '->nullable()' : ''), - "\$table->string('city', {$this->length})" + sprintf("\$table->string('city', %d)", $this->length) .($this->nullable ? '->nullable()' : ''), - "\$table->string('postal_code', {$this->length})" + sprintf("\$table->string('postal_code', %d)", $this->length) .($this->nullable ? '->nullable()' : ''), - "\$table->string('country', {$this->length})" + sprintf("\$table->string('country', %d)", $this->length) .($this->nullable ? '->nullable()' : ''), ]; } + #[Override] public function getFillableFields(): array { return [ diff --git a/packages/builder/src/Blocks/Singles/Light.php b/packages/builder/src/Blocks/Singles/Light.php index f6c1c0d7d..853e7d125 100644 --- a/packages/builder/src/Blocks/Singles/Light.php +++ b/packages/builder/src/Blocks/Singles/Light.php @@ -3,15 +3,20 @@ namespace Moox\Builder\Blocks\Singles; use Moox\Builder\Blocks\AbstractBlock; +use Moox\BuilderPro\Blocks\Singles\Publish; +use Moox\Core\Traits\Base\BaseInCreatePage; +use Moox\Core\Traits\Base\BaseInEditPage; +use Moox\Core\Traits\Base\BaseInListPage; +use Moox\Core\Traits\Base\BaseInResource; +use Moox\Core\Traits\Base\BaseInViewPage; +use Moox\Core\Traits\Simple\SingleSimpleInCreatePage; +use Moox\Core\Traits\Simple\SingleSimpleInEditPage; +use Moox\Core\Traits\Simple\SingleSimpleInListPage; +use Moox\Core\Traits\Simple\SingleSimpleInResource; +use Moox\Core\Traits\Simple\SingleSimpleInViewPage; class Light extends AbstractBlock { - protected array $incompatibleBlocks = [ - 'Moox\Builder\Blocks\Singles\Simple', - 'Moox\BuilderPro\Blocks\Singles\Publish', - 'Moox\Builder\Blocks\Singles\SoftDelete', - ]; - public function __construct( string $name = 'light', string $label = 'Light', @@ -19,25 +24,31 @@ public function __construct( ) { parent::__construct($name, $label, $description); + $this->incompatibleBlocks = [ + Simple::class, + Publish::class, + SoftDelete::class, + ]; + $this->traits['resource'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInResource', - 'Moox\Core\Traits\Base\BaseInResource', + SingleSimpleInResource::class, + BaseInResource::class, ]; $this->traits['pages']['list'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInListPage', - 'Moox\Core\Traits\Base\BaseInListPage', + SingleSimpleInListPage::class, + BaseInListPage::class, ]; $this->traits['pages']['view'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInViewPage', - 'Moox\Core\Traits\Base\BaseInViewPage', + SingleSimpleInViewPage::class, + BaseInViewPage::class, ]; $this->traits['pages']['create'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInCreatePage', - 'Moox\Core\Traits\Base\BaseInCreatePage', + SingleSimpleInCreatePage::class, + BaseInCreatePage::class, ]; $this->traits['pages']['edit'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInEditPage', - 'Moox\Core\Traits\Base\BaseInEditPage', + SingleSimpleInEditPage::class, + BaseInEditPage::class, ]; $this->addSection('meta') diff --git a/packages/builder/src/Blocks/Singles/Simple.php b/packages/builder/src/Blocks/Singles/Simple.php index bc08e1978..a595da737 100644 --- a/packages/builder/src/Blocks/Singles/Simple.php +++ b/packages/builder/src/Blocks/Singles/Simple.php @@ -3,15 +3,22 @@ namespace Moox\Builder\Blocks\Singles; use Moox\Builder\Blocks\AbstractBlock; +use Moox\BuilderPro\Blocks\Singles\Publish; +use Moox\Core\Traits\Base\BaseInCreatePage; +use Moox\Core\Traits\Base\BaseInEditPage; +use Moox\Core\Traits\Base\BaseInListPage; +use Moox\Core\Traits\Base\BaseInModel; +use Moox\Core\Traits\Base\BaseInResource; +use Moox\Core\Traits\Base\BaseInViewPage; +use Moox\Core\Traits\Simple\SingleSimpleInCreatePage; +use Moox\Core\Traits\Simple\SingleSimpleInEditPage; +use Moox\Core\Traits\Simple\SingleSimpleInListPage; +use Moox\Core\Traits\Simple\SingleSimpleInModel; +use Moox\Core\Traits\Simple\SingleSimpleInResource; +use Moox\Core\Traits\Simple\SingleSimpleInViewPage; class Simple extends AbstractBlock { - protected array $incompatibleBlocks = [ - 'Moox\Builder\Blocks\Singles\SoftDelete', - 'Moox\BuilderPro\Blocks\Singles\Publish', - 'Moox\Builder\Blocks\Singles\Light', - ]; - public function __construct( string $name = 'simple', string $label = 'Simple', @@ -19,29 +26,35 @@ public function __construct( ) { parent::__construct($name, $label, $description); + $this->incompatibleBlocks = [ + Light::class, + Publish::class, + SoftDelete::class, + ]; + $this->traits['model'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInModel', - 'Moox\Core\Traits\Base\BaseInModel', + SingleSimpleInModel::class, + BaseInModel::class, ]; $this->traits['resource'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInResource', - 'Moox\Core\Traits\Base\BaseInResource', + SingleSimpleInResource::class, + BaseInResource::class, ]; $this->traits['pages']['list'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInListPage', - 'Moox\Core\Traits\Base\BaseInListPage', + SingleSimpleInListPage::class, + BaseInListPage::class, ]; $this->traits['pages']['view'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInViewPage', - 'Moox\Core\Traits\Base\BaseInViewPage', + SingleSimpleInViewPage::class, + BaseInViewPage::class, ]; $this->traits['pages']['create'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInCreatePage', - 'Moox\Core\Traits\Base\BaseInCreatePage', + SingleSimpleInCreatePage::class, + BaseInCreatePage::class, ]; $this->traits['pages']['edit'] = [ - 'Moox\Core\Traits\Simple\SingleSimpleInEditPage', - 'Moox\Core\Traits\Base\BaseInEditPage', + SingleSimpleInEditPage::class, + BaseInEditPage::class, ]; $this->addSection('meta') diff --git a/packages/builder/src/Blocks/Singles/SoftDelete.php b/packages/builder/src/Blocks/Singles/SoftDelete.php index 4e34c6aff..9ea88a427 100644 --- a/packages/builder/src/Blocks/Singles/SoftDelete.php +++ b/packages/builder/src/Blocks/Singles/SoftDelete.php @@ -5,18 +5,23 @@ namespace Moox\Builder\Blocks\Singles; use Moox\Builder\Blocks\AbstractBlock; +use Moox\BuilderPro\Blocks\Singles\Publish; +use Moox\Core\Traits\Base\BaseInCreatePage; +use Moox\Core\Traits\Base\BaseInEditPage; +use Moox\Core\Traits\Base\BaseInListPage; +use Moox\Core\Traits\Base\BaseInModel; +use Moox\Core\Traits\Base\BaseInResource; +use Moox\Core\Traits\Base\BaseInViewPage; +use Moox\Core\Traits\SoftDelete\SingleSoftDeleteInCreatePage; +use Moox\Core\Traits\SoftDelete\SingleSoftDeleteInEditPage; +use Moox\Core\Traits\SoftDelete\SingleSoftDeleteInListPage; +use Moox\Core\Traits\SoftDelete\SingleSoftDeleteInModel; +use Moox\Core\Traits\SoftDelete\SingleSoftDeleteInResource; +use Moox\Core\Traits\SoftDelete\SingleSoftDeleteInViewPage; +use Override; class SoftDelete extends AbstractBlock { - protected array $containsBlocks = [ - 'Moox\Builder\Blocks\Singles\Simple', - ]; - - protected array $incompatibleBlocks = [ - 'Moox\BuilderPro\Blocks\Singles\Publish', - 'Moox\Builder\Blocks\Singles\Light', - ]; - public function __construct( string $name = 'softDelete', string $label = 'Soft Delete', @@ -24,29 +29,38 @@ public function __construct( ) { parent::__construct($name, $label, $description); + $this->containsBlocks = [ + Simple::class, + ]; + + $this->incompatibleBlocks = [ + Publish::class, + Light::class, + ]; + $this->traits['model'] = [ - 'Moox\Core\Traits\SoftDelete\SingleSoftDeleteInModel', - 'Moox\Core\Traits\Base\BaseInModel', + SingleSoftDeleteInModel::class, + BaseInModel::class, ]; $this->traits['resource'] = [ - 'Moox\Core\Traits\SoftDelete\SingleSoftDeleteInResource', - 'Moox\Core\Traits\Base\BaseInResource', + SingleSoftDeleteInResource::class, + BaseInResource::class, ]; $this->traits['pages']['edit'] = [ - 'Moox\Core\Traits\SoftDelete\SingleSoftDeleteInEditPage', - 'Moox\Core\Traits\Base\BaseInEditPage', + SingleSoftDeleteInEditPage::class, + BaseInEditPage::class, ]; $this->traits['pages']['list'] = [ - 'Moox\Core\Traits\SoftDelete\SingleSoftDeleteInListPage', - 'Moox\Core\Traits\Base\BaseInListPage', + SingleSoftDeleteInListPage::class, + BaseInListPage::class, ]; $this->traits['pages']['view'] = [ - 'Moox\Core\Traits\SoftDelete\SingleSoftDeleteInViewPage', - 'Moox\Core\Traits\Base\BaseInViewPage', + SingleSoftDeleteInViewPage::class, + BaseInViewPage::class, ]; $this->traits['pages']['create'] = [ - 'Moox\Core\Traits\SoftDelete\SingleSoftDeleteInCreatePage', - 'Moox\Core\Traits\Base\BaseInCreatePage', + SingleSoftDeleteInCreatePage::class, + BaseInCreatePage::class, ]; $this->migrations['fields'] = [ @@ -88,6 +102,7 @@ public function getTabs(): array ]; } + #[Override] public function getTableInit(): array { return [ diff --git a/packages/builder/src/BuilderServiceProvider.php b/packages/builder/src/BuilderServiceProvider.php index 38203794b..501ba8a4a 100644 --- a/packages/builder/src/BuilderServiceProvider.php +++ b/packages/builder/src/BuilderServiceProvider.php @@ -18,23 +18,24 @@ use Moox\Builder\Services\File\FileManager; use Moox\Builder\Services\File\FileOperations; use Moox\Builder\Services\Preview\PreviewTableManager; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; class BuilderServiceProvider extends PackageServiceProvider { + #[Override] public function boot(): void { parent::boot(); } + #[Override] public function register(): void { parent::register(); - $this->app->bind('moox.builder.path', function () { - return dirname(__DIR__); - }); + $this->app->bind('moox.builder.path', fn (): string => dirname(__DIR__)); $this->app->register(BuilderPanelProvider::class); @@ -47,20 +48,16 @@ public function register(): void $this->app->singleton(FileOperations::class); $this->app->singleton(FileFormatter::class); - $this->app->singleton(EntityRebuilder::class, function ($app) { - return new EntityRebuilder( - $app->make(EntityCreator::class), - $app->make(BuildManager::class), - $app->make(FileManager::class) - ); - }); + $this->app->singleton(EntityRebuilder::class, fn ($app): EntityRebuilder => new EntityRebuilder( + $app->make(EntityCreator::class), + $app->make(BuildManager::class), + $app->make(FileManager::class) + )); - $this->app->singleton(FileManager::class, function ($app) { - return new FileManager( - $app->make(FileOperations::class), - $app->make(FileFormatter::class) - ); - }); + $this->app->singleton(FileManager::class, fn ($app): FileManager => new FileManager( + $app->make(FileOperations::class), + $app->make(FileFormatter::class) + )); } public function configurePackage(Package $package): void diff --git a/packages/builder/src/Commands/CreateEntityCommand.php b/packages/builder/src/Commands/CreateEntityCommand.php index 55a0b8c02..5b28c01ba 100644 --- a/packages/builder/src/Commands/CreateEntityCommand.php +++ b/packages/builder/src/Commands/CreateEntityCommand.php @@ -4,6 +4,7 @@ namespace Moox\Builder\Commands; +use Exception; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; use Moox\Builder\Contexts\BuildContext; @@ -12,6 +13,7 @@ use Moox\Builder\Services\Build\BuildStateManager; use Moox\Builder\Services\Entity\EntityCreator; use Moox\Builder\Services\Preview\PreviewTableManager; +use Override; class CreateEntityCommand extends AbstractBuilderCommand { @@ -62,8 +64,8 @@ public function handle(): int $context = $this->createContext($name, $package, $preview); $blocks = PresetRegistry::getPresetBlocks($presetName); - if (empty($blocks)) { - $this->error("Preset '{$presetName}' returned no blocks"); + if ($blocks === []) { + $this->error(sprintf("Preset '%s' returned no blocks", $presetName)); return self::FAILURE; } @@ -78,7 +80,7 @@ public function handle(): int $this->entityCreator->setEntityData([ 'singular' => $name, 'plural' => $plural, - 'description' => "A {$name} entity generated with Moox Builder", + 'description' => sprintf('A %s entity generated with Moox Builder', $name), ]); Log::info('Executing entity creation'); @@ -94,20 +96,21 @@ public function handle(): int $this->entityCreator->execute(); - $this->info("Entity {$name} created successfully in {$context->getContextType()} context"); + $this->info(sprintf('Entity %s created successfully in %s context', $name, $context->getContextType())); return self::SUCCESS; - } catch (\Exception $e) { + } catch (Exception $exception) { Log::error('Entity creation failed', [ - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), + 'error' => $exception->getMessage(), + 'trace' => $exception->getTraceAsString(), ]); - $this->error("Failed to create entity: {$e->getMessage()}"); + $this->error('Failed to create entity: '.$exception->getMessage()); return self::FAILURE; } } + #[Override] protected function createContext( string $entityName, ?string $package = null, @@ -122,6 +125,7 @@ protected function createContext( ); } + #[Override] protected function getBuildContext(?bool $preview = false, ?bool $app = false, ?string $package = null): string { if ($context = $this->option('context')) { diff --git a/packages/builder/src/Commands/InstallCommand.php b/packages/builder/src/Commands/InstallCommand.php index 322cfd84d..aa75a24f2 100644 --- a/packages/builder/src/Commands/InstallCommand.php +++ b/packages/builder/src/Commands/InstallCommand.php @@ -34,7 +34,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -80,6 +80,7 @@ public function publishConfiguration(): void return; } + warning('The Builder config already exist. The config will not be published.'); } } @@ -92,6 +93,7 @@ public function publishMigrations(): void return; } + info('Publishing Items Migrations...'); $this->call('vendor:publish', ['--tag' => 'builder-migrations']); } @@ -123,9 +125,7 @@ public function registerPlugins(string $providerPath): void return; } - $availablePlugins = array_map(function ($file) { - return basename($file, '.php'); - }, $pluginFiles); + $availablePlugins = array_map(fn ($file): string => basename((string) $file, '.php'), $pluginFiles); $pluginsToAdd = multiselect( label: 'These plugins will be installed:', @@ -142,22 +142,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -195,12 +195,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/builder/src/Contexts/BuildContext.php b/packages/builder/src/Contexts/BuildContext.php index d2e707385..abc19dabf 100644 --- a/packages/builder/src/Contexts/BuildContext.php +++ b/packages/builder/src/Contexts/BuildContext.php @@ -12,34 +12,19 @@ class BuildContext { public const PREVIEW_PREFIX = 'preview_'; - protected string $contextType; - - protected array $config; - - protected array $blocks; - - protected string $entityName; - protected string $pluralName; protected ?Command $command = null; - protected ?string $preset = null; - public function __construct( - string $contextType, - array $config, - array $blocks = [], - string $entityName = '', + protected string $contextType, + protected array $config, + protected array $blocks = [], + protected string $entityName = '', ?string $pluralName = null, - ?string $preset = null + protected ?string $preset = null ) { - $this->contextType = $contextType; - $this->config = $config; - $this->blocks = $blocks; - $this->entityName = $entityName; - $this->pluralName = $pluralName ?? str($entityName)->plural()->toString(); - $this->preset = $preset; + $this->pluralName = $pluralName ?? str($this->entityName)->plural()->toString(); } public function getContextType(): string @@ -73,16 +58,14 @@ public function getPath(string $type): string $path = $this->config['generators'][$type]['path'] ?? ''; if (empty($path)) { - throw new RuntimeException("Path configuration for {$type} not found"); + throw new RuntimeException(sprintf('Path configuration for %s not found', $type)); } - $path = str_replace( + return str_replace( ['%BasePath%', '%locale%', '\\'], [$basePath, config('app.locale', 'en'), '/'], $path ); - - return $path; } public function getNamespace(string $type): string @@ -91,7 +74,7 @@ public function getNamespace(string $type): string $namespace = $this->config['generators'][$type]['namespace'] ?? ''; if (empty($namespace)) { - throw new RuntimeException("Namespace configuration for {$type} not found"); + throw new RuntimeException(sprintf('Namespace configuration for %s not found', $type)); } return str_replace( @@ -106,7 +89,7 @@ public function getTemplate(string $type): string $template = $this->config['generators'][$type]['template'] ?? null; if (! $template) { - throw new RuntimeException("Template configuration for {$type} not found in config"); + throw new RuntimeException(sprintf('Template configuration for %s not found in config', $type)); } return $template; diff --git a/packages/builder/src/Contexts/ContextFactory.php b/packages/builder/src/Contexts/ContextFactory.php index 2929584ca..576f49476 100644 --- a/packages/builder/src/Contexts/ContextFactory.php +++ b/packages/builder/src/Contexts/ContextFactory.php @@ -39,7 +39,7 @@ public static function create( $contextConfig = array_merge( $contexts[$contextType] ?? [], [ - 'base_path' => base_path("packages/{$packagePath}"), + 'base_path' => base_path('packages/'.$packagePath), 'base_namespace' => $packageNamespace, 'package' => $config['package'], ], @@ -54,7 +54,7 @@ public static function create( } if (! isset($contexts[$contextType])) { - throw new InvalidArgumentException("Invalid context type: {$contextType}"); + throw new InvalidArgumentException('Invalid context type: '.$contextType); } return new BuildContext( diff --git a/packages/builder/src/Generators/Entity/AbstractGenerator.php b/packages/builder/src/Generators/Entity/AbstractGenerator.php index 10ef1d2ce..3b7887711 100644 --- a/packages/builder/src/Generators/Entity/AbstractGenerator.php +++ b/packages/builder/src/Generators/Entity/AbstractGenerator.php @@ -47,7 +47,7 @@ protected function getTemplate(): string $template = $this->context->getConfig()['generators'][$this->getGeneratorType()]['template'] ?? null; if (! $template) { - throw new RuntimeException("Template configuration for {$this->getGeneratorType()} not found"); + throw new RuntimeException(sprintf('Template configuration for %s not found', $this->getGeneratorType())); } return $template; @@ -57,9 +57,7 @@ protected function formatUseStatements(): string { $statements = $this->getUseStatements($this->getGeneratorType()); - return implode("\n", array_map(function ($statement) { - return rtrim($statement, ';').';'; - }, array_unique($statements))); + return implode("\n", array_map(fn ($statement): string => rtrim((string) $statement, ';').';', array_unique($statements))); } protected function formatTraits(): string @@ -72,11 +70,11 @@ protected function formatTraits(): string } } - if (empty($traits)) { + if ($traits === []) { return ''; } - $shortTraits = array_map(function ($trait) { + $shortTraits = array_map(function ($trait): string { $parts = explode('\\', $trait); return end($parts); @@ -106,7 +104,7 @@ protected function formatMethods(): string } } - if (empty($methods)) { + if ($methods === []) { return ''; } @@ -175,7 +173,7 @@ protected function getTableBulkActions(): string protected function loadStub(string $path): string { if (! file_exists($path)) { - throw new RuntimeException("Template not found: {$path}"); + throw new RuntimeException('Template not found: '.$path); } return file_get_contents($path); @@ -188,10 +186,9 @@ protected function replaceTemplateVariables(string $template, array $variables): } $template = preg_replace('/\{\{\s*[a-zA-Z_]+\s*\}\}/', '', $template); - $template = preg_replace('/^\h*\v+/m', '', $template); - $template = preg_replace('/\n\s*\n\s*\n/', "\n\n", $template); + $template = preg_replace('/^\h*\v+/m', '', (string) $template); - return $template; + return preg_replace('/\n\s*\n\s*\n/', "\n\n", (string) $template); } protected function writeFile(string $path, string $content): void @@ -207,7 +204,7 @@ protected function getBlocks(): array protected function resolveBlocks(array $blocks): array { - if (! empty($blocks)) { + if ($blocks !== []) { $firstBlock = reset($blocks); return $firstBlock->resolveBlockDependencies($blocks); diff --git a/packages/builder/src/Generators/Entity/ConfigGenerator.php b/packages/builder/src/Generators/Entity/ConfigGenerator.php index 5c435233f..edd6029e5 100644 --- a/packages/builder/src/Generators/Entity/ConfigGenerator.php +++ b/packages/builder/src/Generators/Entity/ConfigGenerator.php @@ -5,6 +5,7 @@ namespace Moox\Builder\Generators\Entity; use Illuminate\Support\Str; +use InvalidArgumentException; use Moox\Builder\Contexts\BuildContext; use Moox\Builder\Services\File\FileManager; @@ -57,34 +58,36 @@ protected function collectFeatures(): void protected function formatTabs(): string { - if (empty($this->tabs)) { + if ($this->tabs === []) { return '[]'; } $output = "[\n"; foreach ($this->tabs as $key => $tab) { - $output .= " '$key' => [\n"; + $output .= " '{$key}' => [\n"; foreach ($tab as $property => $value) { if (is_array($value)) { - $output .= " '$property' => [\n"; + $output .= " '{$property}' => [\n"; foreach ($value as $queryItem) { $output .= " [\n"; foreach ($queryItem as $field => $fieldValue) { - $formattedValue = is_null($fieldValue) ? 'null' : "'$fieldValue'"; - $output .= " '$field' => $formattedValue,\n"; + $formattedValue = is_null($fieldValue) ? 'null' : sprintf("'%s'", $fieldValue); + $output .= " '{$field}' => {$formattedValue},\n"; } + $output .= " ],\n"; } + $output .= " ],\n"; } else { - $output .= " '$property' => '$value',\n"; + $output .= " '{$property}' => '{$value}',\n"; } } + $output .= " ],\n"; } - $output .= ' ]'; - return $output; + return $output.' ]'; } protected function generateConfigContent(): string @@ -92,14 +95,14 @@ protected function generateConfigContent(): string $entityName = Str::kebab($this->context->getEntityName()); $contextType = $this->context->getContextType(); $translationKey = match ($contextType) { - 'app' => "entities/{$entityName}", - 'preview' => "previews/{$entityName}", - 'package' => $this->context->getConfig()['package']['name']."/{$entityName}", - default => throw new \InvalidArgumentException('Invalid context type: '.$contextType), + 'app' => 'entities/'.$entityName, + 'preview' => 'previews/'.$entityName, + 'package' => $this->context->getConfig()['package']['name'].('/'.$entityName), + default => throw new InvalidArgumentException('Invalid context type: '.$contextType), }; $taxonomies = $this->generateTaxonomiesConfig(); - $taxonomiesConfig = empty($taxonomies) ? '[]' : "[\n {$taxonomies}\n ]"; + $taxonomiesConfig = $taxonomies === '' || $taxonomies === '0' ? '[]' : "[\n {$taxonomies}\n ]"; return " 'trans//{$translationKey}.{$this->getSingularKey()}',\n". @@ -127,7 +130,7 @@ protected function getPluralKey(): string protected function generateTaxonomiesConfig(): string { - if (empty($this->taxonomies)) { + if ($this->taxonomies === []) { return ''; } @@ -155,7 +158,7 @@ protected function generateTaxonomiesConfig(): string protected function generateRelationsConfig(): string { - if (empty($this->relations)) { + if ($this->relations === []) { return ''; } diff --git a/packages/builder/src/Generators/Entity/MigrationGenerator.php b/packages/builder/src/Generators/Entity/MigrationGenerator.php index 648b30545..c72dbf3d6 100644 --- a/packages/builder/src/Generators/Entity/MigrationGenerator.php +++ b/packages/builder/src/Generators/Entity/MigrationGenerator.php @@ -4,6 +4,8 @@ namespace Moox\Builder\Generators\Entity; +use Illuminate\Console\Command; +use InvalidArgumentException; use Moox\Builder\Contexts\BuildContext; use Moox\Builder\Services\File\FileManager; @@ -21,7 +23,7 @@ public function __construct( public function generate(): void { - if ($this->context->getCommand()) { + if ($this->context->getCommand() instanceof Command) { $this->context->getCommand()->info('Starting migration generation...'); } @@ -36,7 +38,7 @@ public function generate(): void $content = $this->replaceTemplateVariables($template, $variables); $path = $this->context->getPath('migration').'/'.$this->migrationFileName; - if ($this->context->getCommand()) { + if ($this->context->getCommand() instanceof Command) { $this->context->getCommand()->info('Migration details:'); $this->context->getCommand()->info('- File name: '.$this->migrationFileName); $this->context->getCommand()->info('- Full path: '.$path); @@ -45,7 +47,7 @@ public function generate(): void $this->writeFile($path, $content); - if ($this->context->getCommand()) { + if ($this->context->getCommand() instanceof Command) { $this->context->getCommand()->info('Migration file written successfully'); } } @@ -58,7 +60,7 @@ protected function generateMigrationFileName(): string 'app' => date('Y_m_d_His').'_create_'.$tableName.'_table.php', 'package' => 'create_'.$tableName.'_table.php.stub', 'preview' => 'preview_'.date('Y_m_d_His').'_create_'.$tableName.'_table.php', - default => throw new \InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), + default => throw new InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), }; } @@ -97,15 +99,16 @@ protected function getCustomFields(): array $migration = $block->migration(); if (! empty($migration)) { if (is_array($migration)) { - $fields = array_merge($fields, array_map(function ($field) { - return rtrim(trim($field), ';').';'; - }, $migration)); + $fields = array_merge($fields, array_map( + fn (string $field): string => rtrim(trim($field), ';').';', + $migration + )); } else { - $fields[] = rtrim(trim($migration), ';').';'; + $fields[] = rtrim(trim((string) $migration), ';').';'; } } } - return array_filter($fields); + return $fields; } } diff --git a/packages/builder/src/Generators/Entity/ModelGenerator.php b/packages/builder/src/Generators/Entity/ModelGenerator.php index d69aa8959..11dbe4d0a 100644 --- a/packages/builder/src/Generators/Entity/ModelGenerator.php +++ b/packages/builder/src/Generators/Entity/ModelGenerator.php @@ -4,9 +4,11 @@ namespace Moox\Builder\Generators\Entity; +use Exception; use Illuminate\Support\Str; use Moox\Builder\Contexts\BuildContext; use Moox\Builder\Services\File\FileManager; +use Override; class ModelGenerator extends AbstractGenerator { @@ -21,8 +23,8 @@ public function __construct( public function generate(): void { $template = $this->loadStub($this->getTemplate()); - if (! $template) { - throw new \Exception('Failed to load template: '.$this->getTemplate()); + if ($template === '' || $template === '0') { + throw new Exception('Failed to load template: '.$this->getTemplate()); } $variables = [ @@ -50,7 +52,7 @@ protected function getFillable(): string } } - return implode(",\n ", array_map(fn ($field) => "'$field'", $fillable)); + return implode(",\n ", array_map(fn ($field): string => sprintf("'%s'", $field), $fillable)); } protected function getCasts(): string @@ -59,7 +61,7 @@ protected function getCasts(): string foreach ($this->getBlocks() as $block) { $cast = $block->modelCast(); if (! empty($cast)) { - $cast = preg_replace("/['\"](.*?)['\"]\s*=>\s*['\"](.*?)['\"]/", "'$1' => '$2'", $cast); + $cast = preg_replace("/['\"](.*?)['\"]\s*=>\s*['\"](.*?)['\"]/", "'$1' => '$2'", (string) $cast); $casts[] = $cast; } } @@ -72,6 +74,7 @@ protected function getGeneratorType(): string return 'model'; } + #[Override] protected function formatUseStatements(): string { $statements = $this->getUseStatements('model'); @@ -80,18 +83,17 @@ protected function formatUseStatements(): string $blockTraits = $block->getTraits('model'); if (! empty($blockTraits)) { foreach ($blockTraits as $trait) { - if (! in_array("use $trait;", $statements)) { - $statements[] = "use $trait;"; + if (! in_array(sprintf('use %s;', $trait), $statements)) { + $statements[] = sprintf('use %s;', $trait); } } } } - return implode("\n", array_map(function ($statement) { - return rtrim($statement, ';').';'; - }, array_unique($statements))); + return implode("\n", array_map(fn ($statement): string => rtrim((string) $statement, ';').';', array_unique($statements))); } + #[Override] protected function formatMethods(): string { $methods = []; @@ -105,6 +107,7 @@ protected function formatMethods(): string if (! is_string($subMethod)) { continue; } + if (preg_match('/protected function ([a-zA-Z]+)\(/', $subMethod, $matches)) { $methodName = $matches[1]; if (! in_array($methodName, $methodNames)) { diff --git a/packages/builder/src/Generators/Entity/Pages/AbstractPageGenerator.php b/packages/builder/src/Generators/Entity/Pages/AbstractPageGenerator.php index 64622a2da..fa34581af 100644 --- a/packages/builder/src/Generators/Entity/Pages/AbstractPageGenerator.php +++ b/packages/builder/src/Generators/Entity/Pages/AbstractPageGenerator.php @@ -5,9 +5,11 @@ namespace Moox\Builder\Generators\Entity\Pages; use Illuminate\Support\Str; +use InvalidArgumentException; use Moox\Builder\Contexts\BuildContext; use Moox\Builder\Generators\Entity\AbstractGenerator; use Moox\Builder\Services\File\FileManager; +use Override; use RuntimeException; abstract class AbstractPageGenerator extends AbstractGenerator @@ -72,10 +74,11 @@ protected function getGeneratorType(): string return 'page_'.$this->getPageType(); } + #[Override] protected function getTemplate(): string { $template = $this->loadStub($this->getTemplateFile()); - if (! $template) { + if ($template === '' || $template === '0') { throw new RuntimeException('Failed to load template: '.$this->getTemplateFile()); } @@ -92,6 +95,7 @@ protected function getTemplateFile(): string return $templatePath; } + #[Override] protected function formatUseStatements(): string { $statements = []; @@ -106,16 +110,15 @@ protected function formatUseStatements(): string $blockTraits = $block->getTraits('pages'); if (isset($blockTraits[$pageType])) { foreach ($blockTraits[$pageType] as $trait) { - $statements[] = "use $trait;"; + $statements[] = sprintf('use %s;', $trait); } } } - return implode("\n", array_map(function ($statement) { - return rtrim($statement, ';').';'; - }, array_unique($statements))); + return implode("\n", array_map(fn ($statement): string => rtrim((string) $statement, ';').';', array_unique($statements))); } + #[Override] protected function formatTraits(): string { $traits = []; @@ -124,7 +127,7 @@ protected function formatTraits(): string foreach ($this->getBlocks() as $block) { $blockTraits = $block->getTraits('pages'); if (isset($blockTraits[$pageType])) { - $shortTraits = array_map(function ($trait) { + $shortTraits = array_map(function ($trait): string { $parts = explode('\\', $trait); return end($parts); @@ -133,13 +136,14 @@ protected function formatTraits(): string } } - if (empty($traits)) { + if ($traits === []) { return ''; } return 'use '.implode(', ', array_unique($traits)).';'; } + #[Override] protected function formatMethods(): string { $methods = []; @@ -163,6 +167,7 @@ protected function formatMethods(): string if (! isset($methods['mount'])) { $methods['mount'] = []; } + $methods['mount'][] = (string) $methodBody; } else { $methods[$methodName] = (string) $methodBody; @@ -192,10 +197,10 @@ protected function getEntityConfigKey(): string $entityName = Str::kebab($this->context->getEntityName()); return match ($contextType) { - 'app' => "entities.{$entityName}", - 'preview' => "previews.{$entityName}", - 'package' => $this->context->getConfig()['package']['name'].".entities.{$entityName}", - default => throw new \InvalidArgumentException('Invalid context type: '.$contextType), + 'app' => 'entities.'.$entityName, + 'preview' => 'previews.'.$entityName, + 'package' => $this->context->getConfig()['package']['name'].('.entities.'.$entityName), + default => throw new InvalidArgumentException('Invalid context type: '.$contextType), }; } } diff --git a/packages/builder/src/Generators/Entity/Pages/ListPageGenerator.php b/packages/builder/src/Generators/Entity/Pages/ListPageGenerator.php index df15ed816..f59bb8ae0 100644 --- a/packages/builder/src/Generators/Entity/Pages/ListPageGenerator.php +++ b/packages/builder/src/Generators/Entity/Pages/ListPageGenerator.php @@ -4,6 +4,8 @@ namespace Moox\Builder\Generators\Entity\Pages; +use Override; + class ListPageGenerator extends AbstractPageGenerator { protected function getPageType(): string @@ -11,6 +13,7 @@ protected function getPageType(): string return 'List'; } + #[Override] protected function getClassName(): string { return $this->getPageType().$this->context->getPluralName(); diff --git a/packages/builder/src/Generators/Entity/PluginGenerator.php b/packages/builder/src/Generators/Entity/PluginGenerator.php index 88cc90a93..733675bb9 100644 --- a/packages/builder/src/Generators/Entity/PluginGenerator.php +++ b/packages/builder/src/Generators/Entity/PluginGenerator.php @@ -6,6 +6,7 @@ use Moox\Builder\Contexts\BuildContext; use Moox\Builder\Services\File\FileManager; +use Override; class PluginGenerator extends AbstractGenerator { @@ -52,14 +53,13 @@ protected function getGeneratorType(): string return 'plugin'; } + #[Override] protected function formatUseStatements(): string { $statements = [ 'use '.$this->context->getNamespace('resource').'\\'.$this->context->getEntityName().'Resource;', ]; - return implode("\n", array_map(function ($statement) { - return rtrim($statement, ';').';'; - }, array_unique($statements))); + return implode("\n", array_map(fn ($statement): string => rtrim($statement, ';').';', array_unique($statements))); } } diff --git a/packages/builder/src/Generators/Entity/ResourceGenerator.php b/packages/builder/src/Generators/Entity/ResourceGenerator.php index 737d0ca92..a8d0d4c99 100644 --- a/packages/builder/src/Generators/Entity/ResourceGenerator.php +++ b/packages/builder/src/Generators/Entity/ResourceGenerator.php @@ -12,11 +12,12 @@ use Moox\Builder\Generators\Entity\Pages\ViewPageGenerator; use Moox\Builder\Services\Entity\SectionManager; use Moox\Builder\Services\File\FileManager; +use Override; use RuntimeException; class ResourceGenerator extends AbstractGenerator { - private SectionManager $sectionManager; + private readonly SectionManager $sectionManager; public function __construct( BuildContext $context, @@ -30,12 +31,12 @@ public function __construct( public function generate(): void { $this->processBlocks(); - $sections = $this->getSections(); + $this->getSections(); $this->generateResourcePages(); $template = $this->loadStub($this->getTemplate()); - if (! $template) { + if ($template === '' || $template === '0') { throw new RuntimeException('Failed to load template: '.$this->getTemplate()); } @@ -124,6 +125,7 @@ protected function getGeneratorType(): string return 'resource'; } + #[Override] protected function formatUseStatements(): string { $statements = [ @@ -150,16 +152,15 @@ protected function formatUseStatements(): string if ($context === 'pages') { continue; } + if (is_array($contextStatements)) { foreach ($contextStatements as $statement) { if ($statement !== $resourcePagesNamespace) { $statements[] = $statement; } } - } else { - if ($contextStatements !== $resourcePagesNamespace) { - $statements[] = $contextStatements; - } + } elseif ($contextStatements !== $resourcePagesNamespace) { + $statements[] = $contextStatements; } } } @@ -168,11 +169,10 @@ protected function formatUseStatements(): string $statements = array_unique($statements); sort($statements); - return implode("\n", array_map(function ($statement) { - return rtrim($statement, ';').';'; - }, $statements)); + return implode("\n", array_map(fn ($statement): string => rtrim((string) $statement, ';').';', $statements)); } + #[Override] protected function formatTraits(): string { $traits = []; @@ -180,13 +180,13 @@ protected function formatTraits(): string foreach ($this->getBlocks() as $block) { if ($resourceTraits = $block->getTraits('resource')) { foreach ($resourceTraits as $trait) { - $parts = explode('\\', $trait); + $parts = explode('\\', (string) $trait); $traits[] = end($parts); } } } - if (empty($traits)) { + if ($traits === []) { return ''; } @@ -203,7 +203,7 @@ protected function generateFormSchema(): array foreach ($this->getBlocks() as $block) { foreach ($block->getSections() as $section) { - if (str_contains($section['name'], '_actions') && $section['name'] !== 'resource_actions') { + if (str_contains((string) $section['name'], '_actions') && $section['name'] !== 'resource_actions') { continue; } @@ -219,12 +219,10 @@ protected function generateFormSchema(): array } else { $metaSections[] = $section; } + } elseif ($section['name'] === 'form') { + $mainFields = array_merge($mainFields, $section['fields']); } else { - if ($section['name'] === 'form') { - $mainFields = array_merge($mainFields, $section['fields']); - } else { - $mainSections[] = $section; - } + $mainSections[] = $section; } } } @@ -260,6 +258,7 @@ protected function getTableColumns(): string return implode(",\n ", $columns); } + #[Override] protected function getTableActions(): string { $actions = []; @@ -269,6 +268,7 @@ protected function getTableActions(): string if (is_string($blockActions) && str_contains($blockActions, 'static::')) { return $blockActions; } + $actions = array_merge($actions, (array) $blockActions); } } @@ -276,6 +276,7 @@ protected function getTableActions(): string return '['.implode(",\n ", $actions).']'; } + #[Override] protected function getTableFilters(): string { $filters = []; @@ -289,6 +290,7 @@ protected function getTableFilters(): string return implode(",\n ", $filters); } + #[Override] protected function getTableBulkActions(): string { $actions = []; @@ -299,6 +301,7 @@ protected function getTableBulkActions(): string if (is_string($blockActions) && str_contains($blockActions, 'static::')) { return $blockActions; } + $actions = array_merge($actions, (array) $blockActions); } } @@ -321,6 +324,7 @@ protected function getModelReference(): string return $this->context->formatNamespace('model', true).'\\'.$this->context->getEntityName(); } + #[Override] protected function getUseStatements(string $context, ?string $subContext = null): array { $statements = []; @@ -329,7 +333,7 @@ protected function getUseStatements(string $context, ?string $subContext = null) if ($subContext && isset($block->useStatements[$context][$subContext])) { $statements = array_merge($statements, $block->useStatements[$context][$subContext]); } elseif (! $subContext) { - foreach ($block->useStatements[$context] as $key => $value) { + foreach ($block->useStatements[$context] as $value) { if (is_array($value)) { $statements = array_merge($statements, $value); } else { @@ -349,7 +353,7 @@ protected function getDefaultSortColumn(): string foreach ($sortableFields as $field) { foreach ($this->getBlocks() as $block) { - if ($block->getName() === $field && str_contains($block->tableColumn(), '->sortable()')) { + if ($block->getName() === $field && str_contains((string) $block->tableColumn(), '->sortable()')) { return $field; } } diff --git a/packages/builder/src/Generators/Entity/TranslationGenerator.php b/packages/builder/src/Generators/Entity/TranslationGenerator.php index 4ef79dd99..58e785397 100644 --- a/packages/builder/src/Generators/Entity/TranslationGenerator.php +++ b/packages/builder/src/Generators/Entity/TranslationGenerator.php @@ -5,6 +5,7 @@ namespace Moox\Builder\Generators\Entity; use Illuminate\Support\Str; +use InvalidArgumentException; use Moox\Builder\Contexts\BuildContext; use Moox\Builder\Services\File\FileManager; @@ -61,7 +62,7 @@ protected function getTranslationPath(bool $fullPath = true): string 'app' => 'entities', 'preview' => 'previews', 'package' => $this->getPackageName(), - default => throw new \InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), + default => throw new InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), }; } @@ -69,7 +70,7 @@ protected function getTranslationPath(bool $fullPath = true): string 'app' => lang_path(config('app.locale', 'en').'/entities/'.$entityFile.'.php'), 'preview' => lang_path(config('app.locale', 'en').'/previews/'.$entityFile.'.php'), 'package' => $this->context->getPath('translation').'/'.$entityFile.'.php', - default => throw new \InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), + default => throw new InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), }; } diff --git a/packages/builder/src/Models/FullItem.php b/packages/builder/src/Models/FullItem.php index d392e9bce..25a366206 100644 --- a/packages/builder/src/Models/FullItem.php +++ b/packages/builder/src/Models/FullItem.php @@ -13,7 +13,11 @@ class FullItem extends Model { - use HasFactory, SinglePublishInModel, SoftDeletes, TaxonomyInModel, UserInModel; + use HasFactory; + use SinglePublishInModel; + use SoftDeletes; + use TaxonomyInModel; + use UserInModel; protected $table = 'full_items'; diff --git a/packages/builder/src/Models/Item.php b/packages/builder/src/Models/Item.php index 893244fa9..7c4536928 100644 --- a/packages/builder/src/Models/Item.php +++ b/packages/builder/src/Models/Item.php @@ -13,7 +13,11 @@ class Item extends Model { - use HasFactory, SinglePublishInModel, SoftDeletes, TaxonomyInModel, UserInModel; + use HasFactory; + use SinglePublishInModel; + use SoftDeletes; + use TaxonomyInModel; + use UserInModel; protected $table = 'items'; diff --git a/packages/builder/src/Models/NestedTaxonomy.php b/packages/builder/src/Models/NestedTaxonomy.php index e048b2874..1c84871b6 100644 --- a/packages/builder/src/Models/NestedTaxonomy.php +++ b/packages/builder/src/Models/NestedTaxonomy.php @@ -11,10 +11,13 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\DB; use Kalnoy\Nestedset\NodeTrait; +use Override; class NestedTaxonomy extends Model { - use HasFactory, NodeTrait, SoftDeletes; + use HasFactory; + use NodeTrait; + use SoftDeletes; protected $table = 'nested_taxonomies'; @@ -59,9 +62,10 @@ public function detachAllNestedtaxonomyables(): void DB::table('nestedtaxonomyables')->where('nested_taxonomy_id', $this->id)->delete(); } + #[Override] protected static function booted(): void { - static::deleting(function (NestedTaxonomy $nestedTaxonomy) { + static::deleting(function (NestedTaxonomy $nestedTaxonomy): void { $nestedTaxonomy->detachAllNestedtaxonomyables(); }); } diff --git a/packages/builder/src/Models/SimpleItem.php b/packages/builder/src/Models/SimpleItem.php index c7dcb5bd0..96ecdf4dd 100644 --- a/packages/builder/src/Models/SimpleItem.php +++ b/packages/builder/src/Models/SimpleItem.php @@ -10,7 +10,8 @@ class SimpleItem extends Model { - use HasFactory, TaxonomyInModel; + use HasFactory; + use TaxonomyInModel; protected $table = 'simple_items'; diff --git a/packages/builder/src/Models/SimpleTaxonomy.php b/packages/builder/src/Models/SimpleTaxonomy.php index 7696644a2..0aa1ca0d7 100644 --- a/packages/builder/src/Models/SimpleTaxonomy.php +++ b/packages/builder/src/Models/SimpleTaxonomy.php @@ -9,10 +9,12 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\DB; +use Override; class SimpleTaxonomy extends Model { - use HasFactory, SoftDeletes; + use HasFactory; + use SoftDeletes; protected $table = 'simple_taxonomies'; @@ -51,9 +53,10 @@ public function detachAllSimpletaxonomyables(): void DB::table('simpletaxonomyables')->where('simple_taxonomy_id', $this->id)->delete(); } + #[Override] protected static function booted(): void { - static::deleting(function (SimpleTaxonomy $simpleTaxonomy) { + static::deleting(function (SimpleTaxonomy $simpleTaxonomy): void { $simpleTaxonomy->detachAllSimpletaxonomyables(); }); } diff --git a/packages/builder/src/PresetRegistry.php b/packages/builder/src/PresetRegistry.php index 081c33711..827a50d5d 100644 --- a/packages/builder/src/PresetRegistry.php +++ b/packages/builder/src/PresetRegistry.php @@ -18,7 +18,7 @@ public static function getPreset(string $name): object $presetConfig = config('builder.presets.'.$name); if (! $presetConfig || ! isset($presetConfig['class'])) { - throw new RuntimeException("Preset {$name} not found in configuration"); + throw new RuntimeException(sprintf('Preset %s not found in configuration', $name)); } $presetClass = $presetConfig['class']; @@ -33,16 +33,16 @@ public static function getPresetNames(): array public static function getPresetBlocks(string $presetName): array { - $presetConfig = config("builder.presets.{$presetName}"); + $presetConfig = config('builder.presets.'.$presetName); if (! $presetConfig) { - throw new RuntimeException("Preset '{$presetName}' not found in configuration"); + throw new RuntimeException(sprintf("Preset '%s' not found in configuration", $presetName)); } $presetClass = $presetConfig['class']; if (! class_exists($presetClass)) { - throw new RuntimeException("Preset class not found: {$presetClass}"); + throw new RuntimeException('Preset class not found: '.$presetClass); } $preset = new $presetClass; @@ -50,8 +50,8 @@ public static function getPresetBlocks(string $presetName): array if (empty($blocks)) { throw new RuntimeException( - "Preset '{$presetName}' initialization failed. ". - "Class: {$presetClass}" + sprintf("Preset '%s' initialization failed. ", $presetName). + ('Class: '.$presetClass) ); } @@ -60,10 +60,10 @@ public static function getPresetBlocks(string $presetName): array public static function getPresetGenerators(string $presetName): array { - $presetConfig = config("builder.presets.{$presetName}"); + $presetConfig = config('builder.presets.'.$presetName); if (! $presetConfig) { - throw new RuntimeException("Preset '{$presetName}' not found in configuration"); + throw new RuntimeException(sprintf("Preset '%s' not found in configuration", $presetName)); } return $presetConfig['generators'] ?? []; diff --git a/packages/builder/src/Resources/FullItemResource.php b/packages/builder/src/Resources/FullItemResource.php index 3d165e523..02e6cba53 100644 --- a/packages/builder/src/Resources/FullItemResource.php +++ b/packages/builder/src/Resources/FullItemResource.php @@ -6,6 +6,7 @@ use Camya\Filament\Forms\Components\TitleWithSlugInput; use Filament\Forms\Components\Actions; +use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Components\FileUpload; use Filament\Forms\Components\Grid; @@ -35,6 +36,7 @@ use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Core\Traits\Taxonomy\TaxonomyInResource; use Moox\Core\Traits\UserRelation\UserInResource; +use Override; class FullItemResource extends Resource { @@ -48,6 +50,7 @@ class FullItemResource extends Resource protected static ?string $navigationIcon = 'gmdi-engineering'; + #[Override] public static function form(Form $form): Form { static::initUserModel(); @@ -78,73 +81,74 @@ public static function form(Form $form): Form Section::make() ->schema([ Actions::make([ - Actions\Action::make('restore') + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof ViewFullItem), - Actions\Action::make('save') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof ViewFullItem), + Action::make('save') ->label(__('core::core.save')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire instanceof CreateFullItem ? $livewire->create() : $livewire->save(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateFullItem || $livewire instanceof EditFullItem), - Actions\Action::make('publish') + ->visible(fn ($livewire): bool => $livewire instanceof CreateFullItem || $livewire instanceof EditFullItem), + Action::make('publish') ->label(__('core::core.publish')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $data = $livewire->form->getState(); if (! $data['published_at']) { $data['published_at'] = now(); } + $livewire->form->fill($data); $livewire instanceof CreateFullItem ? $livewire->create() : $livewire->save(); }) - ->hidden(fn ($livewire, $record) => $record && $record->trashed()), - Actions\Action::make('saveAndCreateAnother') + ->hidden(fn ($livewire, $record): bool => $record && $record->trashed()), + Action::make('saveAndCreateAnother') ->label(__('core::core.save_and_create_another')) ->color('secondary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire->saveAndCreateAnother(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateFullItem), - Actions\Action::make('cancel') + ->visible(fn ($livewire): bool => $livewire instanceof CreateFullItem), + Action::make('cancel') ->label(__('core::core.cancel')) ->color('secondary') ->outlined() ->extraAttributes(['class' => 'w-full']) - ->url(fn () => static::getUrl('index')) - ->visible(fn ($livewire) => $livewire instanceof CreateFullItem), - Actions\Action::make('edit') + ->url(fn (): string => static::getUrl('index')) + ->visible(fn ($livewire): bool => $livewire instanceof CreateFullItem), + Action::make('edit') ->label(__('core::core.edit')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) - ->visible(fn ($livewire, $record) => $livewire instanceof ViewFullItem && ! $record->trashed()), - Actions\Action::make('restore') + ->url(fn ($record): string => static::getUrl('edit', ['record' => $record])) + ->visible(fn ($livewire, $record): bool => $livewire instanceof ViewFullItem && ! $record->trashed()), + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof EditFullItem), - Actions\Action::make('delete') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof EditFullItem), + Action::make('delete') ->label(__('core::core.delete')) ->color('danger') ->link() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->delete()) - ->visible(fn ($livewire, $record) => $record && ! $record->trashed() && $livewire instanceof EditFullItem), + ->visible(fn ($livewire, $record): bool => $record && ! $record->trashed() && $livewire instanceof EditFullItem), ]), Select::make('type') ->options(static::getModel()::getTypeOptions()) @@ -159,7 +163,7 @@ public static function form(Form $form): Form Section::make() ->schema(static::getTaxonomyFields()) ->columns(1) - ->visible(fn () => ! empty(static::getTaxonomyFields())), + ->visible(fn (): bool => static::getTaxonomyFields() !== []), ]) ->columnSpan(['lg' => 1]), ]) @@ -167,6 +171,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { static::initUserModel(); @@ -202,7 +207,7 @@ public static function table(Table $table): Table TextColumn::make('type') ->label(__('core::core.type')) ->visible(! empty(config('builder.types'))) - ->formatStateUsing(fn ($record): string => config('builder.types')[$record->type] ?? ucfirst($record->type)) + ->formatStateUsing(fn ($record): string => config('builder.types')[$record->type] ?? ucfirst((string) $record->type)) ->sortable(), ...static::getTaxonomyColumns(), static::getStatusTableColumn(), @@ -218,16 +223,8 @@ public static function table(Table $table): Table ...static::getTableActions(), ]) ->bulkActions([ - DeleteBulkAction::make()->hidden(function () use ($currentTab) { - $isHidden = in_array($currentTab, ['trash', 'deleted']); - - return $isHidden; - }), - RestoreBulkAction::make()->visible(function () use ($currentTab) { - $isVisible = in_array($currentTab, ['trash', 'deleted']); - - return $isVisible; - }), + DeleteBulkAction::make()->hidden(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), + RestoreBulkAction::make()->visible(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), ]) ->filters([ Filter::make('title') @@ -235,23 +232,19 @@ public static function table(Table $table): Table TextInput::make('title') ->label(__('core::core.title')), ]) - ->query(function (Builder $query, array $data): Builder { - return $query->when( - $data['title'], - fn (Builder $query, $title): Builder => $query->where('title', 'like', "%{$title}%"), - ); - }), + ->query(fn (Builder $query, array $data): Builder => $query->when( + $data['title'], + fn (Builder $query, $title): Builder => $query->where('title', 'like', sprintf('%%%s%%', $title)), + )), Filter::make('slug') ->form([ TextInput::make('slug') ->label(__('core::core.slug')), ]) - ->query(function (Builder $query, array $data): Builder { - return $query->when( - $data['slug'], - fn (Builder $query, $slug): Builder => $query->where('slug', 'like', "%{$slug}%"), - ); - }), + ->query(fn (Builder $query, array $data): Builder => $query->when( + $data['slug'], + fn (Builder $query, $slug): Builder => $query->where('slug', 'like', sprintf('%%%s%%', $slug)), + )), SelectFilter::make('type') ->options(static::getModel()::getTypeOptions()) ->label(__('core::core.type')), @@ -261,6 +254,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -268,6 +262,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -278,6 +273,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -285,26 +281,31 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return config('builder.resources.full-item.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('builder.resources.full-item.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('builder.resources.full-item.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('builder.resources.full-item.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -315,11 +316,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return config('builder.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('builder.navigation_sort') + 2; diff --git a/packages/builder/src/Resources/FullItemResource/Pages/CreateFullItem.php b/packages/builder/src/Resources/FullItemResource/Pages/CreateFullItem.php index 9a911e1a4..4999712d4 100644 --- a/packages/builder/src/Resources/FullItemResource/Pages/CreateFullItem.php +++ b/packages/builder/src/Resources/FullItemResource/Pages/CreateFullItem.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\CreateRecord; use Moox\Builder\Resources\FullItemResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class CreateFullItem extends CreateRecord { @@ -14,6 +15,7 @@ class CreateFullItem extends CreateRecord protected static string $resource = FullItemResource::class; + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/FullItemResource/Pages/EditFullItem.php b/packages/builder/src/Resources/FullItemResource/Pages/EditFullItem.php index 3704e32bd..38a033ac2 100644 --- a/packages/builder/src/Resources/FullItemResource/Pages/EditFullItem.php +++ b/packages/builder/src/Resources/FullItemResource/Pages/EditFullItem.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\EditRecord; use Moox\Builder\Resources\FullItemResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class EditFullItem extends EditRecord { @@ -14,6 +15,7 @@ class EditFullItem extends EditRecord protected static string $resource = FullItemResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -28,6 +30,7 @@ protected function getHeaderActions(): array return []; } + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/FullItemResource/Pages/ListFullItems.php b/packages/builder/src/Resources/FullItemResource/Pages/ListFullItems.php index 3102e056f..726eb22bb 100644 --- a/packages/builder/src/Resources/FullItemResource/Pages/ListFullItems.php +++ b/packages/builder/src/Resources/FullItemResource/Pages/ListFullItems.php @@ -12,6 +12,7 @@ use Moox\Builder\Resources\FullItemResource; use Moox\Builder\Resources\FullItemResource\Widgets\FullItemWidgets; use Moox\Core\Traits\Tabs\TabsInListPage; +use Override; class ListFullItems extends ListRecords { @@ -23,15 +24,13 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): FullItem { - return $model::create($data); - }) - ->hidden(fn () => $this->activeTab === 'deleted'), + ->using(fn (array $data, string $model): FullItem => $model::create($data)) + ->hidden(fn (): bool => $this->activeTab === 'deleted'), Action::make('emptyTrash') ->label(__('core::core.empty_trash')) ->icon('heroicon-o-trash') ->color('danger') - ->action(function () { + ->action(function (): void { $trashedCount = FullItem::onlyTrashed()->count(); FullItem::onlyTrashed()->forceDelete(); Notification::make() @@ -41,10 +40,11 @@ protected function getHeaderActions(): array ->send(); }) ->requiresConfirmation() - ->visible(fn () => $this->activeTab === 'deleted' && FullItem::onlyTrashed()->exists()), + ->visible(fn (): bool => $this->activeTab === 'deleted' && FullItem::onlyTrashed()->exists()), ]; } + #[Override] public function getTitle(): string { return config('builder.resources.full-item.plural'); @@ -55,7 +55,8 @@ public function getTabs(): array return $this->getDynamicTabs('builder.resources.full-item.tabs', FullItem::class); } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ FullItemWidgets::class, diff --git a/packages/builder/src/Resources/FullItemResource/Pages/ViewFullItem.php b/packages/builder/src/Resources/FullItemResource/Pages/ViewFullItem.php index 10e0e09cd..3074319ce 100644 --- a/packages/builder/src/Resources/FullItemResource/Pages/ViewFullItem.php +++ b/packages/builder/src/Resources/FullItemResource/Pages/ViewFullItem.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Model; use Moox\Builder\Resources\FullItemResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class ViewFullItem extends ViewRecord { @@ -15,6 +16,7 @@ class ViewFullItem extends ViewRecord protected static string $resource = FullItemResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -24,6 +26,7 @@ public function mount($record): void $this->fillForm(); } + #[Override] public function getTitle(): string { $title = parent::getTitle(); diff --git a/packages/builder/src/Resources/FullItemResource/Widgets/FullItemWidgets.php b/packages/builder/src/Resources/FullItemResource/Widgets/FullItemWidgets.php index 8a3462b22..a2f8920da 100644 --- a/packages/builder/src/Resources/FullItemResource/Widgets/FullItemWidgets.php +++ b/packages/builder/src/Resources/FullItemResource/Widgets/FullItemWidgets.php @@ -8,9 +8,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Builder\Models\FullItem; +use Override; class FullItemWidgets extends BaseWidget { + #[Override] protected function getStats(): array { $aggregationColumns = [ diff --git a/packages/builder/src/Resources/ItemResource.php b/packages/builder/src/Resources/ItemResource.php index 842632b55..ac657b82c 100644 --- a/packages/builder/src/Resources/ItemResource.php +++ b/packages/builder/src/Resources/ItemResource.php @@ -28,15 +28,21 @@ use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Core\Traits\Taxonomy\TaxonomyInResource; use Moox\Core\Traits\UserRelation\UserInResource; +use Override; class ItemResource extends Resource { - use BaseInResource, SinglePublishInResource, TabsInResource, TaxonomyInResource, UserInResource; + use BaseInResource; + use SinglePublishInResource; + use TabsInResource; + use TaxonomyInResource; + use UserInResource; protected static ?string $model = Item::class; protected static ?string $navigationIcon = 'gmdi-article'; + #[Override] public static function form(Form $form): Form { static::initUserModel(); @@ -74,7 +80,7 @@ public static function form(Form $form): Form Section::make() ->schema(static::getTaxonomyFields()) ->columns(1) - ->visible(fn () => ! empty(static::getTaxonomyFields())), + ->visible(fn (): bool => static::getTaxonomyFields() !== []), ]) ->columnSpan(['lg' => 1]), ]) @@ -82,6 +88,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { static::initUserModel(); @@ -129,20 +136,12 @@ public static function table(Table $table): Table ->actions([ // SinglePublishInResource - getTableActions ViewAction::make(), - EditAction::make()->hidden(fn () => in_array(static::getCurrentTab(), ['trash', 'deleted'])), + EditAction::make()->hidden(fn (): bool => in_array(static::getCurrentTab(), ['trash', 'deleted'])), ]) ->bulkActions([ // SinglePublishInResource - getTableBulkActions - DeleteBulkAction::make()->hidden(function () use ($currentTab) { - $isHidden = in_array($currentTab, ['trash', 'deleted']); - - return $isHidden; - }), - RestoreBulkAction::make()->visible(function () use ($currentTab) { - $isVisible = in_array($currentTab, ['trash', 'deleted']); - - return $isVisible; - }), + DeleteBulkAction::make()->hidden(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), + RestoreBulkAction::make()->visible(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), ]) ->filters([ ...static::getTableFilters(), @@ -151,6 +150,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getPages(): array { return [ @@ -161,31 +161,37 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('builder.resources.item.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('builder.resources.item.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('builder.resources.item.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('builder.resources.item.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('builder.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('builder.navigation_sort') + 1; diff --git a/packages/builder/src/Resources/ItemResource/Pages/CreateItem.php b/packages/builder/src/Resources/ItemResource/Pages/CreateItem.php index 0de65223c..8c3dd75ae 100644 --- a/packages/builder/src/Resources/ItemResource/Pages/CreateItem.php +++ b/packages/builder/src/Resources/ItemResource/Pages/CreateItem.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\CreateRecord; use Moox\Builder\Resources\ItemResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class CreateItem extends CreateRecord { @@ -14,6 +15,7 @@ class CreateItem extends CreateRecord protected static string $resource = ItemResource::class; + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/ItemResource/Pages/EditItem.php b/packages/builder/src/Resources/ItemResource/Pages/EditItem.php index 93e92db7c..caeaf5b42 100644 --- a/packages/builder/src/Resources/ItemResource/Pages/EditItem.php +++ b/packages/builder/src/Resources/ItemResource/Pages/EditItem.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\EditRecord; use Moox\Builder\Resources\ItemResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class EditItem extends EditRecord { @@ -14,6 +15,7 @@ class EditItem extends EditRecord protected static string $resource = ItemResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -28,6 +30,7 @@ protected function getHeaderActions(): array return []; } + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/ItemResource/Pages/ListItems.php b/packages/builder/src/Resources/ItemResource/Pages/ListItems.php index ea34921c7..4b5100eba 100644 --- a/packages/builder/src/Resources/ItemResource/Pages/ListItems.php +++ b/packages/builder/src/Resources/ItemResource/Pages/ListItems.php @@ -11,6 +11,7 @@ use Moox\Builder\Models\Item; use Moox\Builder\Resources\ItemResource; use Moox\Core\Traits\Tabs\TabsInListPage; +use Override; class ListItems extends ListRecords { @@ -18,6 +19,7 @@ class ListItems extends ListRecords public static string $resource = ItemResource::class; + #[Override] public function mount(): void { parent::mount(); @@ -28,15 +30,13 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Item { - return $model::create($data); - }) - ->hidden(fn () => $this->activeTab === 'deleted'), + ->using(fn (array $data, string $model): Item => $model::create($data)) + ->hidden(fn (): bool => $this->activeTab === 'deleted'), Action::make('emptyTrash') ->label(__('core::core.empty_trash')) ->icon('heroicon-o-trash') ->color('danger') - ->action(function () { + ->action(function (): void { $trashedCount = Item::onlyTrashed()->count(); Item::onlyTrashed()->forceDelete(); Notification::make() @@ -46,10 +46,11 @@ protected function getHeaderActions(): array ->send(); }) ->requiresConfirmation() - ->visible(fn () => $this->activeTab === 'deleted' && Item::onlyTrashed()->exists()), + ->visible(fn (): bool => $this->activeTab === 'deleted' && Item::onlyTrashed()->exists()), ]; } + #[Override] public function getTitle(): string { return config('builder.resources.item.plural'); diff --git a/packages/builder/src/Resources/ItemResource/Pages/ViewItem.php b/packages/builder/src/Resources/ItemResource/Pages/ViewItem.php index 03ac489f6..f8d2810bf 100644 --- a/packages/builder/src/Resources/ItemResource/Pages/ViewItem.php +++ b/packages/builder/src/Resources/ItemResource/Pages/ViewItem.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Model; use Moox\Builder\Resources\ItemResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class ViewItem extends ViewRecord { @@ -15,6 +16,7 @@ class ViewItem extends ViewRecord protected static string $resource = ItemResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -24,6 +26,7 @@ public function mount($record): void $this->fillForm(); } + #[Override] public function getTitle(): string { $title = parent::getTitle(); diff --git a/packages/builder/src/Resources/ItemResource/Widgets/ItemWidgets.php b/packages/builder/src/Resources/ItemResource/Widgets/ItemWidgets.php index 7e586dafa..d8647f6c3 100644 --- a/packages/builder/src/Resources/ItemResource/Widgets/ItemWidgets.php +++ b/packages/builder/src/Resources/ItemResource/Widgets/ItemWidgets.php @@ -8,9 +8,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Builder\Models\Item; +use Override; class ItemWidgets extends BaseWidget { + #[Override] protected function getStats(): array { $aggregationColumns = [ diff --git a/packages/builder/src/Resources/NestedTaxonomyResource.php b/packages/builder/src/Resources/NestedTaxonomyResource.php index eb9431607..efc158f9d 100644 --- a/packages/builder/src/Resources/NestedTaxonomyResource.php +++ b/packages/builder/src/Resources/NestedTaxonomyResource.php @@ -6,6 +6,7 @@ use Camya\Filament\Forms\Components\TitleWithSlugInput; use Filament\Forms\Components\Actions; +use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\FileUpload; use Filament\Forms\Components\Grid; use Filament\Forms\Components\MarkdownEditor; @@ -27,6 +28,7 @@ use Moox\Builder\Resources\NestedTaxonomyResource\Pages\ListNestedTaxonomies; use Moox\Builder\Resources\NestedTaxonomyResource\Pages\ViewNestedTaxonomy; use Moox\Core\Traits\Taxonomy\TaxonomyInResource; +use Override; class NestedTaxonomyResource extends Resource { @@ -40,6 +42,7 @@ class NestedTaxonomyResource extends Resource protected static ?string $navigationIcon = 'gmdi-category'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -68,80 +71,81 @@ public static function form(Form $form): Form Section::make() ->schema([ Actions::make([ - Actions\Action::make('restore') + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof ViewNestedTaxonomy), - Actions\Action::make('save') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof ViewNestedTaxonomy), + Action::make('save') ->label(__('core::core.save')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire instanceof CreateNestedTaxonomy ? $livewire->create() : $livewire->save(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateNestedTaxonomy || $livewire instanceof EditNestedTaxonomy), - Actions\Action::make('publish') + ->visible(fn ($livewire): bool => $livewire instanceof CreateNestedTaxonomy || $livewire instanceof EditNestedTaxonomy), + Action::make('publish') ->label(__('core::core.publish')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $data = $livewire->form->getState(); if (! $data['published_at']) { $data['published_at'] = now(); } + $livewire->form->fill($data); $livewire instanceof CreateNestedTaxonomy ? $livewire->create() : $livewire->save(); }) - ->hidden(fn ($livewire, $record) => $record && $record->trashed()), - Actions\Action::make('saveAndCreateAnother') + ->hidden(fn ($livewire, $record): bool => $record && $record->trashed()), + Action::make('saveAndCreateAnother') ->label(__('core::core.save_and_create_another')) ->color('secondary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire->saveAndCreateAnother(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateNestedTaxonomy), - Actions\Action::make('cancel') + ->visible(fn ($livewire): bool => $livewire instanceof CreateNestedTaxonomy), + Action::make('cancel') ->label(__('core::core.cancel')) ->color('secondary') ->outlined() ->extraAttributes(['class' => 'w-full']) - ->url(fn () => static::getUrl('index')) - ->visible(fn ($livewire) => $livewire instanceof CreateNestedTaxonomy), - Actions\Action::make('edit') + ->url(fn (): string => static::getUrl('index')) + ->visible(fn ($livewire): bool => $livewire instanceof CreateNestedTaxonomy), + Action::make('edit') ->label(__('core::core.edit')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) - ->visible(fn ($livewire, $record) => $livewire instanceof ViewNestedTaxonomy && ! $record->trashed()), - Actions\Action::make('restore') + ->url(fn ($record): string => static::getUrl('edit', ['record' => $record])) + ->visible(fn ($livewire, $record): bool => $livewire instanceof ViewNestedTaxonomy && ! $record->trashed()), + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof EditNestedTaxonomy), - Actions\Action::make('delete') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof EditNestedTaxonomy), + Action::make('delete') ->label(__('core::core.delete')) ->color('danger') ->link() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->delete()) - ->visible(fn ($livewire, $record) => $record && ! $record->trashed() && $livewire instanceof EditNestedTaxonomy), + ->visible(fn ($livewire, $record): bool => $record && ! $record->trashed() && $livewire instanceof EditNestedTaxonomy), ]), ]), Section::make() ->schema(static::getTaxonomyFields()) ->columns(1) - ->visible(fn () => ! empty(static::getTaxonomyFields())), + ->visible(fn (): bool => static::getTaxonomyFields() !== []), ]) ->columnSpan(['lg' => 1]), ]) @@ -149,6 +153,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { $currentTab = static::getCurrentTab(); @@ -182,25 +187,18 @@ public static function table(Table $table): Table ->defaultSort('slug', 'desc') ->actions([ ViewAction::make(), - EditAction::make()->hidden(fn () => in_array(static::getCurrentTab(), ['trash', 'deleted'])), + EditAction::make()->hidden(fn (): bool => in_array(static::getCurrentTab(), ['trash', 'deleted'])), ]) ->bulkActions([ - DeleteBulkAction::make()->hidden(function () use ($currentTab) { - $isHidden = in_array($currentTab, ['trash', 'deleted']); - - return $isHidden; - }), - RestoreBulkAction::make()->visible(function () use ($currentTab) { - $isVisible = in_array($currentTab, ['trash', 'deleted']); - - return $isVisible; - }), + DeleteBulkAction::make()->hidden(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), + RestoreBulkAction::make()->visible(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), ]) ->filters([ ...static::getTaxonomyFilters(), ]); } + #[Override] public static function getPages(): array { return [ @@ -211,31 +209,37 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('builder.resources.nested-taxonomy.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('builder.resources.nested-taxonomy.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('builder.resources.nested-taxonomy.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('builder.resources.nested-taxonomy.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('builder.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('builder.navigation_sort') + 4; diff --git a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/CreateNestedTaxonomy.php b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/CreateNestedTaxonomy.php index b1f832425..6685d564f 100644 --- a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/CreateNestedTaxonomy.php +++ b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/CreateNestedTaxonomy.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\CreateRecord; use Moox\Builder\Resources\NestedTaxonomyResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class CreateNestedTaxonomy extends CreateRecord { @@ -14,6 +15,7 @@ class CreateNestedTaxonomy extends CreateRecord protected static string $resource = NestedTaxonomyResource::class; + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/EditNestedTaxonomy.php b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/EditNestedTaxonomy.php index c4aab2ba2..4c3afc4b4 100644 --- a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/EditNestedTaxonomy.php +++ b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/EditNestedTaxonomy.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\EditRecord; use Moox\Builder\Resources\NestedTaxonomyResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class EditNestedTaxonomy extends EditRecord { @@ -14,6 +15,7 @@ class EditNestedTaxonomy extends EditRecord protected static string $resource = NestedTaxonomyResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -28,6 +30,7 @@ protected function getHeaderActions(): array return []; } + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ListNestedTaxonomies.php b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ListNestedTaxonomies.php index 785aa3daa..65169752a 100644 --- a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ListNestedTaxonomies.php +++ b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ListNestedTaxonomies.php @@ -11,6 +11,7 @@ use Moox\Builder\Models\NestedTaxonomy; use Moox\Builder\Resources\NestedTaxonomyResource; use Moox\Core\Traits\Tabs\TabsInListPage; +use Override; class ListNestedTaxonomies extends ListRecords { @@ -22,15 +23,13 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): NestedTaxonomy { - return $model::create($data); - }) - ->hidden(fn () => $this->activeTab === 'deleted'), + ->using(fn (array $data, string $model): NestedTaxonomy => $model::create($data)) + ->hidden(fn (): bool => $this->activeTab === 'deleted'), Action::make('emptyTrash') ->label(__('core::core.empty_trash')) ->icon('heroicon-o-trash') ->color('danger') - ->action(function () { + ->action(function (): void { $trashedCount = NestedTaxonomy::onlyTrashed()->count(); NestedTaxonomy::onlyTrashed()->forceDelete(); Notification::make() @@ -40,10 +39,11 @@ protected function getHeaderActions(): array ->send(); }) ->requiresConfirmation() - ->visible(fn () => $this->activeTab === 'deleted' && NestedTaxonomy::onlyTrashed()->exists()), + ->visible(fn (): bool => $this->activeTab === 'deleted' && NestedTaxonomy::onlyTrashed()->exists()), ]; } + #[Override] public function getTitle(): string { return config('builder.resources.nested-taxonomy.plural'); diff --git a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ViewNestedTaxonomy.php b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ViewNestedTaxonomy.php index 18a0a5046..f7d35ae4f 100644 --- a/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ViewNestedTaxonomy.php +++ b/packages/builder/src/Resources/NestedTaxonomyResource/Pages/ViewNestedTaxonomy.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Model; use Moox\Builder\Resources\NestedTaxonomyResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class ViewNestedTaxonomy extends ViewRecord { @@ -15,6 +16,7 @@ class ViewNestedTaxonomy extends ViewRecord protected static string $resource = NestedTaxonomyResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -24,6 +26,7 @@ public function mount($record): void $this->fillForm(); } + #[Override] public function getTitle(): string { $title = parent::getTitle(); diff --git a/packages/builder/src/Resources/NestedTaxonomyResource/Widgets/NestedTaxonomyWidgets.php b/packages/builder/src/Resources/NestedTaxonomyResource/Widgets/NestedTaxonomyWidgets.php index 1a7af3549..e334c505f 100644 --- a/packages/builder/src/Resources/NestedTaxonomyResource/Widgets/NestedTaxonomyWidgets.php +++ b/packages/builder/src/Resources/NestedTaxonomyResource/Widgets/NestedTaxonomyWidgets.php @@ -8,9 +8,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Builder\Models\NestedTaxonomy; +use Override; class NestedTaxonomyWidgets extends BaseWidget { + #[Override] protected function getStats(): array { $aggregationColumns = [ diff --git a/packages/builder/src/Resources/SimpleItemResource.php b/packages/builder/src/Resources/SimpleItemResource.php index ce0940767..1106fe3e7 100644 --- a/packages/builder/src/Resources/SimpleItemResource.php +++ b/packages/builder/src/Resources/SimpleItemResource.php @@ -25,15 +25,18 @@ use Moox\Builder\Resources\SimpleItemResource\Pages\ViewSimpleItem; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; +use Override; class SimpleItemResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = SimpleItem::class; protected static ?string $navigationIcon = 'gmdi-circle'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -55,9 +58,10 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { - $currentTab = static::getCurrentTab(); + static::getCurrentTab(); return $table ->columns([ @@ -95,6 +99,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getPages(): array { return [ @@ -105,36 +110,43 @@ public static function getPages(): array ]; } + #[Override] public static function getEloquentQuery(): Builder { return parent::getEloquentQuery()->withoutGlobalScopes(); } + #[Override] public static function getModelLabel(): string { return config('builder.resources.simple-item.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('builder.resources.simple-item.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('builder.resources.simple-item.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('builder.resources.simple-item.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('builder.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('builder.navigation_sort') + 1; diff --git a/packages/builder/src/Resources/SimpleItemResource/Pages/ListSimpleItems.php b/packages/builder/src/Resources/SimpleItemResource/Pages/ListSimpleItems.php index 5a0cb32e9..2735b3b82 100644 --- a/packages/builder/src/Resources/SimpleItemResource/Pages/ListSimpleItems.php +++ b/packages/builder/src/Resources/SimpleItemResource/Pages/ListSimpleItems.php @@ -9,6 +9,7 @@ use Moox\Builder\Models\SimpleItem; use Moox\Builder\Resources\SimpleItemResource; use Moox\Core\Traits\Tabs\TabsInListPage; +use Override; class ListSimpleItems extends ListRecords { @@ -23,6 +24,7 @@ protected function getHeaderActions(): array ]; } + #[Override] public function getTitle(): string { return config('builder.resources.simple-item.plural'); diff --git a/packages/builder/src/Resources/SimpleTaxonomyResource.php b/packages/builder/src/Resources/SimpleTaxonomyResource.php index 7bc54fdaa..ed5e647d8 100644 --- a/packages/builder/src/Resources/SimpleTaxonomyResource.php +++ b/packages/builder/src/Resources/SimpleTaxonomyResource.php @@ -6,6 +6,7 @@ use Camya\Filament\Forms\Components\TitleWithSlugInput; use Filament\Forms\Components\Actions; +use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\FileUpload; use Filament\Forms\Components\Grid; use Filament\Forms\Components\MarkdownEditor; @@ -25,6 +26,7 @@ use Moox\Builder\Resources\SimpleTaxonomyResource\Pages\ListSimpleTaxonomies; use Moox\Builder\Resources\SimpleTaxonomyResource\Pages\ViewSimpleTaxonomy; use Moox\Core\Traits\Taxonomy\TaxonomyInResource; +use Override; class SimpleTaxonomyResource extends Resource { @@ -38,6 +40,7 @@ class SimpleTaxonomyResource extends Resource protected static ?string $navigationIcon = 'gmdi-label'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -66,66 +69,66 @@ public static function form(Form $form): Form Section::make() ->schema([ Actions::make([ - Actions\Action::make('restore') + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof ViewSimpleTaxonomy), - Actions\Action::make('save') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof ViewSimpleTaxonomy), + Action::make('save') ->label(__('core::core.save')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire instanceof CreateSimpleTaxonomy ? $livewire->create() : $livewire->save(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateSimpleTaxonomy || $livewire instanceof EditSimpleTaxonomy), - Actions\Action::make('saveAndCreateAnother') + ->visible(fn ($livewire): bool => $livewire instanceof CreateSimpleTaxonomy || $livewire instanceof EditSimpleTaxonomy), + Action::make('saveAndCreateAnother') ->label(__('core::core.save_and_create_another')) ->color('secondary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire->saveAndCreateAnother(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateSimpleTaxonomy), - Actions\Action::make('cancel') + ->visible(fn ($livewire): bool => $livewire instanceof CreateSimpleTaxonomy), + Action::make('cancel') ->label(__('core::core.cancel')) ->color('secondary') ->outlined() ->extraAttributes(['class' => 'w-full']) - ->url(fn () => static::getUrl('index')) - ->visible(fn ($livewire) => $livewire instanceof CreateSimpleTaxonomy), - Actions\Action::make('edit') + ->url(fn (): string => static::getUrl('index')) + ->visible(fn ($livewire): bool => $livewire instanceof CreateSimpleTaxonomy), + Action::make('edit') ->label(__('core::core.edit')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) - ->visible(fn ($livewire, $record) => $livewire instanceof ViewSimpleTaxonomy && ! $record->trashed()), - Actions\Action::make('restore') + ->url(fn ($record): string => static::getUrl('edit', ['record' => $record])) + ->visible(fn ($livewire, $record): bool => $livewire instanceof ViewSimpleTaxonomy && ! $record->trashed()), + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof EditSimpleTaxonomy), - Actions\Action::make('delete') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof EditSimpleTaxonomy), + Action::make('delete') ->label(__('core::core.delete')) ->color('danger') ->link() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->delete()) - ->visible(fn ($livewire, $record) => $record && ! $record->trashed() && $livewire instanceof EditSimpleTaxonomy), + ->visible(fn ($livewire, $record): bool => $record && ! $record->trashed() && $livewire instanceof EditSimpleTaxonomy), ]), ]), Section::make() ->schema(static::getTaxonomyFields()) ->columns(1) - ->visible(fn () => ! empty(static::getTaxonomyFields())), + ->visible(fn (): bool => static::getTaxonomyFields() !== []), ]) ->columnSpan(['lg' => 1]), ]) @@ -133,9 +136,10 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { - $currentTab = static::getCurrentTab(); + static::getCurrentTab(); return $table ->columns([ @@ -166,7 +170,7 @@ public static function table(Table $table): Table ->defaultSort('slug', 'desc') ->actions([ ViewAction::make(), - EditAction::make()->hidden(fn () => in_array(static::getCurrentTab(), ['trash', 'deleted'])), + EditAction::make()->hidden(fn (): bool => in_array(static::getCurrentTab(), ['trash', 'deleted'])), ]) ->bulkActions([ @@ -176,6 +180,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getPages(): array { return [ @@ -186,36 +191,43 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('builder.resources.simple-taxonomy.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('builder.resources.simple-taxonomy.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('builder.resources.simple-taxonomy.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('builder.resources.simple-taxonomy.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return config('builder.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('builder.navigation_sort') + 3; diff --git a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/CreateSimpleTaxonomy.php b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/CreateSimpleTaxonomy.php index 0a6d35e60..b4cc39482 100644 --- a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/CreateSimpleTaxonomy.php +++ b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/CreateSimpleTaxonomy.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\CreateRecord; use Moox\Builder\Resources\SimpleTaxonomyResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class CreateSimpleTaxonomy extends CreateRecord { @@ -14,6 +15,7 @@ class CreateSimpleTaxonomy extends CreateRecord protected static string $resource = SimpleTaxonomyResource::class; + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/EditSimpleTaxonomy.php b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/EditSimpleTaxonomy.php index ea0f33490..2b740516f 100644 --- a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/EditSimpleTaxonomy.php +++ b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/EditSimpleTaxonomy.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\EditRecord; use Moox\Builder\Resources\SimpleTaxonomyResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class EditSimpleTaxonomy extends EditRecord { @@ -14,6 +15,7 @@ class EditSimpleTaxonomy extends EditRecord protected static string $resource = SimpleTaxonomyResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -28,6 +30,7 @@ protected function getHeaderActions(): array return []; } + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ListSimpleTaxonomies.php b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ListSimpleTaxonomies.php index f1a568fe6..3f01f5084 100644 --- a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ListSimpleTaxonomies.php +++ b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ListSimpleTaxonomies.php @@ -11,6 +11,7 @@ use Moox\Builder\Models\SimpleTaxonomy; use Moox\Builder\Resources\SimpleTaxonomyResource; use Moox\Core\Traits\Tabs\TabsInListPage; +use Override; class ListSimpleTaxonomies extends ListRecords { @@ -22,15 +23,13 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): SimpleTaxonomy { - return $model::create($data); - }) - ->hidden(fn () => $this->activeTab === 'deleted'), + ->using(fn (array $data, string $model): SimpleTaxonomy => $model::create($data)) + ->hidden(fn (): bool => $this->activeTab === 'deleted'), Action::make('emptyTrash') ->label(__('core::core.empty_trash')) ->icon('heroicon-o-trash') ->color('danger') - ->action(function () { + ->action(function (): void { $trashedCount = SimpleTaxonomy::onlyTrashed()->count(); SimpleTaxonomy::onlyTrashed()->forceDelete(); Notification::make() @@ -40,10 +39,11 @@ protected function getHeaderActions(): array ->send(); }) ->requiresConfirmation() - ->visible(fn () => $this->activeTab === 'deleted' && SimpleTaxonomy::onlyTrashed()->exists()), + ->visible(fn (): bool => $this->activeTab === 'deleted' && SimpleTaxonomy::onlyTrashed()->exists()), ]; } + #[Override] public function getTitle(): string { return config('builder.resources.simple-taxonomy.plural'); diff --git a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ViewSimpleTaxonomy.php b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ViewSimpleTaxonomy.php index 0cd408919..cbb898e1f 100644 --- a/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ViewSimpleTaxonomy.php +++ b/packages/builder/src/Resources/SimpleTaxonomyResource/Pages/ViewSimpleTaxonomy.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Model; use Moox\Builder\Resources\SimpleTaxonomyResource; use Moox\Core\Traits\Taxonomy\TaxonomyInPages; +use Override; class ViewSimpleTaxonomy extends ViewRecord { @@ -15,6 +16,7 @@ class ViewSimpleTaxonomy extends ViewRecord protected static string $resource = SimpleTaxonomyResource::class; + #[Override] public function mount($record): void { $this->record = $this->resolveRecord($record); @@ -24,6 +26,7 @@ public function mount($record): void $this->fillForm(); } + #[Override] public function getTitle(): string { $title = parent::getTitle(); diff --git a/packages/builder/src/Resources/SimpleTaxonomyResource/Widgets/SimpleTaxonomyWidgets.php b/packages/builder/src/Resources/SimpleTaxonomyResource/Widgets/SimpleTaxonomyWidgets.php index 1bc961a41..8485ae8e7 100644 --- a/packages/builder/src/Resources/SimpleTaxonomyResource/Widgets/SimpleTaxonomyWidgets.php +++ b/packages/builder/src/Resources/SimpleTaxonomyResource/Widgets/SimpleTaxonomyWidgets.php @@ -8,9 +8,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Builder\Models\SimpleTaxonomy; +use Override; class SimpleTaxonomyWidgets extends BaseWidget { + #[Override] protected function getStats(): array { $aggregationColumns = [ diff --git a/packages/builder/src/Services/Block/BlockFactory.php b/packages/builder/src/Services/Block/BlockFactory.php index 2543c77ce..77f4d3f5a 100644 --- a/packages/builder/src/Services/Block/BlockFactory.php +++ b/packages/builder/src/Services/Block/BlockFactory.php @@ -4,6 +4,8 @@ namespace Moox\Builder\Services\Block; +use ReflectionClass; + class BlockFactory { public function createFromBuild(string $blockClass, int $entityId): ?object @@ -13,7 +15,7 @@ public function createFromBuild(string $blockClass, int $entityId): ?object public function create(string $blockClass, array $options = []): object { - $reflection = new \ReflectionClass($blockClass); + $reflection = new ReflectionClass($blockClass); $constructor = $reflection->getConstructor(); if (! $constructor) { diff --git a/packages/builder/src/Services/Block/BlockReconstructor.php b/packages/builder/src/Services/Block/BlockReconstructor.php index ea77ed4c6..a308dee2f 100644 --- a/packages/builder/src/Services/Block/BlockReconstructor.php +++ b/packages/builder/src/Services/Block/BlockReconstructor.php @@ -4,6 +4,7 @@ namespace Moox\Builder\Services\Block; +use Exception; use RuntimeException; class BlockReconstructor @@ -34,14 +35,12 @@ public function reconstruct(object $build): array foreach ($blockData as $data) { try { $block = $this->reconstructBlock($data, $build->entity_id); - if ($block) { + if ($block !== null) { $blocks[] = $block; } - } catch (\Exception $e) { - throw new RuntimeException( - 'Block reconstruction failed: '.$e->getMessage(). - ' Data: '.json_encode($data) - ); + } catch (Exception $e) { + throw new RuntimeException('Block reconstruction failed: '.$e->getMessage(). + ' Data: '.json_encode($data), $e->getCode(), $e); } } @@ -52,7 +51,7 @@ protected function reconstructBlock(array $data, int $entityId): ?object { $block = $this->blockFactory->createFromBuild($data['type'], $entityId); - if (! $block) { + if ($block === null) { return null; } diff --git a/packages/builder/src/Services/Build/BuildManager.php b/packages/builder/src/Services/Build/BuildManager.php index bfba41a29..900468bd4 100644 --- a/packages/builder/src/Services/Build/BuildManager.php +++ b/packages/builder/src/Services/Build/BuildManager.php @@ -6,6 +6,7 @@ use Moox\Builder\Services\Block\BlockReconstructor; use Moox\Builder\Services\ContextAwareService; +use Override; use RuntimeException; class BuildManager extends ContextAwareService @@ -56,7 +57,7 @@ protected function validateBuildContext(string $context): void protected function validateEntityExists(int $entityId): void { if (! $this->buildRecorder->validateEntityExists($entityId)) { - throw new RuntimeException("Entity {$entityId} not found"); + throw new RuntimeException(sprintf('Entity %d not found', $entityId)); } } @@ -67,20 +68,22 @@ protected function hasConflictingProductionBuild(int $entityId, string $newConte protected function validateFiles(array $files): void { - if (empty($files)) { + if ($files === []) { throw new RuntimeException('No files provided for build recording'); } foreach ($files as $type => $typeFiles) { if (! is_array($typeFiles)) { - throw new RuntimeException("Invalid file structure for type: {$type}"); + throw new RuntimeException('Invalid file structure for type: '.$type); } + foreach ($typeFiles as $path => $content) { if (! is_string($path)) { - throw new RuntimeException("Invalid path in type {$type}"); + throw new RuntimeException('Invalid path in type '.$type); } + if (! is_string($content)) { - throw new RuntimeException("Invalid content for path {$path} in type {$type}"); + throw new RuntimeException(sprintf('Invalid content for path %s in type %s', $path, $type)); } } } @@ -88,7 +91,7 @@ protected function validateFiles(array $files): void protected function validateBlocks(array $blocks): void { - if (empty($blocks)) { + if ($blocks === []) { throw new RuntimeException('Blocks array cannot be empty'); } @@ -96,12 +99,14 @@ protected function validateBlocks(array $blocks): void if (! method_exists($block, 'getOptions') || ! method_exists($block, 'getMigrations')) { throw new RuntimeException('Invalid block object: missing required methods'); } + if (! method_exists($block, 'getTitle') || ! method_exists($block, 'getDescription')) { throw new RuntimeException('Invalid block object: missing title or description methods'); } } } + #[Override] protected function validateContextConfig(): void { $config = $this->context->getConfig(); @@ -109,14 +114,14 @@ protected function validateContextConfig(): void if (! isset($config['base_path'], $config['base_namespace'], $config['generators'])) { throw new RuntimeException( - "Missing required configuration for context {$contextType}" + 'Missing required configuration for context '.$contextType ); } foreach ($config['generators'] as $type => $genConfig) { if (! isset($genConfig['path'], $genConfig['namespace'])) { throw new RuntimeException( - "Invalid generator configuration for {$type} in context {$contextType}" + sprintf('Invalid generator configuration for %s in context %s', $type, $contextType) ); } } diff --git a/packages/builder/src/Services/Build/BuildRecorder.php b/packages/builder/src/Services/Build/BuildRecorder.php index b047de02c..d15ae64c0 100644 --- a/packages/builder/src/Services/Build/BuildRecorder.php +++ b/packages/builder/src/Services/Build/BuildRecorder.php @@ -4,6 +4,7 @@ namespace Moox\Builder\Services\Build; +use Exception; use Illuminate\Support\Facades\DB; use Moox\Builder\Blocks\AbstractBlock; use RuntimeException; @@ -12,14 +13,14 @@ class BuildRecorder { public function record(int $entityId, string $buildContext, array $blocks, array $files): void { - if (empty($blocks)) { + if ($blocks === []) { throw new RuntimeException( 'Blocks array empty in BuildRecorder. Debug trace: '. json_encode([ 'entityId' => $entityId, 'context' => $buildContext, 'blockCount' => count($blocks), - 'blockTypes' => array_map(fn ($block) => get_class($block), $blocks), + 'blockTypes' => array_map(fn ($block) => $block::class, $blocks), 'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5), ]) ); @@ -30,10 +31,10 @@ public function record(int $entityId, string $buildContext, array $blocks, array $this->validateFileStructure($files); $blockData = $this->serializeBlocks($blocks); - if (empty($blockData)) { + if ($blockData === []) { throw new RuntimeException( 'Serialized block data empty. Original blocks: '. - json_encode(array_map(fn ($block) => get_class($block), $blocks)) + json_encode(array_map(fn ($block) => $block::class, $blocks)) ); } @@ -42,13 +43,11 @@ public function record(int $entityId, string $buildContext, array $blocks, array $this->persistBlocks($entityId, $blocks); DB::commit(); - } catch (\Exception $e) { + } catch (Exception $exception) { DB::rollBack(); - throw new RuntimeException( - 'Build recording failed: '.$e->getMessage(). - "\nBlock count: ".count($blocks). - "\nBlock types: ".json_encode(array_map(fn ($block) => get_class($block), $blocks)) - ); + throw new RuntimeException('Build recording failed: '.$exception->getMessage(). + "\nBlock count: ".count($blocks). + "\nBlock types: ".json_encode(array_map(fn ($block) => $block::class, $blocks)), $exception->getCode(), $exception); } } @@ -82,8 +81,8 @@ public function loadCurrentState(int $entityId, string $contextType): array return [ 'entity_id' => $build->entity_id, 'build_context' => $build->build_context, - 'data' => json_decode($build->data, true), - 'files' => json_decode($build->files, true), + 'data' => json_decode((string) $build->data, true), + 'files' => json_decode((string) $build->files, true), ]; } @@ -126,7 +125,7 @@ protected function persistBlocks(int $entityId, array $blocks): void 'entity_id' => $entityId, 'title' => $block->getTitle(), 'description' => $block->getDescription(), - 'block_class' => get_class($block), + 'block_class' => $block::class, 'options' => json_encode($block->getOptions()), 'sort_order' => $index, 'created_at' => now(), @@ -137,19 +136,21 @@ protected function persistBlocks(int $entityId, array $blocks): void protected function serializeBlocks(array $blocks): array { - $serialized = array_map(function ($block) { + $serialized = array_map(function ($block): array { if (! $block instanceof AbstractBlock) { throw new RuntimeException('Invalid block: must be instance of AbstractBlock'); } $data = [ - 'type' => get_class($block), + 'type' => $block::class, 'title' => $block->getTitle(), 'description' => $block->getDescription(), 'options' => $block->getOptions(), 'migrations' => $block->getMigrations(), ]; + /** @var mixed $block */ + /** @phpstan-ignore-next-line */ if (method_exists($block, 'getUseStatements')) { $data['useStatements'] = [ 'model' => $block->getUseStatements('model'), @@ -157,6 +158,7 @@ protected function serializeBlocks(array $blocks): array 'pages' => $block->getUseStatements('pages'), ]; } + if (method_exists($block, 'getTraits')) { $data['traits'] = [ 'model' => $block->getTraits('model'), @@ -164,12 +166,15 @@ protected function serializeBlocks(array $blocks): array 'pages' => $block->getTraits('pages'), ]; } + if (method_exists($block, 'getMethods')) { $data['methods'] = $block->getMethods('model'); } + if (method_exists($block, 'getFormFields')) { $data['formFields'] = $block->getFormFields(); } + if (method_exists($block, 'getTableColumns')) { $data['tableColumns'] = $block->getTableColumns(); } @@ -177,7 +182,7 @@ protected function serializeBlocks(array $blocks): array return $data; }, $blocks); - if (empty($serialized)) { + if ($serialized === []) { throw new RuntimeException('Failed to serialize blocks'); } @@ -188,14 +193,16 @@ protected function validateFileStructure(array $files): void { foreach ($files as $type => $typeFiles) { if (! is_array($typeFiles)) { - throw new RuntimeException("Invalid file structure for type: {$type}"); + throw new RuntimeException('Invalid file structure for type: '.$type); } + foreach ($typeFiles as $path => $content) { if (! is_string($path)) { - throw new RuntimeException("Invalid path in type {$type}"); + throw new RuntimeException('Invalid path in type '.$type); } + if (! is_string($content)) { - throw new RuntimeException("Invalid content for path {$path} in type {$type}"); + throw new RuntimeException(sprintf('Invalid content for path %s in type %s', $path, $type)); } } } @@ -214,7 +221,7 @@ public function getLatestBuild(int $entityId, ?string $buildContext = null): obj $build = $query->orderBy('created_at', 'desc')->first(); if (! $build) { - throw new RuntimeException("No active build found for entity {$entityId}"); + throw new RuntimeException('No active build found for entity '.$entityId); } return $build; @@ -227,7 +234,7 @@ public function getEntityIdFromName(string $entityName): int ->first(); if (! $entity) { - throw new RuntimeException("Entity not found with name: {$entityName}"); + throw new RuntimeException('Entity not found with name: '.$entityName); } return $entity->id; diff --git a/packages/builder/src/Services/ContextAwareService.php b/packages/builder/src/Services/ContextAwareService.php index 1a3221200..5a449a7a7 100644 --- a/packages/builder/src/Services/ContextAwareService.php +++ b/packages/builder/src/Services/ContextAwareService.php @@ -18,7 +18,7 @@ public function setContext(BuildContext $context): void protected function ensureContextIsSet(): void { - if (! $this->context) { + if (! $this->context instanceof BuildContext) { throw new RuntimeException('Context must be set before execution'); } } @@ -47,14 +47,14 @@ protected function validateContextConfig(): void if (! isset($config['base_path'], $config['base_namespace'], $config['generators'])) { throw new RuntimeException( - "Missing required configuration for context {$contextType}" + 'Missing required configuration for context '.$contextType ); } foreach ($config['generators'] as $type => $genConfig) { if (! isset($genConfig['path'])) { throw new RuntimeException( - "Missing path configuration for generator {$type} in context {$contextType}" + sprintf('Missing path configuration for generator %s in context %s', $type, $contextType) ); } } diff --git a/packages/builder/src/Services/Entity/EntityCreator.php b/packages/builder/src/Services/Entity/EntityCreator.php index 4f219837f..a0f9e7df2 100644 --- a/packages/builder/src/Services/Entity/EntityCreator.php +++ b/packages/builder/src/Services/Entity/EntityCreator.php @@ -21,7 +21,7 @@ public function __construct( public function setBlocks(array $blocks): void { - if (empty($blocks)) { + if ($blocks === []) { throw new RuntimeException('Blocks array cannot be empty'); } @@ -49,6 +49,7 @@ public function execute(): void $this->entityGenerator->setContext($this->context); $this->entityGenerator->execute(); + $generatedData = $this->entityGenerator->getGenerationResult(); if (! isset($generatedData['blocks'])) { @@ -57,7 +58,7 @@ public function execute(): void $this->blocks = $generatedData['blocks']; - if (empty($this->blocks)) { + if ($this->blocks === []) { throw new RuntimeException('Blocks array empty after generation. Debug: '.print_r($this->blocks, true)); } diff --git a/packages/builder/src/Services/Entity/EntityDeleter.php b/packages/builder/src/Services/Entity/EntityDeleter.php index dd49a2f31..32d7d0f39 100644 --- a/packages/builder/src/Services/Entity/EntityDeleter.php +++ b/packages/builder/src/Services/Entity/EntityDeleter.php @@ -19,7 +19,7 @@ public function execute(): void $this->ensureContextIsSet(); $entity = $this->findEntity($this->context->getEntityName()); - if (! $entity) { + if ($entity === null) { throw new RuntimeException('Entity not found'); } diff --git a/packages/builder/src/Services/Entity/EntityGenerator.php b/packages/builder/src/Services/Entity/EntityGenerator.php index 171d7b00e..f4a8e377f 100644 --- a/packages/builder/src/Services/Entity/EntityGenerator.php +++ b/packages/builder/src/Services/Entity/EntityGenerator.php @@ -20,18 +20,11 @@ class EntityGenerator extends ContextAwareService protected array $generatedData = []; - protected array $blocks = []; - protected array $originalBlocks = []; protected array $generationResult = []; - public function __construct( - private readonly FileManager $fileManager, - array $blocks = [] - ) { - $this->blocks = $blocks; - } + public function __construct(private readonly FileManager $fileManager, protected array $blocks = []) {} public function setBlocks(array $blocks): void { @@ -56,7 +49,7 @@ protected function initializeGenerators(): void { $this->validateContext(); $contextType = $this->context->getContextType(); - $contextConfig = config("builder.contexts.{$contextType}"); + $contextConfig = config('builder.contexts.'.$contextType); Log::info('EntityGenerator: Initializing generators', [ 'contextType' => $contextType, @@ -64,12 +57,12 @@ protected function initializeGenerators(): void ]); if (! isset($contextConfig['generators'])) { - throw new RuntimeException("No generators configured for context {$contextType}"); + throw new RuntimeException('No generators configured for context '.$contextType); } foreach ($contextConfig['generators'] as $name => $config) { if (! isset($config['generator'])) { - throw new RuntimeException("Generator class not specified for {$name}"); + throw new RuntimeException('Generator class not specified for '.$name); } $generatorClass = $config['generator']; @@ -88,7 +81,7 @@ protected function initializeGenerators(): void protected function reinitializeGenerators(): void { - if (! empty($this->generators)) { + if ($this->generators !== []) { $this->initializeGenerators(); } } @@ -99,9 +92,9 @@ protected function generateFiles(): void 'generatorCount' => count($this->generators), ]); - foreach ($this->generators as $name => $generator) { + foreach ($this->generators as $generator) { Log::info('EntityGenerator: Generating files with generator', [ - 'generator' => get_class($generator), + 'generator' => $generator::class, ]); $generator->generate(); diff --git a/packages/builder/src/Services/Entity/EntityRebuilder.php b/packages/builder/src/Services/Entity/EntityRebuilder.php index 33d4c5874..de040dd3a 100644 --- a/packages/builder/src/Services/Entity/EntityRebuilder.php +++ b/packages/builder/src/Services/Entity/EntityRebuilder.php @@ -45,6 +45,7 @@ public function execute(): void $this->entityGenerator->setContext($this->context); $this->entityGenerator->execute(); + $generatedData = $this->entityGenerator->getGenerationResult(); $this->buildManager->recordBuild( diff --git a/packages/builder/src/Services/Entity/SectionManager.php b/packages/builder/src/Services/Entity/SectionManager.php index 5c03b9f48..06c863e9b 100644 --- a/packages/builder/src/Services/Entity/SectionManager.php +++ b/packages/builder/src/Services/Entity/SectionManager.php @@ -26,6 +26,7 @@ public function addBlock(AbstractBlock $block): void if (! isset($this->metaSections[$sectionName])) { $this->metaSections[$sectionName] = []; } + $this->metaSections[$sectionName] = array_merge( $this->metaSections[$sectionName], $fields @@ -34,6 +35,7 @@ public function addBlock(AbstractBlock $block): void if (! isset($this->sections[$sectionName])) { $this->sections[$sectionName] = []; } + $this->sections[$sectionName] = array_merge( $this->sections[$sectionName], $fields @@ -58,7 +60,7 @@ public function addBlock(AbstractBlock $block): void public function formatSections(array $sections): string { - if (empty($sections)) { + if ($sections === []) { return ''; } @@ -72,11 +74,9 @@ public function formatSections(array $sections): string continue; } - $fields = array_map(function ($field) { - return " {$field},"; - }, $section['fields']); + $fields = array_map(fn ($field): string => sprintf(' %s,', $field), $section['fields']); - $sectionTitle = $section['hideHeader'] ?? false ? "''" : "'".ucfirst($section['name'])."'"; + $sectionTitle = $section['hideHeader'] ?? false ? "''" : "'".ucfirst((string) $section['name'])."'"; $output[] = " Section::make({$sectionTitle}) ->schema([ diff --git a/packages/builder/src/Services/File/FileFormatter.php b/packages/builder/src/Services/File/FileFormatter.php index c7e6dc938..29611340d 100644 --- a/packages/builder/src/Services/File/FileFormatter.php +++ b/packages/builder/src/Services/File/FileFormatter.php @@ -10,22 +10,22 @@ class FileFormatter { public function formatFiles(array $paths): void { - if (empty($paths)) { + if ($paths === []) { return; } $fileList = implode(' ', array_map( - fn ($path) => escapeshellarg(str_replace('\\', '/', $path)), + fn ($path): string => escapeshellarg(str_replace('\\', '/', $path)), array_filter($paths) )); - if (empty($fileList)) { + if ($fileList === '' || $fileList === '0') { return; } $command = PHP_OS_FAMILY === 'Windows' - ? "php vendor/bin/pint {$fileList} --quiet" - : "vendor/bin/pint {$fileList} --quiet"; + ? sprintf('php vendor/bin/pint %s --quiet', $fileList) + : sprintf('vendor/bin/pint %s --quiet', $fileList); exec($command, $output, $returnCode); diff --git a/packages/builder/src/Services/File/FileManager.php b/packages/builder/src/Services/File/FileManager.php index 616c2cf39..1cf1d5acb 100644 --- a/packages/builder/src/Services/File/FileManager.php +++ b/packages/builder/src/Services/File/FileManager.php @@ -28,12 +28,12 @@ public function deleteFiles(int $entityId, string $buildContext): void return; } - $files = json_decode($build->files, true); + $files = json_decode((string) $build->files, true); foreach ($files as $file) { $path = $file['path'] ?? null; if ($path) { $this->fileOperations->deleteFile($path); - $this->removeEmptyDirectories(dirname($path)); + $this->removeEmptyDirectories(dirname((string) $path)); } } } @@ -53,8 +53,9 @@ public function writeAndFormatFiles(array $files): void } if (file_put_contents($path, $content) === false) { - throw new RuntimeException("Failed to write file: {$path}"); + throw new RuntimeException('Failed to write file: '.$path); } + $paths[] = $path; } @@ -64,15 +65,11 @@ public function writeAndFormatFiles(array $files): void public function formatFiles(array $files): void { - if (empty($files)) { + if ($files === []) { return; } - if (isset($files[0])) { - $paths = $files; - } else { - $paths = array_keys($files); - } + $paths = isset($files[0]) ? $files : array_keys($files); $this->fileFormatter->formatFiles($paths); } @@ -80,7 +77,7 @@ public function formatFiles(array $files): void public function findMigrationFiles(string $path): array { if (! is_dir($path)) { - throw new RuntimeException("Migration directory not found: {$path}"); + throw new RuntimeException('Migration directory not found: '.$path); } $finder = new Finder; @@ -100,7 +97,7 @@ public function findMigrationFiles(string $path): array protected function removeEmptyDirectories(string $path): void { - if (empty($path) || $path === '.' || $path === '/') { + if ($path === '' || $path === '0' || $path === '.' || $path === '/') { return; } @@ -112,23 +109,21 @@ protected function removeEmptyDirectories(string $path): void protected function ensureDirectoryExists(string $directory): void { - if (! File::exists($directory)) { - if (! File::makeDirectory($directory, 0755, true)) { - throw new RuntimeException("Failed to create directory: {$directory}"); - } + if (! File::exists($directory) && ! File::makeDirectory($directory, 0755, true)) { + throw new RuntimeException('Failed to create directory: '.$directory); } } protected function writeFile(string $path, string $content): void { if (! File::put($path, $content)) { - throw new RuntimeException("Failed to write file: {$path}"); + throw new RuntimeException('Failed to write file: '.$path); } } protected function validateFiles(array $files): void { - if (empty($files)) { + if ($files === []) { throw new RuntimeException('No files provided for operation'); } @@ -136,14 +131,17 @@ protected function validateFiles(array $files): void if (! is_string($path)) { throw new RuntimeException('File path must be a string'); } + if (! is_string($content)) { throw new RuntimeException('File content must be a string'); } - if (empty(trim($path))) { + + if (in_array(trim($path), ['', '0'], true)) { throw new RuntimeException('File path cannot be empty'); } + if (File::exists($path) && ! is_writable($path)) { - throw new RuntimeException("File not writable: {$path}"); + throw new RuntimeException('File not writable: '.$path); } } } diff --git a/packages/builder/src/Services/Preview/PreviewTableManager.php b/packages/builder/src/Services/Preview/PreviewTableManager.php index 882c67d23..172bc5557 100644 --- a/packages/builder/src/Services/Preview/PreviewTableManager.php +++ b/packages/builder/src/Services/Preview/PreviewTableManager.php @@ -38,7 +38,7 @@ public function execute(): void $tableName = $this->context->getTableName(); $this->dropTableIfExists($tableName); - Schema::create($tableName, function (Blueprint $table) { + Schema::create($tableName, function (Blueprint $table): void { $table->id(); foreach ($this->blocks as $block) { @@ -59,7 +59,7 @@ public function execute(): void protected function addField(Blueprint $table, string $field): void { $field = trim(rtrim($field, ';')); - if (! empty($field)) { + if ($field !== '' && $field !== '0') { $field = str_replace('$table->', '', $field); eval('$table->'.$field.';'); } diff --git a/packages/builder/src/Support/SectionBuilder.php b/packages/builder/src/Support/SectionBuilder.php index 8350772e7..b5fa3a5be 100644 --- a/packages/builder/src/Support/SectionBuilder.php +++ b/packages/builder/src/Support/SectionBuilder.php @@ -14,25 +14,19 @@ class SectionBuilder private array $sections; - private string $name; - - private int $order; - private bool $hideHeader = false; public function __construct( array &$sections, - string $name, - int $order = 0 + private readonly string $name, + private int $order = 0 ) { $this->sections = &$sections; - $this->name = $name; - $this->order = $order; - if (isset($this->sections[$name])) { - $this->isMeta = $this->sections[$name]['isMeta'] ?? false; - $this->fields = $this->sections[$name]['fields'] ?? []; - $this->order = $this->sections[$name]['order'] ?? 0; + if (isset($this->sections[$this->name])) { + $this->isMeta = $this->sections[$this->name]['isMeta'] ?? false; + $this->fields = $this->sections[$this->name]['fields'] ?? []; + $this->order = $this->sections[$this->name]['order'] ?? 0; } } diff --git a/packages/builder/src/Traits/HandlesContentCleanup.php b/packages/builder/src/Traits/HandlesContentCleanup.php index c2cf7c9d4..8d7f44e26 100644 --- a/packages/builder/src/Traits/HandlesContentCleanup.php +++ b/packages/builder/src/Traits/HandlesContentCleanup.php @@ -11,22 +11,22 @@ protected function cleanupContent(string $content, string $classType = 'Model'): // Remove multiple empty lines $content = preg_replace("/\n\n\n+/", "\n\n", $content); // Remove empty arrays - $content = preg_replace("/\[\n \n \]/", '[]', $content); + $content = preg_replace("/\[\n \n \]/", '[]', (string) $content); // Remove empty casts - $content = preg_replace("/\n\n protected \\\$casts = \[\n \n \];\n/", '', $content); + $content = preg_replace("/\n\n protected \\\$casts = \[\n \n \];\n/", '', (string) $content); // Remove empty traits - $content = preg_replace("/\n \n/", "\n", $content); + $content = preg_replace("/\n \n/", "\n", (string) $content); // Remove empty lines between form/table setup and return - $content = preg_replace("/\{\n \n\n return/", "{\n return", $content); + $content = preg_replace("/\{\n \n\n return/", "{\n return", (string) $content); // Remove empty lines after class opening brace - $content = preg_replace("/class (.+) extends .*\n{(\n+)/", "class $1 extends $classType\n{\n", $content); + $content = preg_replace("/class (.+) extends .*\n{(\n+)/", "class $1 extends {$classType}\n{\n", (string) $content); // Remove empty line at the end of the class - $content = preg_replace("/\n\n}/", "\n}", $content); + $content = preg_replace("/\n\n}/", "\n}", (string) $content); return $content; } diff --git a/packages/builder/src/Traits/HandlesIndentation.php b/packages/builder/src/Traits/HandlesIndentation.php index 671af45c3..18e3341e0 100644 --- a/packages/builder/src/Traits/HandlesIndentation.php +++ b/packages/builder/src/Traits/HandlesIndentation.php @@ -11,20 +11,20 @@ protected function indent(string $content, int $level = 1): string $indentation = str_repeat(' ', $level); return implode("\n", array_map( - fn ($line) => $line !== '' ? $indentation.$line : $line, + fn ($line): string => $line !== '' ? $indentation.$line : $line, explode("\n", $content) )); } protected function formatWithIndentation(array $items, int $level = 1, string $separator = ';'): string { - if (empty($items)) { + if ($items === []) { return ''; } $indentation = str_repeat(' ', $level); $formattedItems = array_map( - fn ($item) => $indentation.trim($item, "'"), + fn ($item): string => $indentation.trim((string) $item, "'"), $items ); diff --git a/packages/builder/src/Traits/HandlesMigrationFiles.php b/packages/builder/src/Traits/HandlesMigrationFiles.php index 538b8d11a..24e539dc6 100644 --- a/packages/builder/src/Traits/HandlesMigrationFiles.php +++ b/packages/builder/src/Traits/HandlesMigrationFiles.php @@ -5,6 +5,7 @@ namespace Moox\Builder\Traits; use Illuminate\Support\Facades\DB; +use InvalidArgumentException; trait HandlesMigrationFiles { @@ -17,7 +18,7 @@ protected function getMigrationPattern(): string 'app' => $migrationPath.'/[0-9]{4}_[0-9]{2}_[0-9]{2}_[0-9]{6}_create_'.$tableName.'_table.php', 'package' => $migrationPath.'/create_'.$tableName.'_table.php.stub', 'preview' => $migrationPath.'/preview_[0-9]{4}_[0-9]{2}_[0-9]{2}_[0-9]{6}_create_'.$tableName.'_table.php', - default => throw new \InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), + default => throw new InvalidArgumentException('Invalid context type: '.$this->context->getContextType()), }; } @@ -37,7 +38,7 @@ protected function findMigrationFile(): ?string ->first(); if ($latestBuild) { - $files = json_decode($latestBuild->files, true); + $files = json_decode((string) $latestBuild->files, true); if (isset($files['migration']) && file_exists($files['migration'])) { return $files['migration']; } @@ -47,6 +48,6 @@ protected function findMigrationFile(): ?string $pattern = $this->getMigrationPattern(); $files = glob($pattern); - return ! empty($files) ? $files[0] : null; + return $files === [] || $files === false ? null : $files[0]; } } diff --git a/packages/builder/src/Traits/ValidatesEntity.php b/packages/builder/src/Traits/ValidatesEntity.php index da9b89583..6f18f4828 100644 --- a/packages/builder/src/Traits/ValidatesEntity.php +++ b/packages/builder/src/Traits/ValidatesEntity.php @@ -12,7 +12,7 @@ trait ValidatesEntity protected function validateEntityExists(int $entityId): void { if (! DB::table('builder_entities')->where('id', $entityId)->exists()) { - throw new RuntimeException("Entity {$entityId} not found"); + throw new RuntimeException(sprintf('Entity %d not found', $entityId)); } } @@ -24,7 +24,7 @@ protected function validateBuildExists(int $entityId, string $buildContext): voi ->where('is_active', true) ->exists() ) { - throw new RuntimeException("No active build found for entity {$entityId} in context {$buildContext}"); + throw new RuntimeException(sprintf('No active build found for entity %d in context %s', $entityId, $buildContext)); } } } diff --git a/packages/builder/tests/ArchTest.php b/packages/builder/tests/ArchTest.php index f76321f56..9b60c828e 100644 --- a/packages/builder/tests/ArchTest.php +++ b/packages/builder/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\Builder') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\Builder\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\Builder'); arch()->preset()->php(); diff --git a/packages/builder/tests/Feature/ExampleTest.php b/packages/builder/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/builder/tests/Feature/ExampleTest.php +++ b/packages/builder/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/builder/tests/Pest.php b/packages/builder/tests/Pest.php index 7c1359001..4c2b2c9e0 100644 --- a/packages/builder/tests/Pest.php +++ b/packages/builder/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/builder/tests/Unit/ExampleTest.php b/packages/builder/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/builder/tests/Unit/ExampleTest.php +++ b/packages/builder/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/builder/workbench/app/Models/.gitkeep b/packages/builder/workbench/app/Models/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/builder/workbench/app/Models/User.php b/packages/builder/workbench/app/Models/User.php deleted file mode 100644 index f241576b9..000000000 --- a/packages/builder/workbench/app/Models/User.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - protected $fillable = [ - 'name', - 'email', - 'password', - ]; - - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ - protected $hidden = [ - 'password', - 'remember_token', - ]; - - /** - * The attributes that should be cast. - * - * @var array - */ - protected $casts = [ - 'email_verified_at' => 'datetime', - 'password' => 'hashed', - ]; - - /** - * Determine if the user can access the Filament panel. - */ - public function canAccessPanel(Panel $panel): bool - { - return true; - } - - /** - * This method determines if the user can access the Filament panel. - * It always returns true, indicating that all users have access to the panel. - */ - protected static function newFactory() - { - return \Workbench\Database\Factories\UserFactory::new(); - } -} diff --git a/packages/builder/workbench/app/Providers/AdminPanelProvider.php b/packages/builder/workbench/app/Providers/AdminPanelProvider.php deleted file mode 100644 index 3a91b7496..000000000 --- a/packages/builder/workbench/app/Providers/AdminPanelProvider.php +++ /dev/null @@ -1,63 +0,0 @@ -default() - ->id('admin') - ->path('admin') - ->passwordReset() - ->login() - ->colors([ - 'primary' => Color::Amber, - ]) - ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources') - ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages') - ->pages([ - Pages\Dashboard::class, - ]) - ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets') - ->widgets([ - Widgets\AccountWidget::class, - Widgets\FilamentInfoWidget::class, - ]) - ->middleware([ - EncryptCookies::class, - AddQueuedCookiesToResponse::class, - StartSession::class, - AuthenticateSession::class, - ShareErrorsFromSession::class, - VerifyCsrfToken::class, - SubstituteBindings::class, - DisableBladeIconComponents::class, - DispatchServingFilamentEvent::class, - ]) - ->authMiddleware([ - Authenticate::class, - ]) - ->spa() - ->plugins([ - \Moox\Builder\ItemPlugin::make(), - ]); - } -} diff --git a/packages/builder/workbench/app/Providers/WorkbenchServiceProvider.php b/packages/builder/workbench/app/Providers/WorkbenchServiceProvider.php deleted file mode 100644 index e8cec9c2a..000000000 --- a/packages/builder/workbench/app/Providers/WorkbenchServiceProvider.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -class UserFactory extends Factory -{ - /** - * The current password being used by the factory. - */ - protected static ?string $password; - - /** - * The name of the factory's corresponding model. - * - * @var class-string - */ - protected $model = User::class; - - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - 'name' => fake()->name(), - 'email' => fake()->unique()->safeEmail(), - 'email_verified_at' => now(), - 'password' => static::$password ??= Hash::make('password'), - 'remember_token' => Str::random(10), - ]; - } - - /** - * Indicate that the model's email address should be unverified. - */ - public function unverified(): static - { - return $this->state(fn (array $attributes) => [ - 'email_verified_at' => null, - ]); - } -} diff --git a/packages/builder/workbench/database/migrations/.gitkeep b/packages/builder/workbench/database/migrations/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/builder/workbench/database/seeders/DatabaseSeeder.php b/packages/builder/workbench/database/seeders/DatabaseSeeder.php deleted file mode 100644 index ce9bd1597..000000000 --- a/packages/builder/workbench/database/seeders/DatabaseSeeder.php +++ /dev/null @@ -1,23 +0,0 @@ -create(); - - UserFactory::new()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', - ]); - } -} diff --git a/packages/builder/workbench/resources/views/.gitkeep b/packages/builder/workbench/resources/views/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/builder/workbench/routes/web.php b/packages/builder/workbench/routes/web.php deleted file mode 100644 index 86a06c53e..000000000 --- a/packages/builder/workbench/routes/web.php +++ /dev/null @@ -1,7 +0,0 @@ -art(); $this->welcome(); @@ -80,6 +80,7 @@ public function publishConfiguration(): void return; } + warning('The Category config already exist. The config will not be published.'); } } @@ -92,6 +93,7 @@ public function publishMigrations(): void return; } + info('Publishing Categorys Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'category-migrations']); } @@ -128,22 +130,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -184,12 +186,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/category/src/Forms/TaxonomyCreateForm.php b/packages/category/src/Forms/TaxonomyCreateForm.php index 810323e8b..f6a0d5c4e 100644 --- a/packages/category/src/Forms/TaxonomyCreateForm.php +++ b/packages/category/src/Forms/TaxonomyCreateForm.php @@ -33,7 +33,7 @@ public static function getSchema(): array ) ->label('Parent Category') ->searchable() - ->disabledOptions(fn ($get) => [$get('id')]) + ->disabledOptions(fn ($get): array => [$get('id')]) ->enableBranchNode(), Grid::make(2) ->schema([ diff --git a/packages/category/src/Models/Category.php b/packages/category/src/Models/Category.php index 61c1787e6..4ea68a3f4 100644 --- a/packages/category/src/Models/Category.php +++ b/packages/category/src/Models/Category.php @@ -12,10 +12,13 @@ use Illuminate\Support\Facades\DB; use Kalnoy\Nestedset\NodeTrait; use Moox\Category\Database\Factories\CategoryFactory; +use Override; class Category extends Model { - use HasFactory, NodeTrait, SoftDeletes; + use HasFactory; + use NodeTrait; + use SoftDeletes; protected $table = 'categories'; @@ -60,9 +63,10 @@ public function detachAllCategorizables(): void DB::table('categorizables')->where('category_id', $this->id)->delete(); } + #[Override] protected static function booted(): void { - static::deleting(function (Category $category) { + static::deleting(function (Category $category): void { $category->detachAllCategorizables(); }); } diff --git a/packages/category/src/Resources/CategoryResource.php b/packages/category/src/Resources/CategoryResource.php index 242f2998b..110461a43 100644 --- a/packages/category/src/Resources/CategoryResource.php +++ b/packages/category/src/Resources/CategoryResource.php @@ -7,6 +7,7 @@ use Camya\Filament\Forms\Components\TitleWithSlugInput; use CodeWithDennis\FilamentSelectTree\SelectTree; use Filament\Forms\Components\Actions; +use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\ColorPicker; use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Components\FileUpload; @@ -34,17 +35,20 @@ use Moox\Category\Resources\CategoryResource\Pages\ViewCategory; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; +use Override; // use Moox\Core\Forms\Components\TitleWithSlugInput; class CategoryResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = Category::class; protected static ?string $currentTab = null; + #[Override] public static function getEloquentQuery(): Builder { return parent::getEloquentQuery() @@ -54,6 +58,7 @@ public static function getEloquentQuery(): Builder protected static ?string $navigationIcon = 'gmdi-category'; + #[Override] public static function form(Form $form): Form { return $form @@ -81,7 +86,7 @@ public static function form(Form $form): Form ) ->label('Parent Category') ->searchable() - ->disabledOptions(fn ($get) => [$get('id')]) + ->disabledOptions(fn ($get): array => [$get('id')]) ->enableBranchNode(), ]), ]) @@ -91,74 +96,74 @@ public static function form(Form $form): Form Section::make() ->schema([ Actions::make([ - Actions\Action::make('restore') + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof ViewCategory), - Actions\Action::make('save') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof ViewCategory), + Action::make('save') ->label(__('core::core.save')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire instanceof CreateCategory ? $livewire->create() : $livewire->save(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateCategory || $livewire instanceof EditCategory), - Actions\Action::make('saveAndCreateAnother') + ->visible(fn ($livewire): bool => $livewire instanceof CreateCategory || $livewire instanceof EditCategory), + Action::make('saveAndCreateAnother') ->label(__('core::core.save_and_create_another')) ->color('secondary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire->saveAndCreateAnother(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateCategory), - Actions\Action::make('cancel') + ->visible(fn ($livewire): bool => $livewire instanceof CreateCategory), + Action::make('cancel') ->label(__('core::core.cancel')) ->color('secondary') ->outlined() ->extraAttributes(['class' => 'w-full']) - ->url(fn () => static::getUrl('index')) - ->visible(fn ($livewire) => $livewire instanceof CreateCategory), - Actions\Action::make('edit') + ->url(fn (): string => static::getUrl('index')) + ->visible(fn ($livewire): bool => $livewire instanceof CreateCategory), + Action::make('edit') ->label(__('core::core.edit')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) - ->visible(fn ($livewire, $record) => $livewire instanceof ViewCategory && ! $record->trashed()), - Actions\Action::make('restore') + ->url(fn ($record): string => static::getUrl('edit', ['record' => $record])) + ->visible(fn ($livewire, $record): bool => $livewire instanceof ViewCategory && ! $record->trashed()), + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof EditCategory), - Actions\Action::make('delete') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof EditCategory), + Action::make('delete') ->label(__('core::core.delete')) ->color('danger') ->link() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->delete()) - ->visible(fn ($livewire, $record) => $record && ! $record->trashed() && $livewire instanceof EditCategory), + ->visible(fn ($livewire, $record): bool => $record && ! $record->trashed() && $livewire instanceof EditCategory), ]), ColorPicker::make('color'), TextInput::make('weight'), TextInput::make('count') ->disabled() - ->visible(fn ($livewire, $record) => ($record && $livewire instanceof EditCategory) || ($record && $livewire instanceof ViewCategory)), + ->visible(fn ($livewire, $record): bool => ($record && $livewire instanceof EditCategory) || ($record && $livewire instanceof ViewCategory)), DateTimePicker::make('created_at') ->disabled() - ->visible(fn ($livewire, $record) => ($record && $livewire instanceof EditCategory) || ($record && $livewire instanceof ViewCategory)), + ->visible(fn ($livewire, $record): bool => ($record && $livewire instanceof EditCategory) || ($record && $livewire instanceof ViewCategory)), DateTimePicker::make('updated_at') ->disabled() - ->visible(fn ($livewire, $record) => ($record && $livewire instanceof EditCategory) || ($record && $livewire instanceof ViewCategory)), + ->visible(fn ($livewire, $record): bool => ($record && $livewire instanceof EditCategory) || ($record && $livewire instanceof ViewCategory)), DateTimePicker::make('deleted_at') ->disabled() - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof ViewCategory), + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof ViewCategory), ]), ]) ->columnSpan(['lg' => 1]), @@ -167,12 +172,13 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { $currentTab = static::getCurrentTab(); return $table - ->query(fn () => static::getEloquentQuery()) + ->query(fn (): Builder => static::getEloquentQuery()) ->defaultSort('_lft', 'asc') ->columns([ ImageColumn::make('featured_image_url') @@ -187,7 +193,7 @@ public static function table(Table $table): Table $depth = $record->ancestors->count(); $prefix = str_repeat('--', $depth); - return "{$prefix} {$record->title}"; + return sprintf('%s %s', $prefix, $record->title); }) ->searchable(), TextColumn::make('slug') @@ -231,19 +237,11 @@ public static function table(Table $table): Table ->defaultSort('slug', 'desc') ->actions([ ViewAction::make(), - EditAction::make()->hidden(fn () => in_array(static::getCurrentTab(), ['trash', 'deleted'])), + EditAction::make()->hidden(fn (): bool => in_array(static::getCurrentTab(), ['trash', 'deleted'])), ]) ->bulkActions([ - DeleteBulkAction::make()->hidden(function () use ($currentTab) { - $isHidden = in_array($currentTab, ['trash', 'deleted']); - - return $isHidden; - }), - RestoreBulkAction::make()->visible(function () use ($currentTab) { - $isVisible = in_array($currentTab, ['trash', 'deleted']); - - return $isVisible; - }), + DeleteBulkAction::make()->hidden(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), + RestoreBulkAction::make()->visible(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), ]) ->filters([ SelectFilter::make('parent_id') @@ -258,49 +256,37 @@ public static function table(Table $table): Table '6-10' => '6-10', '10+' => '10+', ]) - ->query(function (Builder $query, array $data) { - return $query->when($data['value'], function ($query, $option) { - switch ($option) { - case '0': - return $query->doesntHave('children'); - case '1-5': - return $query->has('children', '>=', 1)->has('children', '<=', 5); - case '6-10': - return $query->has('children', '>=', 6)->has('children', '<=', 10); - case '10+': - return $query->has('children', '>', 10); - } - }); - }), + ->query(fn (Builder $query, array $data) => $query->when($data['value'], function ($query, $option) { + switch ($option) { + case '0': + return $query->doesntHave('children'); + case '1-5': + return $query->has('children', '>=', 1)->has('children', '<=', 5); + case '6-10': + return $query->has('children', '>=', 6)->has('children', '<=', 10); + case '10+': + return $query->has('children', '>', 10); + } + })), SelectFilter::make('depth') ->label('Level') - ->options(fn () => array_combine(range(1, 5), range(1, 5))) - ->query(function (Builder $query, array $data) { - return $query->when($data['value'], function ($query, $depth) { - $query->whereIn('id', function ($subquery) use ($depth) { - $subquery->select('id') - ->from('categories as c') - ->whereRaw('(SELECT COUNT(*) FROM categories as ancestors WHERE ancestors._lft < c._lft AND ancestors._rgt > c._rgt) = ?', [$depth - 1]); - }); + ->options(fn (): array => array_combine(range(1, 5), range(1, 5))) + ->query(fn (Builder $query, array $data) => $query->when($data['value'], function ($query, $depth): void { + $query->whereIn('id', function ($subquery) use ($depth): void { + $subquery->select('id') + ->from('categories as c') + ->whereRaw('(SELECT COUNT(*) FROM categories as ancestors WHERE ancestors._lft < c._lft AND ancestors._rgt > c._rgt) = ?', [$depth - 1]); }); - }), + })), ]) ->defaultSort('slug', 'desc') ->actions([ ViewAction::make(), - EditAction::make()->hidden(fn () => in_array(static::getCurrentTab(), ['trash', 'deleted'])), + EditAction::make()->hidden(fn (): bool => in_array(static::getCurrentTab(), ['trash', 'deleted'])), ]) ->bulkActions([ - DeleteBulkAction::make()->hidden(function () use ($currentTab) { - $isHidden = in_array($currentTab, ['trash', 'deleted']); - - return $isHidden; - }), - RestoreBulkAction::make()->visible(function () use ($currentTab) { - $isVisible = in_array($currentTab, ['trash', 'deleted']); - - return $isVisible; - }), + DeleteBulkAction::make()->hidden(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), + RestoreBulkAction::make()->visible(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), ]) ->filters([ SelectFilter::make('parent_id') @@ -315,35 +301,32 @@ public static function table(Table $table): Table '6-10' => '6-10', '10+' => '10+', ]) - ->query(function (Builder $query, array $data) { - return $query->when($data['value'], function ($query, $option) { - switch ($option) { - case '0': - return $query->doesntHave('children'); - case '1-5': - return $query->has('children', '>=', 1)->has('children', '<=', 5); - case '6-10': - return $query->has('children', '>=', 6)->has('children', '<=', 10); - case '10+': - return $query->has('children', '>', 10); - } - }); - }), + ->query(fn (Builder $query, array $data) => $query->when($data['value'], function ($query, $option) { + switch ($option) { + case '0': + return $query->doesntHave('children'); + case '1-5': + return $query->has('children', '>=', 1)->has('children', '<=', 5); + case '6-10': + return $query->has('children', '>=', 6)->has('children', '<=', 10); + case '10+': + return $query->has('children', '>', 10); + } + })), SelectFilter::make('depth') ->label('Level') - ->options(fn () => array_combine(range(1, 5), range(1, 5))) - ->query(function (Builder $query, array $data) { - return $query->when($data['value'], function ($query, $depth) { - $query->whereIn('id', function ($subquery) use ($depth) { - $subquery->select('id') - ->from('categories as c') - ->whereRaw('(SELECT COUNT(*) FROM categories as ancestors WHERE ancestors._lft < c._lft AND ancestors._rgt > c._rgt) = ?', [$depth - 1]); - }); + ->options(fn (): array => array_combine(range(1, 5), range(1, 5))) + ->query(fn (Builder $query, array $data) => $query->when($data['value'], function ($query, $depth): void { + $query->whereIn('id', function ($subquery) use ($depth): void { + $subquery->select('id') + ->from('categories as c') + ->whereRaw('(SELECT COUNT(*) FROM categories as ancestors WHERE ancestors._lft < c._lft AND ancestors._rgt > c._rgt) = ?', [$depth - 1]); }); - }), + })), ]); } + #[Override] public static function getRelations(): array { return [ @@ -351,6 +334,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -361,42 +345,50 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ ]; } + #[Override] public static function getModelLabel(): string { return config('category.resources.category.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('category.resources.category.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('category.resources.category.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('category.resources.category.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return config('category.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('category.navigation_sort') + 3; diff --git a/packages/category/src/Resources/CategoryResource/Pages/CreateCategory.php b/packages/category/src/Resources/CategoryResource/Pages/CreateCategory.php index 2e6123b38..3af4ce030 100644 --- a/packages/category/src/Resources/CategoryResource/Pages/CreateCategory.php +++ b/packages/category/src/Resources/CategoryResource/Pages/CreateCategory.php @@ -6,6 +6,7 @@ use Filament\Resources\Pages\CreateRecord; use Moox\Category\Resources\CategoryResource; +use Override; class CreateCategory extends CreateRecord { @@ -16,6 +17,7 @@ protected function hasFormActionsInPanel(): bool return false; } + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/category/src/Resources/CategoryResource/Pages/EditCategory.php b/packages/category/src/Resources/CategoryResource/Pages/EditCategory.php index b774b3338..00880ade8 100644 --- a/packages/category/src/Resources/CategoryResource/Pages/EditCategory.php +++ b/packages/category/src/Resources/CategoryResource/Pages/EditCategory.php @@ -7,6 +7,7 @@ use Filament\Actions\DeleteAction; use Filament\Resources\Pages\EditRecord; use Moox\Category\Resources\CategoryResource; +use Override; class EditCategory extends EditRecord { @@ -19,6 +20,7 @@ protected function getHeaderActions(): array ]; } + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/category/src/Resources/CategoryResource/Pages/ListCategories.php b/packages/category/src/Resources/CategoryResource/Pages/ListCategories.php index 9d573d6ab..8bf9a1c3a 100644 --- a/packages/category/src/Resources/CategoryResource/Pages/ListCategories.php +++ b/packages/category/src/Resources/CategoryResource/Pages/ListCategories.php @@ -11,6 +11,7 @@ use Moox\Category\Models\Category; use Moox\Category\Resources\CategoryResource; use Moox\Core\Traits\Tabs\TabsInListPage; +use Override; class ListCategories extends ListRecords { @@ -22,15 +23,13 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Category { - return $model::create($data); - }) - ->hidden(fn () => $this->activeTab === 'deleted'), + ->using(fn (array $data, string $model): Category => $model::create($data)) + ->hidden(fn (): bool => $this->activeTab === 'deleted'), Action::make('emptyTrash') ->label(__('core::core.empty_trash')) ->icon('heroicon-o-trash') ->color('danger') - ->action(function () { + ->action(function (): void { $trashedCount = Category::onlyTrashed()->count(); Category::onlyTrashed()->forceDelete(); Notification::make() @@ -40,10 +39,11 @@ protected function getHeaderActions(): array ->send(); }) ->requiresConfirmation() - ->visible(fn () => $this->activeTab === 'deleted' && Category::onlyTrashed()->exists()), + ->visible(fn (): bool => $this->activeTab === 'deleted' && Category::onlyTrashed()->exists()), ]; } + #[Override] public function getTitle(): string { return config('category.resources.category.plural'); diff --git a/packages/category/src/Resources/CategoryResource/Pages/ViewCategory.php b/packages/category/src/Resources/CategoryResource/Pages/ViewCategory.php index 0582f2858..8534ea273 100644 --- a/packages/category/src/Resources/CategoryResource/Pages/ViewCategory.php +++ b/packages/category/src/Resources/CategoryResource/Pages/ViewCategory.php @@ -9,6 +9,7 @@ use Filament\Resources\Pages\ViewRecord; use Illuminate\Database\Eloquent\Model; use Moox\Category\Resources\CategoryResource; +use Override; class ViewCategory extends ViewRecord { @@ -22,6 +23,7 @@ protected function getHeaderActions(): array ]; } + #[Override] public function getTitle(): string { $title = parent::getTitle(); diff --git a/packages/category/tests/ArchTest.php b/packages/category/tests/ArchTest.php index 3e627b048..652b7a376 100644 --- a/packages/category/tests/ArchTest.php +++ b/packages/category/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\Category') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\Category\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\Category'); arch()->preset()->php(); diff --git a/packages/category/tests/Feature/ExampleTest.php b/packages/category/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/category/tests/Feature/ExampleTest.php +++ b/packages/category/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/category/tests/Pest.php b/packages/category/tests/Pest.php index 8979b2196..a0737fab1 100644 --- a/packages/category/tests/Pest.php +++ b/packages/category/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/category/tests/Unit/ExampleTest.php b/packages/category/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/category/tests/Unit/ExampleTest.php +++ b/packages/category/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/category/workbench/app/Models/.gitkeep b/packages/category/workbench/app/Models/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/category/workbench/app/Models/User.php b/packages/category/workbench/app/Models/User.php deleted file mode 100644 index f241576b9..000000000 --- a/packages/category/workbench/app/Models/User.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - protected $fillable = [ - 'name', - 'email', - 'password', - ]; - - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ - protected $hidden = [ - 'password', - 'remember_token', - ]; - - /** - * The attributes that should be cast. - * - * @var array - */ - protected $casts = [ - 'email_verified_at' => 'datetime', - 'password' => 'hashed', - ]; - - /** - * Determine if the user can access the Filament panel. - */ - public function canAccessPanel(Panel $panel): bool - { - return true; - } - - /** - * This method determines if the user can access the Filament panel. - * It always returns true, indicating that all users have access to the panel. - */ - protected static function newFactory() - { - return \Workbench\Database\Factories\UserFactory::new(); - } -} diff --git a/packages/category/workbench/app/Providers/AdminPanelProvider.php b/packages/category/workbench/app/Providers/AdminPanelProvider.php deleted file mode 100644 index ec5c49173..000000000 --- a/packages/category/workbench/app/Providers/AdminPanelProvider.php +++ /dev/null @@ -1,63 +0,0 @@ -default() - ->id('admin') - ->path('admin') - ->passwordReset() - ->login() - ->colors([ - 'primary' => Color::Amber, - ]) - ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources') - ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages') - ->pages([ - Pages\Dashboard::class, - ]) - ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets') - ->widgets([ - Widgets\AccountWidget::class, - Widgets\FilamentInfoWidget::class, - ]) - ->middleware([ - EncryptCookies::class, - AddQueuedCookiesToResponse::class, - StartSession::class, - AuthenticateSession::class, - ShareErrorsFromSession::class, - VerifyCsrfToken::class, - SubstituteBindings::class, - DisableBladeIconComponents::class, - DispatchServingFilamentEvent::class, - ]) - ->authMiddleware([ - Authenticate::class, - ]) - ->spa() - ->plugins([ - \Moox\Category\CategoryPlugin::make(), - ]); - } -} diff --git a/packages/category/workbench/app/Providers/WorkbenchServiceProvider.php b/packages/category/workbench/app/Providers/WorkbenchServiceProvider.php deleted file mode 100644 index e8cec9c2a..000000000 --- a/packages/category/workbench/app/Providers/WorkbenchServiceProvider.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -class UserFactory extends Factory -{ - /** - * The current password being used by the factory. - */ - protected static ?string $password; - - /** - * The name of the factory's corresponding model. - * - * @var class-string - */ - protected $model = User::class; - - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - 'name' => fake()->name(), - 'email' => fake()->unique()->safeEmail(), - 'email_verified_at' => now(), - 'password' => static::$password ??= Hash::make('password'), - 'remember_token' => Str::random(10), - ]; - } - - /** - * Indicate that the model's email address should be unverified. - */ - public function unverified(): static - { - return $this->state(fn (array $attributes) => [ - 'email_verified_at' => null, - ]); - } -} diff --git a/packages/category/workbench/database/migrations/.gitkeep b/packages/category/workbench/database/migrations/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/category/workbench/database/seeders/DatabaseSeeder.php b/packages/category/workbench/database/seeders/DatabaseSeeder.php deleted file mode 100644 index ce9bd1597..000000000 --- a/packages/category/workbench/database/seeders/DatabaseSeeder.php +++ /dev/null @@ -1,23 +0,0 @@ -create(); - - UserFactory::new()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', - ]); - } -} diff --git a/packages/category/workbench/resources/views/.gitkeep b/packages/category/workbench/resources/views/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/category/workbench/routes/web.php b/packages/category/workbench/routes/web.php deleted file mode 100644 index 86a06c53e..000000000 --- a/packages/category/workbench/routes/web.php +++ /dev/null @@ -1,7 +0,0 @@ - 'Identifiant du commentaire', 'comment_post_ID' => 'Comment Post ID', 'comment_author' => 'Comment Author', - 'comment_author_email' => 'Courriel de l\'auteur du commentaire', - 'comment_author_url' => 'URL de l\'auteur du commentaire', - 'comment_author_IP' => 'IP de l\'auteur du commentaire', + 'comment_author_email' => "Courriel de l'auteur du commentaire", + 'comment_author_url' => "URL de l'auteur du commentaire", + 'comment_author_IP' => "IP de l'auteur du commentaire", 'comment_date' => 'Date du commentaire', 'comment_date_gmt' => 'Date GMT du commentaire', 'comment_content' => 'Comment Content', diff --git a/packages/core/resources/lang/fr/core.php b/packages/core/resources/lang/fr/core.php index 5d0e088e1..2f79be601 100644 --- a/packages/core/resources/lang/fr/core.php +++ b/packages/core/resources/lang/fr/core.php @@ -29,7 +29,7 @@ 'data' => 'Données', 'interval' => 'Intervalle', 'has_errors' => 'A des erreurs', - 'error_message' => 'Message d\'erreur', + 'error_message' => "Message d'erreur", 'domain' => 'Domaine', 'ip_address' => 'Address IP', 'thumbnail' => 'Miniature', diff --git a/packages/core/resources/lang/fr/user.php b/packages/core/resources/lang/fr/user.php index a133322b2..ab051c20a 100644 --- a/packages/core/resources/lang/fr/user.php +++ b/packages/core/resources/lang/fr/user.php @@ -6,9 +6,9 @@ 'user_agent' => 'Agent utilisateur', 'user_id' => 'Identifiant utilisateur', 'user_type' => 'Modèle utilisateur', - 'username' => 'Nom d\'utilisateur', + 'username' => "Nom d'utilisateur", 'profile_photo_path' => 'Chemin photo de profil', - 'avatar_url' => 'URL de l\'avatar', + 'avatar_url' => "URL de l'avatar", 'password' => 'Mot de passe', 'language_id' => 'Identifiant de la langue', 'user_updated' => 'Utilisateur mis à jour', @@ -18,14 +18,14 @@ 'new_password' => 'Nouveau mot de passe', 'new_password_confirmation' => 'Confirmation du nouveau mot de passe', 'user_login' => 'Identifiant de connexion utilisateur', - 'user_nicename' => 'Pseudo de l\'utilisateur', - 'user_email' => 'Courriel de l\'utilisateur', - 'user_url' => 'URL de l\'utilisateur', + 'user_nicename' => "Pseudo de l'utilisateur", + 'user_email' => "Courriel de l'utilisateur", + 'user_url' => "URL de l'utilisateur", 'user_registered' => 'Utilisateur enregistré', 'user_activation_key' => 'Clé d\'activation de l\'utilisateur', - 'user_status' => 'Statut de l\'utilisateur', - 'user_pass' => 'Mot de passe de l\'utilisateur', - 'display_name' => 'Nom d\'affichage', + 'user_status' => "Statut de l'utilisateur", + 'user_pass' => "Mot de passe de l'utilisateur", + 'display_name' => "Nom d'affichage", 'roles' => 'Rôles', 'gender' => 'Genre', 'first_name' => 'Prénom', diff --git a/packages/core/routes/api.php b/packages/core/routes/api.php index 9e001466f..00a8d4265 100644 --- a/packages/core/routes/api.php +++ b/packages/core/routes/api.php @@ -1,9 +1,11 @@ providerPath)) { - if (! confirm('Filament is not installed properly. Do you want to proceed anyway?', false)) { - info('Installation cancelled.'); + if (! File::exists($this->providerPath) && ! confirm('Filament is not installed properly. Do you want to proceed anyway?', false)) { + info('Installation cancelled.'); - return; // cancel installation - } + return; + // cancel installation } } diff --git a/packages/core/src/CoreServiceProvider.php b/packages/core/src/CoreServiceProvider.php index 63c20ea6d..3eff141a1 100644 --- a/packages/core/src/CoreServiceProvider.php +++ b/packages/core/src/CoreServiceProvider.php @@ -8,14 +8,18 @@ use Moox\Core\Commands\InstallCommand; use Moox\Core\Traits\GoogleIcons; use Moox\Core\Traits\TranslatableConfig; +use Moox\Permission\Policies\DefaultPolicy; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; class CoreServiceProvider extends PackageServiceProvider { - use GoogleIcons, TranslatableConfig; + use GoogleIcons; + use TranslatableConfig; - public function boot() + #[Override] + public function boot(): void { parent::boot(); @@ -25,7 +29,7 @@ public function boot() $this->loadTranslationsFrom(lang_path('previews'), 'previews'); - $this->app->booted(function () { + $this->app->booted(function (): void { $this->translateConfigurations(); }); } @@ -61,11 +65,12 @@ protected function translateConfigurations() if ($key === 'app') { continue; } + config([$key => $value]); } } - public function setPolicies() + public function setPolicies(): void { $packages = $this->getPackageNames(); @@ -73,7 +78,7 @@ public function setPolicies() if (isset($package['models']) && is_array($package['models'])) { foreach ($package['models'] as $model => $settings) { if (isset($settings['policy']) && class_exists($settings['policy'])) { - $modelClass = "App\\Models\\$model"; + $modelClass = 'App\Models\\'.$model; if (class_exists($modelClass)) { Gate::policy($modelClass, $settings['policy']); } @@ -82,8 +87,6 @@ public function setPolicies() } } - Gate::guessPolicyNamesUsing(function ($modelClass) { - return \Moox\Permission\Policies\DefaultPolicy::class; - }); + Gate::guessPolicyNamesUsing(fn ($modelClass): string => DefaultPolicy::class); } } diff --git a/packages/core/src/Forms/Components/TitleWithSlugInput.php b/packages/core/src/Forms/Components/TitleWithSlugInput.php index 392273dea..40a922d84 100644 --- a/packages/core/src/Forms/Components/TitleWithSlugInput.php +++ b/packages/core/src/Forms/Components/TitleWithSlugInput.php @@ -8,8 +8,6 @@ class TitleWithSlugInput { - protected string $name; - protected ?string $titleLabel = null; protected ?string $slugLabel = null; @@ -18,10 +16,7 @@ class TitleWithSlugInput protected ?string $slugPrefix = null; - public function __construct(string $name) - { - $this->name = $name; - } + public function __construct(protected string $name) {} public static function make(string $name): self { @@ -63,7 +58,7 @@ public function components(): array ->label($this->titleLabel ?? __('core::core.title')) ->required() ->live(onBlur: true) - ->afterStateUpdated(function ($state, $set) { + ->afterStateUpdated(function ($state, $set): void { if (! $state || $this->evaluateShowSlugInput()) { $set('slug', Str::slug($state)); } @@ -76,7 +71,7 @@ public function components(): array ->rules(['max:255']) ->afterStateUpdated(fn ($state, $set) => $set('slug', Str::slug($state))) ->prefix($this->slugPrefix) - ->hidden(fn () => ! $this->evaluateShowSlugInput()), + ->hidden(fn (): bool => ! $this->evaluateShowSlugInput()), ]; } diff --git a/packages/core/src/Http/SharedHosting/Scheduler.php b/packages/core/src/Http/SharedHosting/Scheduler.php index ce97f831e..ea9dcf593 100644 --- a/packages/core/src/Http/SharedHosting/Scheduler.php +++ b/packages/core/src/Http/SharedHosting/Scheduler.php @@ -7,7 +7,7 @@ class Scheduler extends Controller { - public function __invoke() + public function __invoke(): string { $sharedHostingToken = config('core.shared_hosting.token'); diff --git a/packages/core/src/Services/TaxonomyService.php b/packages/core/src/Services/TaxonomyService.php index 3378586fc..ac28fc2f0 100644 --- a/packages/core/src/Services/TaxonomyService.php +++ b/packages/core/src/Services/TaxonomyService.php @@ -3,6 +3,8 @@ namespace Moox\Core\Services; use Illuminate\Support\Facades\Config; +use InvalidArgumentException; +use RuntimeException; class TaxonomyService { @@ -21,7 +23,7 @@ public function getCurrentResource(): ?string private function ensureResourceIsSet(): void { if ($this->currentResource === null) { - throw new \RuntimeException('Current resource is not set. Call setCurrentResource() first.'); + throw new RuntimeException('Current resource is not set. Call setCurrentResource() first.'); } } @@ -29,8 +31,8 @@ public function getTaxonomies(): array { $this->ensureResourceIsSet(); - return Config::get("previews.{$this->currentResource}.taxonomies", []) - ?: Config::get("builder.resources.{$this->currentResource}.taxonomies", []); + return Config::get(sprintf('previews.%s.taxonomies', $this->currentResource), []) + ?: Config::get(sprintf('builder.resources.%s.taxonomies', $this->currentResource), []); } public function getTaxonomyModel(string $taxonomy): ?string @@ -43,7 +45,7 @@ public function validateTaxonomy(string $taxonomy): void $modelClass = $this->getTaxonomyModel($taxonomy); if (! $modelClass || ! class_exists($modelClass)) { - throw new \InvalidArgumentException("Invalid model class for taxonomy: $taxonomy in resource: {$this->currentResource}"); + throw new InvalidArgumentException(sprintf('Invalid model class for taxonomy: %s in resource: %s', $taxonomy, $this->currentResource)); } } @@ -71,6 +73,6 @@ public function hasTaxonomies(): bool { $this->ensureResourceIsSet(); - return ! empty($this->getTaxonomies()); + return $this->getTaxonomies() !== []; } } diff --git a/packages/core/src/Traits/Base/BaseInResource.php b/packages/core/src/Traits/Base/BaseInResource.php index 71d8141f0..eacb7b804 100644 --- a/packages/core/src/Traits/Base/BaseInResource.php +++ b/packages/core/src/Traits/Base/BaseInResource.php @@ -39,16 +39,12 @@ public static function getEloquentQuery(): Builder $query = static::applySoftDeleteQuery($query); } - if ($currentTab = request()->query('tab')) { - if (method_exists(static::class, 'applyTabQuery')) { - $query = static::applyTabQuery($query, $currentTab); - } + if (($currentTab = request()->query('tab')) && method_exists(static::class, 'applyTabQuery')) { + $query = static::applyTabQuery($query, $currentTab); } - $methods = array_filter(get_class_methods(static::class), function ($method) { - return str_ends_with($method, 'ModifyTableQuery') - && ! in_array($method, ['applySoftDeleteQuery', 'applyTabQuery']); - }); + $methods = array_filter(get_class_methods(static::class), fn ($method): bool => str_ends_with($method, 'ModifyTableQuery') + && ! in_array($method, ['applySoftDeleteQuery', 'applyTabQuery'])); foreach ($methods as $method) { $query = static::$method($query); @@ -73,16 +69,12 @@ public static function getTableQuery(): Builder $query = static::applySoftDeleteQuery($query); } - if ($currentTab = request()->query('tab')) { - if (method_exists(static::class, 'applyTabQuery')) { - $query = static::applyTabQuery($query, $currentTab); - } + if (($currentTab = request()->query('tab')) && method_exists(static::class, 'applyTabQuery')) { + $query = static::applyTabQuery($query, $currentTab); } - $methods = array_filter(get_class_methods(static::class), function ($method) { - return str_ends_with($method, 'ModifyTableQuery') - && ! in_array($method, ['applySoftDeleteQuery', 'applyTabQuery']); - }); + $methods = array_filter(get_class_methods(static::class), fn ($method): bool => str_ends_with($method, 'ModifyTableQuery') + && ! in_array($method, ['applySoftDeleteQuery', 'applyTabQuery'])); foreach ($methods as $method) { $query = static::$method($query); @@ -113,13 +105,13 @@ public static function getRestoreTableAction(): RestoreAction public static function getRestoreBulkAction(): RestoreBulkAction { return RestoreBulkAction::make() - ->visible(fn ($livewire) => isset($livewire->activeTab) && in_array($livewire->activeTab, ['trash', 'deleted'])); + ->visible(fn ($livewire): bool => isset($livewire->activeTab) && in_array($livewire->activeTab, ['trash', 'deleted'])); } public static function getDeleteBulkAction(): DeleteBulkAction { return DeleteBulkAction::make() - ->hidden(fn ($livewire) => isset($livewire->activeTab) && in_array($livewire->activeTab, ['trash', 'deleted'])); + ->hidden(fn ($livewire): bool => isset($livewire->activeTab) && in_array($livewire->activeTab, ['trash', 'deleted'])); } public static function getSaveAction(): Action @@ -129,10 +121,10 @@ public static function getSaveAction(): Action ->extraAttributes(attributes: ['class' => 'w-full']) ->keyBindings(['command+s', 'ctrl+s']) ->color('success') - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire instanceof CreateRecord ? $livewire->create() : $livewire->save(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateRecord || $livewire instanceof EditRecord); + ->visible(fn ($livewire): bool => $livewire instanceof CreateRecord || $livewire instanceof EditRecord); } public static function getSaveAndCreateAnotherAction(): Action @@ -142,11 +134,11 @@ public static function getSaveAndCreateAnotherAction(): Action ->color('secondary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire instanceof CreateRecord ? $livewire->create() : $livewire->save(); $livewire->redirect(static::getUrl('create')); }) - ->visible(fn ($livewire) => $livewire instanceof CreateRecord); + ->visible(fn ($livewire): bool => $livewire instanceof CreateRecord); } public static function getCancelAction(): Action @@ -158,7 +150,7 @@ public static function getCancelAction(): Action ->color('secondary') ->outlined() ->url(fn () => static::getUrl('index')) - ->visible(fn ($livewire) => $livewire instanceof CreateRecord); + ->visible(fn ($livewire): bool => $livewire instanceof CreateRecord); } public static function getDeleteAction(): Action @@ -168,12 +160,12 @@ public static function getDeleteAction(): Action ->color('danger') ->outlined() ->extraAttributes(attributes: ['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire->record->delete(); $livewire->redirect(static::getUrl('index')); }) ->keyBindings(['delete']) - ->visible(fn ($livewire) => $livewire instanceof EditRecord) + ->visible(fn ($livewire): bool => $livewire instanceof EditRecord) ->requiresConfirmation(); } @@ -185,7 +177,7 @@ public static function getEditAction(): Action ->extraAttributes(attributes: ['class' => 'w-full']) ->keyBindings(['command+e', 'ctrl+e']) ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) - ->visible(fn ($livewire) => $livewire instanceof ViewRecord); + ->visible(fn ($livewire): bool => $livewire instanceof ViewRecord); } public static function getRestoreAction(): Action @@ -196,6 +188,6 @@ public static function getRestoreAction(): Action ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed()); + ->visible(fn ($livewire, $record): bool => $record && $record->trashed()); } } diff --git a/packages/core/src/Traits/GoogleIcons.php b/packages/core/src/Traits/GoogleIcons.php index eb0dd41cd..c5b8bece3 100644 --- a/packages/core/src/Traits/GoogleIcons.php +++ b/packages/core/src/Traits/GoogleIcons.php @@ -6,7 +6,7 @@ trait GoogleIcons { - public function useGoogleIcons() + public function useGoogleIcons(): void { FilamentIcon::register([ 'panels::global-search.field' => 'gmdi-search-o', diff --git a/packages/core/src/Traits/LogLevel.php b/packages/core/src/Traits/LogLevel.php index 4a2915ab6..98e06a898 100644 --- a/packages/core/src/Traits/LogLevel.php +++ b/packages/core/src/Traits/LogLevel.php @@ -23,16 +23,9 @@ protected function log($level, $message, array $context = []) $logInProduction = Config::get('core.logging.log_in_production', false); if ( - ($verboseLevel > 0 && app()->environment() !== 'production') || - ($logInProduction && app()->environment() === 'production') + ($verboseLevel > 0 && app()->environment() !== 'production' || $logInProduction && app()->environment() === 'production') && ($level === 'debug' && $verboseLevel >= 1 || $level === 'info' && $verboseLevel >= 2 || $verboseLevel >= 3) ) { - if ( - ($level === 'debug' && $verboseLevel >= 1) || - ($level === 'info' && $verboseLevel >= 2) || - $verboseLevel >= 3 - ) { - Log::$level($message, $context); - } + Log::$level($message, $context); } } } diff --git a/packages/core/src/Traits/Publish/SinglePublishInListPage.php b/packages/core/src/Traits/Publish/SinglePublishInListPage.php index ae93ebb86..2537dbeb5 100644 --- a/packages/core/src/Traits/Publish/SinglePublishInListPage.php +++ b/packages/core/src/Traits/Publish/SinglePublishInListPage.php @@ -15,15 +15,13 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Item { - return $model::create($data); - }) - ->hidden(fn () => $this->activeTab === 'deleted'), + ->using(fn (array $data, string $model): Item => $model::create($data)) + ->hidden(fn (): bool => $this->activeTab === 'deleted'), Action::make('emptyTrash') ->label(__('core::core.empty_trash')) ->icon('heroicon-o-trash') ->color('danger') - ->action(function () { + ->action(function (): void { $trashedCount = Item::onlyTrashed()->count(); Item::onlyTrashed()->forceDelete(); Notification::make() @@ -33,7 +31,7 @@ protected function getHeaderActions(): array ->send(); }) ->requiresConfirmation() - ->visible(fn () => $this->activeTab === 'deleted' && Item::onlyTrashed()->exists()), + ->visible(fn (): bool => $this->activeTab === 'deleted' && Item::onlyTrashed()->exists()), ]; } } diff --git a/packages/core/src/Traits/Publish/SinglePublishInResource.php b/packages/core/src/Traits/Publish/SinglePublishInResource.php index 89b723db8..fcbf7bf98 100644 --- a/packages/core/src/Traits/Publish/SinglePublishInResource.php +++ b/packages/core/src/Traits/Publish/SinglePublishInResource.php @@ -64,7 +64,7 @@ public static function getTableFilters(): array 'published' => __('core::core.published'), ]) ->label(__('core::core.status')) - ->query(function (Builder $query, array $data) { + ->query(function (Builder $query, array $data): void { $status = $data['value']; if ($status) { static::applyStatusFilter($query, $status); @@ -97,15 +97,16 @@ public static function getPublishAction(): Action ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $data = $livewire->form->getState(); if (! $data['publish_at']) { $data['publish_at'] = now(); } + $livewire->form->fill($data); $livewire instanceof CreateFullItem ? $livewire->create() : $livewire->save(); }) - ->hidden(fn ($livewire, $record) => $record && $record->trashed()); + ->hidden(fn ($livewire, $record): bool => $record && $record->trashed()); } public static function getFormActions(): Actions diff --git a/packages/core/src/Traits/QueriesInConfig.php b/packages/core/src/Traits/QueriesInConfig.php index 3e6f093af..30f0a9874 100644 --- a/packages/core/src/Traits/QueriesInConfig.php +++ b/packages/core/src/Traits/QueriesInConfig.php @@ -2,6 +2,7 @@ namespace Moox\Core\Traits; +use Closure; use Illuminate\Database\Eloquent\SoftDeletes; trait QueriesInConfig @@ -11,7 +12,7 @@ protected function applyConditions($query, $conditions) foreach ($conditions as $condition) { $value = $condition['value']; - if ($value instanceof \Closure) { + if ($value instanceof Closure) { $value = $value(); } diff --git a/packages/core/src/Traits/RequestInModel.php b/packages/core/src/Traits/RequestInModel.php index 57cdf5ce4..767098bf3 100644 --- a/packages/core/src/Traits/RequestInModel.php +++ b/packages/core/src/Traits/RequestInModel.php @@ -7,7 +7,7 @@ trait RequestInModel { - public function getRequestData($key) + public function getRequestData(string $key) { $components = Request::input('components', []); @@ -19,6 +19,6 @@ public function getRequestData($key) $firstComponent = $components[0] ?? []; - return $firstComponent['updates']["data.$key"] ?? null; + return $firstComponent['updates']['data.'.$key] ?? null; } } diff --git a/packages/core/src/Traits/Simple/SingleSimpleInResource.php b/packages/core/src/Traits/Simple/SingleSimpleInResource.php index 45308e666..0aff54ffa 100644 --- a/packages/core/src/Traits/Simple/SingleSimpleInResource.php +++ b/packages/core/src/Traits/Simple/SingleSimpleInResource.php @@ -26,7 +26,10 @@ public static function enableDelete(): bool return true; } - public static function getTableActions() + /** + * @return mixed[] + */ + public static function getTableActions(): array { $actions = []; @@ -41,7 +44,10 @@ public static function getTableActions() return $actions; } - public static function getBulkActions() + /** + * @return mixed[] + */ + public static function getBulkActions(): array { $actions = []; diff --git a/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInListPage.php b/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInListPage.php index 12be0e410..0c276d5a9 100644 --- a/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInListPage.php +++ b/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInListPage.php @@ -40,7 +40,7 @@ protected function getHeaderActions(): array ->requiresConfirmation() ->modalHeading(__('core::core.empty_trash_confirmation')) ->modalDescription(__('core::core.empty_trash_description')) - ->disabled(function () { + ->disabled(function (): bool { $model = $this->getModel(); if (! in_array(SoftDeletes::class, class_uses_recursive($model))) { @@ -58,7 +58,7 @@ protected function getHeaderActions(): array ->whereNotNull($deletedAtColumn) ->count() === 0; }) - ->action(function () { + ->action(function (): void { $model = $this->getModel(); if (! in_array(SoftDeletes::class, class_uses_recursive($model))) { diff --git a/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInResource.php b/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInResource.php index 9596a7884..ba6d2e6df 100644 --- a/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInResource.php +++ b/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInResource.php @@ -11,6 +11,7 @@ use Filament\Tables\Actions\ViewAction; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletingScope; @@ -56,7 +57,7 @@ public static function getSoftDeleteEditTableAction(): EditAction return EditAction::make('edit') ->color('primary') ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) - ->visible(fn ($livewire, $record) => $record instanceof \Illuminate\Database\Eloquent\Model && method_exists($record, 'trashed') && ! $record->trashed()); + ->visible(fn ($livewire, $record): bool => $record instanceof Model && method_exists($record, 'trashed') && ! $record->trashed()); } public static function getSoftDeleteViewTableAction(): ViewAction @@ -64,7 +65,7 @@ public static function getSoftDeleteViewTableAction(): ViewAction return ViewAction::make('view') ->color('secondary') ->url(fn ($record) => static::getUrl('view', ['record' => $record])) - ->visible(fn ($livewire, $record) => $record instanceof \Illuminate\Database\Eloquent\Model && method_exists($record, 'trashed') && ! $record->trashed()); + ->visible(fn ($livewire, $record): bool => $record instanceof Model && method_exists($record, 'trashed') && ! $record->trashed()); } public static function getHardDeleteTableAction(): Action @@ -76,10 +77,10 @@ public static function getHardDeleteTableAction(): Action ->requiresConfirmation() ->modalHeading(__('core::core.hard_delete_confirmation')) ->modalDescription(__('core::core.hard_delete_description')) - ->action(function ($record) { + ->action(function ($record): void { $record->forceDelete(); }) - ->visible(fn ($livewire, $record) => $record instanceof \Illuminate\Database\Eloquent\Model && method_exists($record, 'trashed') && $record->trashed()); + ->visible(fn ($livewire, $record): bool => $record instanceof Model && method_exists($record, 'trashed') && $record->trashed()); } public static function getTableActions(): array @@ -113,14 +114,14 @@ public static function getHardDeleteBulkAction(): BulkAction ->icon('heroicon-m-trash') ->modalHeading(__('core::core.hard_delete_bulk_confirmation')) ->modalDescription(__('core::core.hard_delete_bulk_description')) - ->action(function (Collection $records, $livewire) { + ->action(function (Collection $records, $livewire): void { $records->each->forceDelete(); $livewire->resetTable(); }) ->deselectRecordsAfterCompletion() ->visible( - fn ($livewire) => isset($livewire->activeTab) + fn ($livewire): bool => isset($livewire->activeTab) && in_array($livewire->activeTab, ['trash', 'deleted'])) ->requiresConfirmation(); } @@ -153,7 +154,7 @@ public static function getSoftDeleteEditAction(): FormAction ->keyBindings(['command+e', 'ctrl+e']) ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) ->visible( - fn ($livewire, $record) => $livewire instanceof ViewRecord + fn ($livewire, $record): bool => $livewire instanceof ViewRecord && method_exists($record, 'trashed') && ! $record->trashed()); } diff --git a/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInViewPage.php b/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInViewPage.php index 9d959cd74..230fab2bd 100644 --- a/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInViewPage.php +++ b/packages/core/src/Traits/SoftDelete/SingleSoftDeleteInViewPage.php @@ -4,6 +4,7 @@ namespace Moox\Core\Traits\SoftDelete; +use Exception; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletingScope; @@ -14,11 +15,7 @@ public function mount(Model|int|string $record): void { $model = static::getModel(); - if ($record instanceof Model) { - $recordId = $record->getKey(); - } else { - $recordId = $record; - } + $recordId = $record instanceof Model ? $record->getKey() : $record; $query = $model::query(); @@ -29,7 +26,7 @@ public function mount(Model|int|string $record): void $foundRecord = $query->find($recordId); if (! $foundRecord) { - throw new \Exception("Record with ID {$recordId} not found."); + throw new Exception(sprintf('Record with ID %s not found.', $recordId)); } parent::mount($recordId); diff --git a/packages/core/src/Traits/Tabs/TabsInListPage.php b/packages/core/src/Traits/Tabs/TabsInListPage.php index d2e9f18bc..18f655dd0 100644 --- a/packages/core/src/Traits/Tabs/TabsInListPage.php +++ b/packages/core/src/Traits/Tabs/TabsInListPage.php @@ -49,9 +49,7 @@ public function getDynamicTabs(string $configKey, string $modelClass): array $tab->modifyQueryUsing(fn ($query) => $query) ->badge($modelClass::query()->count()); } else { - $tab->modifyQueryUsing(function ($query) use ($queryConditions) { - return $this->applyConditions($query, $queryConditions); - }); + $tab->modifyQueryUsing(fn ($query) => $this->applyConditions($query, $queryConditions)); $badgeCountQuery = $modelClass::query(); $badgeCountQuery = $this->applyConditions($badgeCountQuery, $queryConditions); diff --git a/packages/core/src/Traits/Taxonomy/TaxonomyInModel.php b/packages/core/src/Traits/Taxonomy/TaxonomyInModel.php index d49ab0561..7fd625797 100644 --- a/packages/core/src/Traits/Taxonomy/TaxonomyInModel.php +++ b/packages/core/src/Traits/Taxonomy/TaxonomyInModel.php @@ -31,7 +31,7 @@ public function taxonomy(string $taxonomy): MorphToMany $taxonomies = $this->getTaxonomyService()->getTaxonomies(); if (! isset($taxonomies[$taxonomy])) { - Log::error("Taxonomy not found: $taxonomy"); + Log::error('Taxonomy not found: '.$taxonomy); return $this->emptyMorphToMany(); } diff --git a/packages/core/src/Traits/Taxonomy/TaxonomyInPages.php b/packages/core/src/Traits/Taxonomy/TaxonomyInPages.php index 718871cd3..87fec292d 100644 --- a/packages/core/src/Traits/Taxonomy/TaxonomyInPages.php +++ b/packages/core/src/Traits/Taxonomy/TaxonomyInPages.php @@ -42,9 +42,7 @@ protected function handleTaxonomies(): void foreach ($this->getTaxonomies() as $taxonomy => $settings) { if (isset($data[$taxonomy])) { - $tagIds = collect($data[$taxonomy])->map(function ($item) { - return is_array($item) ? $item['id'] : $item; - })->toArray(); + $tagIds = collect($data[$taxonomy])->map(fn ($item): mixed => is_array($item) ? $item['id'] : $item)->toArray(); $record->$taxonomy()->sync($tagIds); } } @@ -69,9 +67,9 @@ protected function mutateFormDataBeforeFill(array $data): array $modelTable = $model->getTable(); $tags = DB::table($table) - ->join($modelTable, "{$table}.{$relatedKey}", '=', "{$modelTable}.id") - ->where("{$table}.{$foreignKey}", $this->record->getKey()) - ->pluck("{$modelTable}.id") + ->join($modelTable, sprintf('%s.%s', $table, $relatedKey), '=', $modelTable.'.id') + ->where(sprintf('%s.%s', $table, $foreignKey), $this->record->getKey()) + ->pluck($modelTable.'.id') ->toArray(); $data[$taxonomy] = $tags; @@ -139,7 +137,7 @@ public function getFormSelectOptionLabels(string $statePath): array if ($label === null) { $taxonomies = $this->getTaxonomies(); foreach ($taxonomies as $taxonomy => $settings) { - if ($statePath === "data.{$taxonomy}") { + if ($statePath === 'data.'.$taxonomy) { $modelClass = $this->getTaxonomyModel($taxonomy); $model = app($modelClass)::find($value); if ($model) { diff --git a/packages/core/src/Traits/Taxonomy/TaxonomyInResource.php b/packages/core/src/Traits/Taxonomy/TaxonomyInResource.php index 4f82d9cc3..6f9f1ec28 100644 --- a/packages/core/src/Traits/Taxonomy/TaxonomyInResource.php +++ b/packages/core/src/Traits/Taxonomy/TaxonomyInResource.php @@ -32,7 +32,7 @@ public static function getTaxonomyFields(): array $taxonomyService = static::getTaxonomyService(); return collect($taxonomyService->getTaxonomies()) - ->map(fn ($settings, $taxonomy) => static::createTaxonomyField($taxonomy, $settings, $taxonomyService)) + ->map(fn ($settings, $taxonomy): Select|SelectTree => static::createTaxonomyField($taxonomy, $settings, $taxonomyService)) ->toArray(); } @@ -81,7 +81,7 @@ protected static function createTaxonomyField(string $taxonomy, array $settings, ->multiple() ->options(fn () => app($modelClass)::pluck('title', 'id')->toArray()) ->getSearchResultsUsing( - fn (string $search) => app($modelClass)::where('title', 'like', "%{$search}%") + fn (string $search) => app($modelClass)::where('title', 'like', sprintf('%%%s%%', $search)) ->limit(50) ->pluck('title', 'id') ->toArray() @@ -99,7 +99,7 @@ public static function getTaxonomyFilters(): array $resourceModel = static::getModel(); $resourceTable = app($resourceModel)->getTable(); - return collect($taxonomies)->map(function ($settings, $taxonomy) use ($taxonomyService, $resourceTable) { + return collect($taxonomies)->map(function ($settings, $taxonomy) use ($taxonomyService, $resourceTable): SelectFilter { $taxonomyModel = $taxonomyService->getTaxonomyModel($taxonomy); $pivotTable = $taxonomyService->getTaxonomyTable($taxonomy); $foreignKey = $taxonomyService->getTaxonomyForeignKey($taxonomy); @@ -110,14 +110,14 @@ public static function getTaxonomyFilters(): array ->label($settings['label'] ?? ucfirst($taxonomy)) ->multiple() ->options(fn () => $taxonomyModel::pluck('title', 'id')->toArray()) - ->query(function (Builder $query, array $data) use ($pivotTable, $foreignKey, $relatedKey, $resourceTable) { + ->query(function (Builder $query, array $data) use ($pivotTable, $foreignKey, $relatedKey, $resourceTable): void { $selectedIds = $data['values'] ?? []; if (! empty($selectedIds)) { - $query->whereExists(function ($subQuery) use ($pivotTable, $foreignKey, $relatedKey, $resourceTable, $selectedIds) { + $query->whereExists(function ($subQuery) use ($pivotTable, $foreignKey, $relatedKey, $resourceTable, $selectedIds): void { $subQuery->select(DB::raw(1)) ->from($pivotTable) - ->whereColumn("{$pivotTable}.{$foreignKey}", "{$resourceTable}.id") - ->whereIn("{$pivotTable}.{$relatedKey}", $selectedIds); + ->whereColumn(sprintf('%s.%s', $pivotTable, $foreignKey), $resourceTable.'.id') + ->whereIn(sprintf('%s.%s', $pivotTable, $relatedKey), $selectedIds); }); } }); @@ -129,37 +129,33 @@ protected static function getTaxonomyColumns(): array $taxonomyService = static::getTaxonomyService(); $taxonomies = $taxonomyService->getTaxonomies(); - return collect($taxonomies)->map(function ($settings, $taxonomy) use ($taxonomyService) { - return TagsColumn::make($taxonomy) - ->label($settings['label'] ?? ucfirst($taxonomy)) - ->getStateUsing(function ($record) use ($taxonomy, $taxonomyService, $settings) { - $relationshipName = $settings['relationship'] ?? $taxonomy; - $table = $taxonomyService->getTaxonomyTable($taxonomy); - $foreignKey = $taxonomyService->getTaxonomyForeignKey($taxonomy); - $relatedKey = $taxonomyService->getTaxonomyRelatedKey($taxonomy); - $modelClass = $taxonomyService->getTaxonomyModel($taxonomy); - - $model = app($modelClass); - $modelTable = $model->getTable(); - - $tags = DB::table($table) - ->join($modelTable, "{$table}.{$relatedKey}", '=', "{$modelTable}.id") - ->where("{$table}.{$foreignKey}", $record->id) - ->pluck("{$modelTable}.title") - ->toArray(); - - return $tags; - }) - ->toggleable(isToggledHiddenByDefault: true) - ->separator(',') - ->searchable(); - })->toArray(); + return collect($taxonomies)->map(fn ($settings, $taxonomy): TagsColumn => TagsColumn::make($taxonomy) + ->label($settings['label'] ?? ucfirst((string) $taxonomy)) + ->getStateUsing(function ($record) use ($taxonomy, $taxonomyService, $settings) { + $relationshipName = $settings['relationship'] ?? $taxonomy; + $table = $taxonomyService->getTaxonomyTable($taxonomy); + $foreignKey = $taxonomyService->getTaxonomyForeignKey($taxonomy); + $relatedKey = $taxonomyService->getTaxonomyRelatedKey($taxonomy); + $modelClass = $taxonomyService->getTaxonomyModel($taxonomy); + + $model = app($modelClass); + $modelTable = $model->getTable(); + + return DB::table($table) + ->join($modelTable, sprintf('%s.%s', $table, $relatedKey), '=', $modelTable.'.id') + ->where(sprintf('%s.%s', $table, $foreignKey), $record->id) + ->pluck($modelTable.'.title') + ->toArray(); + }) + ->toggleable(isToggledHiddenByDefault: true) + ->separator(',') + ->searchable())->toArray(); } protected static function handleTaxonomies(Model $record, array $data): void { $taxonomyService = static::getTaxonomyService(); - foreach ($taxonomyService->getTaxonomies() as $taxonomy => $settings) { + foreach (array_keys($taxonomyService->getTaxonomies()) as $taxonomy) { if (isset($data[$taxonomy])) { $record->$taxonomy()->sync($data[$taxonomy]); } @@ -171,7 +167,7 @@ protected static function addTaxonomyRelationsToQuery(Builder $query): Builder $taxonomyService = static::getTaxonomyService(); $taxonomies = $taxonomyService->getTaxonomies(); - foreach ($taxonomies as $taxonomy => $settings) { + foreach (array_keys($taxonomies) as $taxonomy) { $relationshipName = $taxonomyService->getTaxonomyRelationship($taxonomy); if (method_exists($query->getModel(), $relationshipName)) { diff --git a/packages/core/src/Traits/TranslatableConfig.php b/packages/core/src/Traits/TranslatableConfig.php index 7e87ecd6a..9d51bc4c4 100644 --- a/packages/core/src/Traits/TranslatableConfig.php +++ b/packages/core/src/Traits/TranslatableConfig.php @@ -9,7 +9,7 @@ trait TranslatableConfig */ protected function translateConfig(array $config): array { - foreach ($config as $key => &$value) { + foreach ($config as &$value) { if (is_array($value)) { $value = $this->translateConfig($value); diff --git a/packages/core/src/Traits/UserRelation/UserInResource.php b/packages/core/src/Traits/UserRelation/UserInResource.php index c5b1702e3..c9a69673c 100644 --- a/packages/core/src/Traits/UserRelation/UserInResource.php +++ b/packages/core/src/Traits/UserRelation/UserInResource.php @@ -37,11 +37,11 @@ public static function getUserFormField(): Select { return Select::make('user_id') ->label(__('core::core.user')) - ->options(fn () => static::getUserOptions()) + ->options(fn (): array => static::getUserOptions()) ->default(fn () => auth()->id()) ->required() ->searchable() - ->visible(fn () => static::shouldShowUserField()); + ->visible(fn (): bool => static::shouldShowUserField()); } public static function getUserTableColumn(): ImageColumn @@ -51,7 +51,7 @@ public static function getUserTableColumn(): ImageColumn ->tooltip(fn ($record) => $record->user?->name) ->alignment('center') ->circular() - ->visible(fn () => static::shouldShowUserField()) + ->visible(fn (): bool => static::shouldShowUserField()) ->toggleable(); } @@ -60,7 +60,7 @@ public static function getUserFilters(): array return [ SelectFilter::make('user_id') ->label(__('core::core.user')) - ->options(fn () => static::getUserOptions()) + ->options(fn (): array => static::getUserOptions()) ->searchable(), ]; } diff --git a/packages/core/tests/Feature/ExampleTest.php b/packages/core/tests/Feature/ExampleTest.php index 5181054d6..52598ac0e 100644 --- a/packages/core/tests/Feature/ExampleTest.php +++ b/packages/core/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/core/tests/Pest.php b/packages/core/tests/Pest.php index f7d68e1ba..5da5ff12f 100644 --- a/packages/core/tests/Pest.php +++ b/packages/core/tests/Pest.php @@ -35,7 +35,7 @@ | */ -function something() +function something(): void { // .. } diff --git a/packages/core/tests/Unit/ExampleTest.php b/packages/core/tests/Unit/ExampleTest.php index c13139f61..59712f5b5 100644 --- a/packages/core/tests/Unit/ExampleTest.php +++ b/packages/core/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/data-languages/src/Commands/InstallCommand.php b/packages/data-languages/src/Commands/InstallCommand.php index a555bded4..5a14ac49d 100644 --- a/packages/data-languages/src/Commands/InstallCommand.php +++ b/packages/data-languages/src/Commands/InstallCommand.php @@ -34,7 +34,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -80,6 +80,7 @@ public function publishConfiguration(): void return; } + warning('The DataLanguages config already exist. The config will not be published.'); } } @@ -92,6 +93,7 @@ public function publishMigrations(): void return; } + info('Publishing DataLanguages Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'data-languages-migrations']); } @@ -128,22 +130,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -184,12 +186,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/data-languages/tests/ArchTest.php b/packages/data-languages/tests/ArchTest.php index 5b91a2933..4fe44493f 100644 --- a/packages/data-languages/tests/ArchTest.php +++ b/packages/data-languages/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\DataLanguages') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\DataLanguages\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\DataLanguages'); arch()->preset()->php(); diff --git a/packages/data-languages/tests/Feature/ExampleTest.php b/packages/data-languages/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/data-languages/tests/Feature/ExampleTest.php +++ b/packages/data-languages/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/data-languages/tests/Pest.php b/packages/data-languages/tests/Pest.php index e88faf717..01eb97879 100644 --- a/packages/data-languages/tests/Pest.php +++ b/packages/data-languages/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/data-languages/tests/TestCase.php b/packages/data-languages/tests/TestCase.php index caa340663..46699adfc 100644 --- a/packages/data-languages/tests/TestCase.php +++ b/packages/data-languages/tests/TestCase.php @@ -13,7 +13,7 @@ protected function setUp(): void parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'VendorName\\DataLanguages\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn (string $modelName): string => 'VendorName\\DataLanguages\\Database\\Factories\\'.class_basename($modelName).'Factory' ); } @@ -24,7 +24,7 @@ protected function getPackageProviders($app) ]; } - public function getEnvironmentSetUp($app) + public function getEnvironmentSetUp($app): void { config()->set('database.default', 'testing'); diff --git a/packages/data-languages/tests/Unit/ExampleTest.php b/packages/data-languages/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/data-languages/tests/Unit/ExampleTest.php +++ b/packages/data-languages/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/expiry/config/expiry.php b/packages/expiry/config/expiry.php index fe9a721a3..01c8795de 100644 --- a/packages/expiry/config/expiry.php +++ b/packages/expiry/config/expiry.php @@ -1,5 +1,9 @@ 'Documents', ], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'articles' => [ 'label' => 'trans//core::core.articles', @@ -82,9 +83,7 @@ 'value' => 'Articles', ], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'tasks' => [ 'label' => 'trans//core::core.tasks', @@ -96,9 +95,7 @@ 'value' => 'Tasks', ], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'no-user' => [ 'label' => 'trans//core::expiry.no_assignee', @@ -110,9 +107,7 @@ 'value' => 'No assignee', ], ], - 'visible' => in_array(rtrim(env('APP_URL'), '/'), [ - config('app.url'), - ]), + 'visible' => rtrim((string) env('APP_URL'), '/') == config('app.url'), ], 'no-date' => [ 'label' => 'trans//core::expiry.no_expiry_date', @@ -186,7 +181,7 @@ | */ - 'user_model' => \Moox\Press\Models\WpUser::class, + 'user_model' => WpUser::class, 'default_notified_to' => 1, /* @@ -251,7 +246,7 @@ */ 'collect_expiries_jobs' => [ - Moox\Expiry\Jobs\CollectExpiries::class, + CollectExpiries::class, // Add more jobs here if needed. ], @@ -266,7 +261,7 @@ | */ - 'expiry_action' => Moox\Expiry\Actions\CustomExpiryAction::class, + 'expiry_action' => CustomExpiryAction::class, 'expiry_action_enable' => false, 'expiry_action_name' => 'Custom Expiry Action', 'expiry_view_action_color' => 'primary', diff --git a/packages/expiry/routes/api.php b/packages/expiry/routes/api.php index ad0d6f6e1..fd0d6ea36 100644 --- a/packages/expiry/routes/api.php +++ b/packages/expiry/routes/api.php @@ -4,7 +4,7 @@ use Moox\Expiry\Http\Controllers\Api\ExpiryController; if (config('expiry.api')) { - Route::prefix('/api/expiries')->group(function () { + Route::prefix('/api/expiries')->group(function (): void { Route::get('count', [ExpiryController::class, 'count']); Route::get('count/user/{user}', [ExpiryController::class, 'countForUser']); Route::apiResource('/', ExpiryController::class); diff --git a/packages/expiry/src/Actions/CustomExpiryAction.php b/packages/expiry/src/Actions/CustomExpiryAction.php index ff5957235..31190587c 100644 --- a/packages/expiry/src/Actions/CustomExpiryAction.php +++ b/packages/expiry/src/Actions/CustomExpiryAction.php @@ -9,6 +9,7 @@ use Filament\Notifications\Notification; use Filament\Tables\Actions\Action; use Illuminate\Support\Facades\DB; +use Override; class CustomExpiryAction extends Action { @@ -17,13 +18,14 @@ public static function getDefaultName(): ?string return 'setDateAction'; } + #[Override] protected function setUp(): void { parent::setUp(); $this->label(config('expiry.expiry_action_name', 'Set Expiry Date')) ->icon('gmdi-event-available') - ->action(function ($record, array $data) { + ->action(function ($record, array $data): void { $postId = $record->item_id; if ($postId) { @@ -39,10 +41,8 @@ protected function setUp(): void ->send(); } }) - ->form(function ($record) { - $cycleOptions = collect(config('expiry.cycle_options'))->mapWithKeys(function ($value, $key) { - return [__('core::expiry.'.$key) => $value]; - }); + ->form(function ($record): array { + $cycleOptions = collect(config('expiry.cycle_options'))->mapWithKeys(fn ($value, $key) => [__('core::expiry.'.$key) => $value]); return [ Grid::make(2) @@ -89,8 +89,6 @@ protected function setUp(): void ->modalHeading(__('core::expiry.set_date')) ->modalSubmitActionLabel(__('core::expiry.save')) ->color('primary') - ->visible(function ($record) { - return config('expiry.expiry_action_enable', true); - }); + ->visible(fn ($record) => config('expiry.expiry_action_enable', true)); } } diff --git a/packages/expiry/src/Commands/EscalatedExpiriesCommand.php b/packages/expiry/src/Commands/EscalatedExpiriesCommand.php index acb81665e..d5bc9657e 100644 --- a/packages/expiry/src/Commands/EscalatedExpiriesCommand.php +++ b/packages/expiry/src/Commands/EscalatedExpiriesCommand.php @@ -11,7 +11,7 @@ class EscalatedExpiriesCommand extends Command protected $description = 'Dispatch the job to send notifications for escalated expiries'; - public function handle() + public function handle(): void { SendEscalatedExpiriesJob::dispatch(); $this->info('Escalated Expiries Notification Dispatched'); diff --git a/packages/expiry/src/Commands/InstallCommand.php b/packages/expiry/src/Commands/InstallCommand.php index 9a523e9f4..5eb5d2e27 100644 --- a/packages/expiry/src/Commands/InstallCommand.php +++ b/packages/expiry/src/Commands/InstallCommand.php @@ -34,7 +34,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -80,6 +80,7 @@ public function publishConfiguration(): void return; } + warning('The Expiry config already exist. The config will not be published.'); } } @@ -92,6 +93,7 @@ public function publishMigrations(): void return; } + info('Publishing Expirys Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'expiry-migrations']); } @@ -128,22 +130,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -184,12 +186,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/expiry/src/ExpiryServiceProvider.php b/packages/expiry/src/ExpiryServiceProvider.php index e847f41c1..ee88ddb81 100644 --- a/packages/expiry/src/ExpiryServiceProvider.php +++ b/packages/expiry/src/ExpiryServiceProvider.php @@ -6,6 +6,7 @@ use Moox\Expiry\Commands\EscalatedExpiriesCommand; use Moox\Expiry\Commands\InstallCommand; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -22,14 +23,15 @@ public function configurePackage(Package $package): void ->hasCommands(InstallCommand::class, EscalatedExpiriesCommand::class); } - public function boot() + #[Override] + public function boot(): void { parent::boot(); $this->loadViewsFrom(__DIR__.'/../resources/views', 'expiry'); } - public function packageRegistered() + public function packageRegistered(): void { $this->loadRoutesFrom(__DIR__.'/../routes/api.php'); } diff --git a/packages/expiry/src/Jobs/CollectExpiries.php b/packages/expiry/src/Jobs/CollectExpiries.php index 9482e1b95..7ffa1fbea 100644 --- a/packages/expiry/src/Jobs/CollectExpiries.php +++ b/packages/expiry/src/Jobs/CollectExpiries.php @@ -14,25 +14,33 @@ class CollectExpiries implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; - public $tries; + /** + * @var int + */ + public $tries = 3; - public $timeout; + /** + * @var int + */ + public $timeout = 300; - public $maxExceptions; + /** + * @var int + */ + public $maxExceptions = 1; - public $backoff; + /** + * @var int + */ + public $backoff = 350; - public function __construct() - { - $this->tries = 3; - $this->timeout = 300; - $this->maxExceptions = 1; - $this->backoff = 350; - } - - public function handle() + public function handle(): void { $this->setProgress(1); diff --git a/packages/expiry/src/Jobs/DemoExpiries.php b/packages/expiry/src/Jobs/DemoExpiries.php index a0ebe5695..405268a9f 100644 --- a/packages/expiry/src/Jobs/DemoExpiries.php +++ b/packages/expiry/src/Jobs/DemoExpiries.php @@ -13,25 +13,33 @@ class DemoExpiries implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 3; - $this->timeout = 300; - $this->maxExceptions = 1; - $this->backoff = 350; - } - - public function handle() + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 3; + + /** + * @var int + */ + public $timeout = 300; + + /** + * @var int + */ + public $maxExceptions = 1; + + /** + * @var int + */ + public $backoff = 350; + + public function handle(): void { $this->setProgress(1); diff --git a/packages/expiry/src/Jobs/SendEscalatedExpiriesJob.php b/packages/expiry/src/Jobs/SendEscalatedExpiriesJob.php index f033bec5b..3537fb682 100644 --- a/packages/expiry/src/Jobs/SendEscalatedExpiriesJob.php +++ b/packages/expiry/src/Jobs/SendEscalatedExpiriesJob.php @@ -14,9 +14,12 @@ class SendEscalatedExpiriesJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; - public function handle() + public function handle(): void { if (! config('expiry.send-escalation')) { return; @@ -26,7 +29,7 @@ public function handle() $panelPath = config('expiry.panel_path'); $escalatedExpiries = Expiry::query() - ->where(function ($query) { + ->where(function ($query): void { $query->whereNull('escalated_to') ->whereNotNull('escalated_at'); }) @@ -36,20 +39,18 @@ public function handle() return; } - $escalatedEntries = $escalatedExpiries->filter(fn ($entry) => $entry->escalated_at !== null); + $escalatedEntries = $escalatedExpiries->filter(fn ($entry): bool => $entry->escalated_at !== null); $data = [ - 'escalatedEntries' => $escalatedEntries->map(function ($entry) { - return [ - 'title' => $entry->title, - 'expired_at' => Carbon::parse($entry->expired_at)->diffForHumans(), - 'processing_deadline' => Carbon::parse($entry->processing_deadline)->diffForHumans(), - 'escalated_at' => Carbon::parse($entry->escalated_at)->format('d.m.Y'), - 'notified_to' => config('expiry.user_model')::where('ID', $entry->notified_to)->first()?->display_name, - 'user_email' => config('expiry.user_model')::where('ID', $entry->notified_to)->first()?->email, - 'category' => $entry->category, - ]; - }), + 'escalatedEntries' => $escalatedEntries->map(fn ($entry): array => [ + 'title' => $entry->title, + 'expired_at' => Carbon::parse($entry->expired_at)->diffForHumans(), + 'processing_deadline' => Carbon::parse($entry->processing_deadline)->diffForHumans(), + 'escalated_at' => Carbon::parse($entry->escalated_at)->format('d.m.Y'), + 'notified_to' => config('expiry.user_model')::where('ID', $entry->notified_to)->first()?->display_name, + 'user_email' => config('expiry.user_model')::where('ID', $entry->notified_to)->first()?->email, + 'category' => $entry->category, + ]), ]; $responsibleEmail = config('expiry.user_model')::where('ID', $escalatedExpiries->first()->notified_to)->first()?->email; @@ -58,7 +59,7 @@ public function handle() ->cc($adminEmail) ->send(new EscalatedExpiriesMail($data, $panelPath)); - $escalatedEntries->each(function ($entry) { + $escalatedEntries->each(function ($entry): void { $responsibleId = $entry->notified_to; $entry->escalated_to = $responsibleId; $entry->save(); diff --git a/packages/expiry/src/Mail/EscalatedExpiriesMail.php b/packages/expiry/src/Mail/EscalatedExpiriesMail.php index 7438a960e..9036aeb97 100644 --- a/packages/expiry/src/Mail/EscalatedExpiriesMail.php +++ b/packages/expiry/src/Mail/EscalatedExpiriesMail.php @@ -8,17 +8,10 @@ class EscalatedExpiriesMail extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; - public array $entries; - - public string $panelPath; - - public function __construct(array $entries, string $panelPath) - { - $this->entries = $entries; - $this->panelPath = $panelPath; - } + public function __construct(public array $entries, public string $panelPath) {} public function build() { diff --git a/packages/expiry/src/Models/Expiry.php b/packages/expiry/src/Models/Expiry.php index a8714ad05..fb607769c 100644 --- a/packages/expiry/src/Models/Expiry.php +++ b/packages/expiry/src/Models/Expiry.php @@ -2,16 +2,19 @@ namespace Moox\Expiry\Models; +use Exception; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Collection; use Moox\Core\Traits\SoftDelete\SingleSoftDeleteInModel; use Moox\Press\QueryBuilder\UserQueryBuilder; +use Override; class Expiry extends Model { - use HasFactory, SingleSoftDeleteInModel; + use HasFactory; + use SingleSoftDeleteInModel; protected $fillable = [ 'title', @@ -61,6 +64,7 @@ public function escalateUser(): BelongsTo /** * Use the custom query builder for the model. */ + #[Override] protected function newBaseQueryBuilder() { $connection = $this->getConnection(); @@ -99,7 +103,7 @@ public static function getUserOptions(): array $userModel = config('expiry.user_model'); if (! class_exists($userModel)) { - throw new \Exception("User model class {$userModel} does not exist."); + throw new Exception(sprintf('User model class %s does not exist.', $userModel)); } $notifiedToUserIds = Expiry::pluck('notified_to')->unique()->filter(); @@ -113,12 +117,8 @@ public static function getUserOptions(): array return $users ->pluck('display_name', 'ID') - ->filter(function ($displayName) { - return ! is_null($displayName); - }) - ->sortBy(function ($displayName, $id) { - return strtolower($displayName); - }) + ->filter(fn ($displayName): bool => ! is_null($displayName)) + ->sortBy(fn ($displayName, $id) => strtolower((string) $displayName)) ->toArray(); } } diff --git a/packages/expiry/src/Resources/ExpiryResource.php b/packages/expiry/src/Resources/ExpiryResource.php index bfcdf1473..2cb2821da 100644 --- a/packages/expiry/src/Resources/ExpiryResource.php +++ b/packages/expiry/src/Resources/ExpiryResource.php @@ -4,9 +4,9 @@ use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; @@ -15,11 +15,17 @@ use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Expiry\Actions\CustomExpiryAction; use Moox\Expiry\Models\Expiry; -use Moox\Expiry\Resources\ExpiryResource\Pages; +use Moox\Expiry\Resources\ExpiryResource\Pages\CreateExpiry; +use Moox\Expiry\Resources\ExpiryResource\Pages\EditExpiry; +use Moox\Expiry\Resources\ExpiryResource\Pages\ListExpiries; +use Moox\Expiry\Resources\ExpiryResource\Pages\ViewExpiry; +use Override; class ExpiryResource extends Resource { - use BaseInResource, SingleSoftDeleteInResource, TabsInResource; + use BaseInResource; + use SingleSoftDeleteInResource; + use TabsInResource; protected static ?string $model = Expiry::class; @@ -27,6 +33,7 @@ class ExpiryResource extends Resource protected static ?string $recordTitleAttribute = 'title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -34,6 +41,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { $expiryActionClass = config('expiry.expiry_action'); @@ -49,43 +57,43 @@ public static function table(Table $table): Table ->orderBy('expired_at', 'asc') ) ->columns([ - Tables\Columns\TextColumn::make('title') + TextColumn::make('title') ->label(__('core::core.title')) ->toggleable() ->searchable() ->sortable() ->limit(50), - Tables\Columns\TextColumn::make('expired_at') + TextColumn::make('expired_at') ->label(__('core::expiry.expired_at')) ->toggleable() ->sortable() ->since(), - Tables\Columns\TextColumn::make('processing_deadline') + TextColumn::make('processing_deadline') ->label(__('core::expiry.processing_deadline')) ->toggleable() ->sortable() ->since() - ->hidden(fn () => ! Expiry::query()->whereNotNull('processing_deadline')->exists()) + ->hidden(fn (): bool => ! Expiry::query()->whereNotNull('processing_deadline')->exists()) ->visible( - fn ($livewire) => isset($livewire->activeTab) + fn ($livewire): bool => isset($livewire->activeTab) && in_array($livewire->activeTab, ['all', 'documents', 'tasks'])), - Tables\Columns\TextColumn::make('escalated_at') + TextColumn::make('escalated_at') ->label(__('core::expiry.escalated_at')) ->toggleable() ->sortable() ->date() ->icon('gmdi-warning') ->color('warning') - ->hidden(fn () => ! Expiry::query()->whereNotNull('escalated_at')->exists()) + ->hidden(fn (): bool => ! Expiry::query()->whereNotNull('escalated_at')->exists()) ->visible( - fn ($livewire) => isset($livewire->activeTab) + fn ($livewire): bool => isset($livewire->activeTab) && in_array($livewire->activeTab, ['all', 'documents', 'tasks'])), - Tables\Columns\TextColumn::make('cycle') + TextColumn::make('cycle') ->label(__('core::expiry.cycle')) ->toggleable() ->sortable() ->searchable(), - Tables\Columns\TextColumn::make('notifyUser.display_name') + TextColumn::make('notifyUser.display_name') ->label(__('core::expiry.notifyUser')) ->toggleable() ->searchable() @@ -95,24 +103,24 @@ public static function table(Table $table): Table $tableName = $wpPrefix.'users'; return $query - ->leftJoin($tableName, 'expiries.notified_to', '=', "{$tableName}.ID") - ->orderBy("{$tableName}.display_name", $direction) + ->leftJoin($tableName, 'expiries.notified_to', '=', $tableName.'.ID') + ->orderBy($tableName.'.display_name', $direction) ->select('expiries.*'); }) ->limit(50), - Tables\Columns\TextColumn::make('expiry_job') + TextColumn::make('expiry_job') ->label(__('core::expiry.expiry_job')) ->toggleable() ->sortable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('category') + TextColumn::make('category') ->label(__('core::core.category')) ->toggleable() ->sortable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('status') + TextColumn::make('status') ->label(__('core::core.status')) ->toggleable() ->sortable() @@ -157,46 +165,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListExpiries::route('/'), - 'create' => Pages\CreateExpiry::route('/create'), - 'view' => Pages\ViewExpiry::route('/{record}'), - 'edit' => Pages\EditExpiry::route('/{record}/edit'), + 'index' => ListExpiries::route('/'), + 'create' => CreateExpiry::route('/create'), + 'view' => ViewExpiry::route('/{record}'), + 'edit' => EditExpiry::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('expiry.resources.expiry.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('expiry.resources.expiry.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('expiry.resources.expiry.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('expiry.resources.expiry.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('expiry.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('expiry.navigation_sort') + 1; diff --git a/packages/expiry/src/Resources/ExpiryResource/Pages/ListExpiries.php b/packages/expiry/src/Resources/ExpiryResource/Pages/ListExpiries.php index 960f0b7c6..57190c98e 100644 --- a/packages/expiry/src/Resources/ExpiryResource/Pages/ListExpiries.php +++ b/packages/expiry/src/Resources/ExpiryResource/Pages/ListExpiries.php @@ -12,7 +12,8 @@ class ListExpiries extends ListRecords { - use SingleSoftDeleteInListPage, TabsInListPage; + use SingleSoftDeleteInListPage; + use TabsInListPage; protected static string $resource = ExpiryResource::class; @@ -23,14 +24,14 @@ protected function getHeaderActions(): array Action::make('collectExpiries') ->label(__('core::expiry.update_expiries')) ->requiresConfirmation() - ->action(function () { + ->action(function (): void { self::collectExpiries(); }), ] : []; } - public static function collectExpiries() + public static function collectExpiries(): void { $jobs = config('expiry.collect_expiries_jobs', []); foreach ($jobs as $jobClass) { diff --git a/packages/expiry/src/Widgets/MyExpiry.php b/packages/expiry/src/Widgets/MyExpiry.php index 5a565d7b3..d0c0d4231 100644 --- a/packages/expiry/src/Widgets/MyExpiry.php +++ b/packages/expiry/src/Widgets/MyExpiry.php @@ -2,9 +2,9 @@ namespace Moox\Expiry\Widgets; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Filament\Widgets\TableWidget as BaseWidget; @@ -12,6 +12,7 @@ use Illuminate\Support\Facades\Config; use Livewire\WithPagination; use Moox\Expiry\Models\Expiry; +use Override; class MyExpiry extends BaseWidget { @@ -26,12 +27,12 @@ class MyExpiry extends BaseWidget 'lg' => 2, // full width for large screens ]; - public function mount() + public function mount(): void { $this->activeTab = request('activeTab', 'all'); } - public function switchTab($tab) + public function switchTab($tab): void { $this->activeTab = $tab; $this->resetPage(); @@ -50,26 +51,26 @@ public function table(Table $table): Table return $table ->query($query) ->columns([ - Tables\Columns\TextColumn::make('title') + TextColumn::make('title') ->toggleable() ->searchable() ->sortable() ->limit(50), - Tables\Columns\TextColumn::make('expired_at') + TextColumn::make('expired_at') ->toggleable() ->sortable() ->since(), - Tables\Columns\TextColumn::make('expiry_job') + TextColumn::make('expiry_job') ->toggleable() ->sortable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('category') + TextColumn::make('category') ->toggleable() ->sortable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('status') + TextColumn::make('status') ->toggleable() ->sortable() ->searchable() @@ -89,7 +90,7 @@ public function table(Table $table): Table ->options(Expiry::getExpiryStatusOptions()), ]) ->actions([ - ViewAction::make()->url(fn ($record): string => "{$record->link}") + ViewAction::make()->url(fn ($record): string => $record->link) ->openUrlInNewTab(), ]) ->bulkActions([DeleteBulkAction::make()]); @@ -105,6 +106,7 @@ public function getTabs(): array if ($tabConfig['value'] !== '') { $query = $query->where($tabConfig['field'], $tabConfig['value']); } + $badgeCount = $query->count(); $tabs[$key] = (object) [ 'label' => $tabConfig['label'], @@ -117,6 +119,7 @@ public function getTabs(): array return $tabs; } + #[Override] public function render(): View { return view('expiry::widgets.my-expiry', [ diff --git a/packages/flags/src/FlagsServiceProvider.php b/packages/flags/src/FlagsServiceProvider.php index 3ca39c01c..185445b95 100644 --- a/packages/flags/src/FlagsServiceProvider.php +++ b/packages/flags/src/FlagsServiceProvider.php @@ -7,14 +7,16 @@ use BladeUI\Icons\Factory; use Illuminate\Contracts\Container\Container; use Illuminate\Support\ServiceProvider; +use Override; final class FlagsServiceProvider extends ServiceProvider { + #[Override] public function register(): void { $this->registerConfig(); - $this->callAfterResolving(Factory::class, function (Factory $factory, Container $container) { + $this->callAfterResolving(Factory::class, function (Factory $factory, Container $container): void { $config = $container->make('config')->get('flags', []); $factory->add('flags', array_merge(['path' => __DIR__.'/../resources/svg'], $config)); diff --git a/packages/flags/tests/CompilesIconsTest.php b/packages/flags/tests/CompilesIconsTest.php index db4fb1fbf..ce0406a2e 100644 --- a/packages/flags/tests/CompilesIconsTest.php +++ b/packages/flags/tests/CompilesIconsTest.php @@ -6,12 +6,13 @@ use BladeUI\Icons\BladeIconsServiceProvider; use Moox\Flags\FlagsServiceProvider; +use Orchestra\Testbench\TestCase; // TODO: Care for Testbench -class CompilesIconsTest extends \Orchestra\Testbench\TestCase +class CompilesIconsTest extends TestCase { /** @test */ - public function it_compiles_a_single_anonymous_component() + public function it_compiles_a_single_anonymous_component(): void { $result = svg('flag')->toHtml(); // Note: the empty class here seems to be a Blade components bug. @@ -24,7 +25,7 @@ public function it_compiles_a_single_anonymous_component() } /** @test */ - public function it_can_add_classes_to_icons() + public function it_can_add_classes_to_icons(): void { $result = svg('flag', 'w-6 h-6 text-gray-500')->toHtml(); @@ -37,7 +38,7 @@ public function it_can_add_classes_to_icons() } /** @test */ - public function it_can_add_styles_to_icons() + public function it_can_add_styles_to_icons(): void { $result = svg('flag', ['style' => 'color: #555'])->toHtml(); diff --git a/packages/flags/workbench/app/Models/.gitkeep b/packages/flags/workbench/app/Models/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/flags/workbench/app/Models/User.php b/packages/flags/workbench/app/Models/User.php deleted file mode 100644 index accfba6f7..000000000 --- a/packages/flags/workbench/app/Models/User.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ - protected $fillable = [ - 'name', - 'email', - 'password', - ]; - - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ - protected $hidden = [ - 'password', - 'remember_token', - ]; - - /** - * The attributes that should be cast. - * - * @var array - */ - protected $casts = [ - 'email_verified_at' => 'datetime', - 'password' => 'hashed', - ]; -} diff --git a/packages/flags/workbench/app/Providers/WorkbenchServiceProvider.php b/packages/flags/workbench/app/Providers/WorkbenchServiceProvider.php deleted file mode 100644 index e8cec9c2a..000000000 --- a/packages/flags/workbench/app/Providers/WorkbenchServiceProvider.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -class UserFactory extends Factory -{ - /** - * The current password being used by the factory. - */ - protected static ?string $password; - - /** - * The name of the factory's corresponding model. - * - * @var class-string - */ - protected $model = User::class; - - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - 'name' => fake()->name(), - 'email' => fake()->unique()->safeEmail(), - 'email_verified_at' => now(), - 'password' => static::$password ??= Hash::make('password'), - 'remember_token' => Str::random(10), - ]; - } - - /** - * Indicate that the model's email address should be unverified. - */ - public function unverified(): static - { - return $this->state(fn (array $attributes) => [ - 'email_verified_at' => null, - ]); - } -} diff --git a/packages/flags/workbench/database/migrations/.gitkeep b/packages/flags/workbench/database/migrations/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/flags/workbench/database/seeders/DatabaseSeeder.php b/packages/flags/workbench/database/seeders/DatabaseSeeder.php deleted file mode 100644 index ce9bd1597..000000000 --- a/packages/flags/workbench/database/seeders/DatabaseSeeder.php +++ /dev/null @@ -1,23 +0,0 @@ -create(); - - UserFactory::new()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', - ]); - } -} diff --git a/packages/flags/workbench/resources/views/.gitkeep b/packages/flags/workbench/resources/views/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/flags/workbench/routes/web.php b/packages/flags/workbench/routes/web.php deleted file mode 100644 index 86a06c53e..000000000 --- a/packages/flags/workbench/routes/web.php +++ /dev/null @@ -1,7 +0,0 @@ - $this->title, diff --git a/packages/frontend/tests/ArchTest.php b/packages/frontend/tests/ArchTest.php index 80c425543..03d9c15ab 100644 --- a/packages/frontend/tests/ArchTest.php +++ b/packages/frontend/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\Frontend') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\Frontend\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\Frontend'); arch()->preset()->php(); diff --git a/packages/frontend/tests/Feature/ExampleTest.php b/packages/frontend/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/frontend/tests/Feature/ExampleTest.php +++ b/packages/frontend/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/frontend/tests/Pest.php b/packages/frontend/tests/Pest.php index ca75adaae..4f4739805 100644 --- a/packages/frontend/tests/Pest.php +++ b/packages/frontend/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/frontend/tests/TestCase.php b/packages/frontend/tests/TestCase.php index 53b2af2c3..e5a997d4a 100644 --- a/packages/frontend/tests/TestCase.php +++ b/packages/frontend/tests/TestCase.php @@ -13,7 +13,7 @@ protected function setUp(): void parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'VendorName\\Frontend\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn (string $modelName): string => 'VendorName\\Frontend\\Database\\Factories\\'.class_basename($modelName).'Factory' ); } @@ -24,7 +24,7 @@ protected function getPackageProviders($app) ]; } - public function getEnvironmentSetUp($app) + public function getEnvironmentSetUp($app): void { config()->set('database.default', 'testing'); diff --git a/packages/frontend/tests/Unit/ExampleTest.php b/packages/frontend/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/frontend/tests/Unit/ExampleTest.php +++ b/packages/frontend/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/jobs/src/Commands/InstallCommand.php b/packages/jobs/src/Commands/InstallCommand.php index 34257d62f..ad26cbc3f 100644 --- a/packages/jobs/src/Commands/InstallCommand.php +++ b/packages/jobs/src/Commands/InstallCommand.php @@ -73,6 +73,7 @@ public function publishConfiguration(): void return; } + warning('The Jobs config already exist. The config will not be published.'); } } @@ -87,6 +88,7 @@ public function publishMigrations(): void $this->callSilent('vendor:publish', ['--tag' => 'jobs-batch-migration']); } } + if (confirm('Do you wish to publish the migrations?', true)) { if (Schema::hasTable('job_queue_workers')) { warning('The job_queue_workers table already exists. The migrations will not be published.'); @@ -95,6 +97,7 @@ public function publishMigrations(): void $this->callSilent('vendor:publish', ['--tag' => 'jobs-queue-migration']); } } + if (confirm('Do you wish to publish the migrations?', true)) { if (Schema::hasTable('job_manager')) { warning('The job_manager table already exists. The migrations will not be published.'); @@ -156,7 +159,7 @@ public function registerPlugins(string $providerPath): void $intend = ' '; $namespace = "\Moox\Jobs"; - if ($queueDriver != 'database') { + if ($queueDriver !== 'database') { warning('The queue driver is not set to database. Jobs waiting will not be installed.'); $pluginsToAdd = multiselect( @@ -180,26 +183,27 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); } + File::put($providerPath, $newContent); } else { alert('There are no new plugins detected.'); @@ -235,12 +239,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/jobs/src/Commands/UpdateCommand.php b/packages/jobs/src/Commands/UpdateCommand.php index 07cb9143c..9a10bc7f3 100644 --- a/packages/jobs/src/Commands/UpdateCommand.php +++ b/packages/jobs/src/Commands/UpdateCommand.php @@ -60,23 +60,28 @@ public function updateSchema(): void info('Updating job_manager table...'); if (Schema::hasTable('job_manager')) { - Schema::table('job_manager', function (Blueprint $table) { + Schema::table('job_manager', function (Blueprint $table): void { if (! Schema::hasColumn('job_manager', 'available_at')) { $table->timestamp('available_at')->nullable(); } + if (! Schema::hasColumn('job_manager', 'status')) { $table->string('status'); $table->index(['status'], 'job_manager_status_index'); } + if (! Schema::hasColumn('job_manager', 'connection')) { $table->string('connection')->nullable(); } + if (! Schema::hasColumn('job_manager', 'job_queue_worker_id')) { $table->unsignedBigInteger('job_queue_worker_id')->nullable(); } + if (Schema::hasColumn('job_manager', 'job_id')) { $table->index(['job_id'], 'job_manager_job_id_index'); } + if (Schema::hasColumn('job_manager', 'queue')) { $table->index(['queue'], 'job_manager_queue_index'); } @@ -86,7 +91,8 @@ public function updateSchema(): void return; } - warning('The job_manager table does not exist. Let\'s publish the migration for it.'); + + warning("The job_manager table does not exist. Let's publish the migration for it."); $this->callSilent('vendor:publish', ['--tag' => 'jobs-manager-migration']); } } @@ -126,7 +132,7 @@ public function migrateData(): void $jobCount = DB::table('job_manager')->count(); if ($jobCount > 0) { - info("There are {$jobCount} entries in your job_manager table."); + info(sprintf('There are %d entries in your job_manager table.', $jobCount)); if (confirm('Do you want to migrate the jobs to show a correct status?')) { $jobs = DB::table('job_manager')->get(); diff --git a/packages/jobs/src/Http/SharedHosting/QueueWorker.php b/packages/jobs/src/Http/SharedHosting/QueueWorker.php index ce998e6ae..16e200bf2 100644 --- a/packages/jobs/src/Http/SharedHosting/QueueWorker.php +++ b/packages/jobs/src/Http/SharedHosting/QueueWorker.php @@ -7,7 +7,7 @@ class QueueWorker extends Controller { - public function __invoke() + public function __invoke(): string { $sharedHostingToken = config('core.shared_hosting.token'); diff --git a/packages/jobs/src/JobManagerProvider.php b/packages/jobs/src/JobManagerProvider.php index 10c122e5a..d1be5e202 100644 --- a/packages/jobs/src/JobManagerProvider.php +++ b/packages/jobs/src/JobManagerProvider.php @@ -10,33 +10,32 @@ use Illuminate\Support\Facades\Queue; use Illuminate\Support\ServiceProvider; use Moox\Jobs\Models\JobManager; +use Throwable; class JobManagerProvider extends ServiceProvider { /** * Bootstrap services. - * - * @return void */ - public function boot() + public function boot(): void { // Running - Queue::before(static function (JobProcessing $event) { + Queue::before(static function (JobProcessing $event): void { self::jobStarted($event->job); }); // Succeeded - Queue::after(static function (JobProcessed $event) { + Queue::after(static function (JobProcessed $event): void { self::jobFinished($event->job); }); // Failed - Queue::failing(static function (JobFailed $event) { + Queue::failing(static function (JobFailed $event): void { self::jobFinished($event->job, true, $event->exception); }); // Failed (retries exhausted) - Queue::exceptionOccurred(static function (JobExceptionOccurred $event) { + Queue::exceptionOccurred(static function (JobExceptionOccurred $event): void { self::jobFinished($event->job, true, $event->exception); }); } @@ -72,7 +71,7 @@ protected static function jobStarted(JobContract $job): void ->where('job_id', $jobId) ->where('failed', false) ->whereNull('finished_at') - ->each(function (JobManager $monitor) { + ->each(function (JobManager $monitor): void { $monitor->finished_at = now(); $monitor->failed = true; $monitor->save(); @@ -82,7 +81,7 @@ protected static function jobStarted(JobContract $job): void /** * Finish Queue Monitoring for Job. */ - protected static function jobFinished(JobContract $job, bool $failed = false, ?\Throwable $exception = null): void + protected static function jobFinished(JobContract $job, bool $failed = false, ?Throwable $exception = null): void { $monitor = JobManager::query() ->where('job_id', self::getJobId($job)) @@ -112,7 +111,7 @@ protected static function jobFinished(JobContract $job, bool $failed = false, ?\ $attributes += ['status' => 'failed']; - if ($exception !== null) { + if ($exception instanceof Throwable) { $attributes += [ 'exception_message' => mb_strcut($exception->getMessage(), 0, 65535), ]; diff --git a/packages/jobs/src/JobsServiceProvider.php b/packages/jobs/src/JobsServiceProvider.php index 9fc544da2..ba3292ac6 100644 --- a/packages/jobs/src/JobsServiceProvider.php +++ b/packages/jobs/src/JobsServiceProvider.php @@ -4,6 +4,7 @@ use Moox\Jobs\Commands\InstallCommand; use Moox\Jobs\Commands\UpdateCommand; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -18,7 +19,8 @@ public function configurePackage(Package $package): void ->hasCommands(InstallCommand::class, UpdateCommand::class); } - public function boot() + #[Override] + public function boot(): void { parent::boot(); diff --git a/packages/jobs/src/Models/FailedJob.php b/packages/jobs/src/Models/FailedJob.php index 80c4f4d76..e2b008e5c 100644 --- a/packages/jobs/src/Models/FailedJob.php +++ b/packages/jobs/src/Models/FailedJob.php @@ -2,6 +2,7 @@ namespace Moox\Jobs\Models; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; /** @@ -9,7 +10,7 @@ * @property string $uuid * @property string $connection * @property string $queue - * @property \Carbon\Carbon $failed_at + * @property Carbon $failed_at */ class FailedJob extends Model { diff --git a/packages/jobs/src/Models/Job.php b/packages/jobs/src/Models/Job.php index 9c85293e7..18aecd675 100644 --- a/packages/jobs/src/Models/Job.php +++ b/packages/jobs/src/Models/Job.php @@ -16,7 +16,7 @@ class Job extends Model public function status(): Attribute { return Attribute::make( - get: function () { + get: function (): string { if ($this->reserved_at) { return 'running'; } @@ -28,7 +28,7 @@ public function status(): Attribute public function getDisplayNameAttribute() { - $payload = json_decode($this->attributes['payload'], true); + $payload = json_decode((string) $this->attributes['payload'], true); return $payload['displayName'] ?? null; } diff --git a/packages/jobs/src/Models/JobManager.php b/packages/jobs/src/Models/JobManager.php index 1ed959e0f..d0ccc6938 100644 --- a/packages/jobs/src/Models/JobManager.php +++ b/packages/jobs/src/Models/JobManager.php @@ -3,6 +3,7 @@ namespace Moox\Jobs\Models; use Illuminate\Contracts\Queue\Job as JobContract; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Prunable; @@ -10,14 +11,15 @@ class JobManager extends Model { - use HasFactory, Prunable; + use HasFactory; + use Prunable; protected $table = 'job_manager'; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'job_id', @@ -76,7 +78,7 @@ public function hasSucceeded(): bool } /** - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ public function prunable() { diff --git a/packages/jobs/src/Resources/JobBatchesResource.php b/packages/jobs/src/Resources/JobBatchesResource.php index 651f6f026..3b7da0898 100644 --- a/packages/jobs/src/Resources/JobBatchesResource.php +++ b/packages/jobs/src/Resources/JobBatchesResource.php @@ -9,6 +9,7 @@ use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Jobs\Models\JobBatch; use Moox\Jobs\Resources\JobBatchesResource\Pages\ListJobBatches; +use Override; class JobBatchesResource extends Resource { @@ -18,19 +19,17 @@ class JobBatchesResource extends Resource protected static ?string $navigationIcon = null; + #[Override] public static function getNavigationIcon(): string { if (self::$navigationIcon === null) { - if (config('core.use_google_icons', true)) { - self::$navigationIcon = 'gmdi-all-inbox'; - } else { - self::$navigationIcon = 'heroicon-o-inbox-stack'; - } + self::$navigationIcon = config('core.use_google_icons', true) ? 'gmdi-all-inbox' : 'heroicon-o-inbox-stack'; } return self::$navigationIcon; } + #[Override] public static function table(Table $table): Table { return $table @@ -95,6 +94,7 @@ public static function table(Table $table): Table ->defaultSort('created_at', 'desc'); } + #[Override] public static function getRelations(): array { return [ @@ -102,11 +102,13 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return ['index' => ListJobBatches::route('/')]; } + #[Override] public static function getWidgets(): array { return [ @@ -114,26 +116,31 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return __('jobs::translations.jobs_batches.single'); } + #[Override] public static function getPluralModelLabel(): string { return __('jobs::translations.jobs_batches.plural'); } + #[Override] public static function getNavigationLabel(): string { return __('jobs::translations.jobs_batches.navigation_label'); } + #[Override] public static function getBreadcrumb(): string { return __('jobs::translations.breadcrumb'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -144,11 +151,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return __('jobs::translations.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('jobs.navigation_sort') + 4; diff --git a/packages/jobs/src/Resources/JobBatchesResource/Pages/ListJobBatches.php b/packages/jobs/src/Resources/JobBatchesResource/Pages/ListJobBatches.php index cfcc2aa11..2285b4dcb 100644 --- a/packages/jobs/src/Resources/JobBatchesResource/Pages/ListJobBatches.php +++ b/packages/jobs/src/Resources/JobBatchesResource/Pages/ListJobBatches.php @@ -12,7 +12,7 @@ class ListJobBatches extends ListRecords { protected static string $resource = JobBatchesResource::class; - public function getActions(): array + protected function getActions(): array { return [ Action::make('prune_batches') diff --git a/packages/jobs/src/Resources/JobsFailedResource.php b/packages/jobs/src/Resources/JobsFailedResource.php index 6486296bd..a790015e6 100644 --- a/packages/jobs/src/Resources/JobsFailedResource.php +++ b/packages/jobs/src/Resources/JobsFailedResource.php @@ -18,6 +18,7 @@ use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Jobs\Models\FailedJob; use Moox\Jobs\Resources\JobsFailedResource\Pages\ListFailedJobs; +use Override; class JobsFailedResource extends Resource { @@ -27,19 +28,17 @@ class JobsFailedResource extends Resource protected static ?string $navigationIcon = null; + #[Override] public static function getNavigationIcon(): string { if (self::$navigationIcon === null) { - if (config('core.use_google_icons', true)) { - self::$navigationIcon = 'gmdi-error'; - } else { - self::$navigationIcon = 'heroicon-o-exclamation-triangle'; - } + self::$navigationIcon = config('core.use_google_icons', true) ? 'gmdi-error' : 'heroicon-o-exclamation-triangle'; } return self::$navigationIcon; } + #[Override] public static function form(Form $form): Form { return $form @@ -56,6 +55,7 @@ public static function form(Form $form): Form ])->columns(4); } + #[Override] public static function table(Table $table): Table { return $table @@ -69,7 +69,7 @@ public static function table(Table $table): Table ->toggleable() ->wrap() ->limit(200) - ->tooltip(fn (FailedJob $record) => "{$record->failed_at} UUID: {$record->uuid}; Connection: {$record->connection}; Queue: {$record->queue};") + ->tooltip(fn (FailedJob $record): string => sprintf('%s UUID: %s; Connection: %s; Queue: %s;', $record->failed_at, $record->uuid, $record->connection, $record->queue)) ->label(__('jobs::translations.exception')), TextColumn::make('uuid')->sortable()->searchable()->toggleable(isToggledHiddenByDefault: true)->label(__('jobs::translations.uuid')), TextColumn::make('connection')->sortable()->searchable()->toggleable(isToggledHiddenByDefault: true)->label(__('jobs::translations.connection')), @@ -82,8 +82,9 @@ public static function table(Table $table): Table ->requiresConfirmation() ->action(function (Collection $records): void { foreach ($records as $record) { - Artisan::call("queue:retry {$record->uuid}"); + Artisan::call('queue:retry '.$record->uuid); } + Notification::make() ->title($records->count().__('jobs::translations.pushed_back_notification')) ->success() @@ -97,15 +98,16 @@ public static function table(Table $table): Table ->label(__('jobs::translations.retry')) ->requiresConfirmation() ->action(function (FailedJob $record): void { - Artisan::call("queue:retry {$record->uuid}"); + Artisan::call('queue:retry '.$record->uuid); Notification::make() - ->title(__('jobs::translations.jobs.single')." {$record->uuid} ".__('jobs::translations.job_pushed_back_notification')) + ->title(__('jobs::translations.jobs.single').sprintf(' %s ', $record->uuid).__('jobs::translations.job_pushed_back_notification')) ->success() ->send(); }), ]); } + #[Override] public static function getRelations(): array { return [ @@ -113,6 +115,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -120,6 +123,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -127,26 +131,31 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return __('jobs::translations.jobs_failed.single'); } + #[Override] public static function getPluralModelLabel(): string { return __('jobs::translations.jobs_failed.plural'); } + #[Override] public static function getNavigationLabel(): string { return __('jobs::translations.jobs_failed.navigation_label'); } + #[Override] public static function getBreadcrumb(): string { return __('jobs::translations.breadcrumb'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -157,11 +166,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return __('jobs::translations.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('jobs.navigation_sort') + 2; diff --git a/packages/jobs/src/Resources/JobsFailedResource/Pages/ListFailedJobs.php b/packages/jobs/src/Resources/JobsFailedResource/Pages/ListFailedJobs.php index b9fc4e5b6..7d034a79b 100644 --- a/packages/jobs/src/Resources/JobsFailedResource/Pages/ListFailedJobs.php +++ b/packages/jobs/src/Resources/JobsFailedResource/Pages/ListFailedJobs.php @@ -13,7 +13,7 @@ class ListFailedJobs extends ListRecords { protected static string $resource = JobsFailedResource::class; - public function getActions(): array + protected function getActions(): array { return [ Action::make('retry_all') diff --git a/packages/jobs/src/Resources/JobsResource.php b/packages/jobs/src/Resources/JobsResource.php index b196e9284..a6445319e 100644 --- a/packages/jobs/src/Resources/JobsResource.php +++ b/packages/jobs/src/Resources/JobsResource.php @@ -15,6 +15,7 @@ use Moox\Jobs\Models\JobManager; use Moox\Jobs\Resources\JobsResource\Pages\ListJobs; use Moox\Jobs\Resources\JobsResource\Widgets\JobStatsOverview; +use Override; use RyanChandler\FilamentProgressColumn\ProgressColumn; class JobsResource extends Resource @@ -25,19 +26,17 @@ class JobsResource extends Resource protected static ?string $navigationIcon = null; + #[Override] public static function getNavigationIcon(): string { if (self::$navigationIcon === null) { - if (config('core.use_google_icons', true)) { - self::$navigationIcon = 'gmdi-play-arrow'; - } else { - self::$navigationIcon = 'heroicon-o-play'; - } + self::$navigationIcon = config('core.use_google_icons', true) ? 'gmdi-play-arrow' : 'heroicon-o-play'; } return self::$navigationIcon; } + #[Override] public static function form(Form $form): Form { return $form @@ -65,6 +64,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -75,7 +75,7 @@ public static function table(Table $table): Table ->badge() ->sortable() ->label(__('jobs::translations.status')) - ->formatStateUsing(fn (string $state): string => __("jobs::translations.{$state}")) + ->formatStateUsing(fn (string $state): string => __('jobs::translations.'.$state)) ->color(fn (string $state): string => match ($state) { 'running' => 'primary', 'succeeded' => 'success', @@ -95,9 +95,7 @@ public static function table(Table $table): Table // TODO: poll? extra poll needed?, color (test live), width etc. // IDEA: For adding width (of each separately) to the progress bar, fork (into core?) // SEE: https://github.com/ryangjchandler/filament-progress-column - ->color(function ($record) { - return $record->progress > 99 ? 'success' : ''; - }), + ->color(fn ($record): string => $record->progress > 99 ? 'success' : ''), TextColumn::make('started_at') ->label(__('jobs::translations.started_at')) ->since() @@ -109,6 +107,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -116,11 +115,13 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return ['index' => ListJobs::route('/')]; } + #[Override] public static function getWidgets(): array { return [ @@ -128,36 +129,43 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return __('jobs::translations.jobs.single'); } + #[Override] public static function getPluralModelLabel(): string { return __('jobs::translations.jobs.plural'); } + #[Override] public static function getNavigationLabel(): string { return __('jobs::translations.jobs.navigation_label'); } + #[Override] public static function getBreadcrumb(): string { return __('jobs::translations.breadcrumb'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return __('jobs::translations.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('jobs.navigation_sort'); diff --git a/packages/jobs/src/Resources/JobsResource/Pages/ListJobs.php b/packages/jobs/src/Resources/JobsResource/Pages/ListJobs.php index 13196855b..5e372a536 100644 --- a/packages/jobs/src/Resources/JobsResource/Pages/ListJobs.php +++ b/packages/jobs/src/Resources/JobsResource/Pages/ListJobs.php @@ -5,23 +5,26 @@ use Filament\Resources\Pages\ListRecords; use Moox\Jobs\Resources\JobsResource; use Moox\Jobs\Resources\JobsResource\Widgets\JobStatsOverview; +use Override; class ListJobs extends ListRecords { public static string $resource = JobsResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ JobStatsOverview::class, ]; } + #[Override] public function getTitle(): string { return __('jobs::translations.jobs.plural'); diff --git a/packages/jobs/src/Resources/JobsResource/Widgets/JobStatsOverview.php b/packages/jobs/src/Resources/JobsResource/Widgets/JobStatsOverview.php index 5639df4d7..6b61e2d63 100644 --- a/packages/jobs/src/Resources/JobsResource/Widgets/JobStatsOverview.php +++ b/packages/jobs/src/Resources/JobsResource/Widgets/JobStatsOverview.php @@ -7,11 +7,13 @@ use Illuminate\Support\Facades\DB; use Moox\Jobs\Models\JobManager; use Moox\Jobs\Traits\FormatSeconds; +use Override; class JobStatsOverview extends BaseWidget { use FormatSeconds; + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/jobs/src/Resources/JobsWaitingResource.php b/packages/jobs/src/Resources/JobsWaitingResource.php index d43552233..e2490f42d 100644 --- a/packages/jobs/src/Resources/JobsWaitingResource.php +++ b/packages/jobs/src/Resources/JobsWaitingResource.php @@ -15,6 +15,7 @@ use Moox\Jobs\Models\Job; use Moox\Jobs\Resources\JobsWaitingResource\Pages\ListJobsWaiting; use Moox\Jobs\Resources\JobsWaitingResource\Widgets\JobsWaitingOverview; +use Override; class JobsWaitingResource extends Resource { @@ -24,19 +25,17 @@ class JobsWaitingResource extends Resource protected static ?string $navigationIcon = null; + #[Override] public static function getNavigationIcon(): string { if (self::$navigationIcon === null) { - if (config('core.use_google_icons', true)) { - self::$navigationIcon = 'gmdi-pause'; - } else { - self::$navigationIcon = 'heroicon-o-pause'; - } + self::$navigationIcon = config('core.use_google_icons', true) ? 'gmdi-pause' : 'heroicon-o-pause'; } return self::$navigationIcon; } + #[Override] public static function form(Form $form): Form { return $form @@ -65,6 +64,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -72,7 +72,7 @@ public static function table(Table $table): Table TextColumn::make('status') ->badge() ->label(__('jobs::translations.status')) - ->formatStateUsing(fn (string $state): string => __("jobs::translations.{$state}")) + ->formatStateUsing(fn (string $state): string => __('jobs::translations.'.$state)) ->color(fn (string $state): string => match ($state) { 'running' => 'primary', 'waiting' => 'success', @@ -103,6 +103,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -110,6 +111,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -117,6 +119,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -124,26 +127,31 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return __('jobs::translations.jobs_waiting.single'); } + #[Override] public static function getPluralModelLabel(): string { return __('jobs::translations.jobs_waiting.plural'); } + #[Override] public static function getNavigationLabel(): string { return __('jobs::translations.jobs_waiting.navigation_label'); } + #[Override] public static function getBreadcrumb(): string { return __('jobs::translations.breadcrumb'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -154,11 +162,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return __('jobs::translations.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('jobs.navigation_sort') + 1; diff --git a/packages/jobs/src/Resources/JobsWaitingResource/Pages/ListJobsWaiting.php b/packages/jobs/src/Resources/JobsWaitingResource/Pages/ListJobsWaiting.php index e692f8a06..11461bc43 100644 --- a/packages/jobs/src/Resources/JobsWaitingResource/Pages/ListJobsWaiting.php +++ b/packages/jobs/src/Resources/JobsWaitingResource/Pages/ListJobsWaiting.php @@ -5,23 +5,26 @@ use Filament\Resources\Pages\ListRecords; use Moox\Jobs\Resources\JobsWaitingResource; use Moox\Jobs\Resources\JobsWaitingResource\Widgets\JobsWaitingOverview; +use Override; class ListJobsWaiting extends ListRecords { public static string $resource = JobsWaitingResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ JobsWaitingOverview::class, ]; } + #[Override] public function getTitle(): string { return __('jobs::translations.jobs_waiting.plural'); diff --git a/packages/jobs/src/Resources/JobsWaitingResource/Widgets/JobsWaitingOverview.php b/packages/jobs/src/Resources/JobsWaitingResource/Widgets/JobsWaitingOverview.php index a9107a203..341d90f71 100644 --- a/packages/jobs/src/Resources/JobsWaitingResource/Widgets/JobsWaitingOverview.php +++ b/packages/jobs/src/Resources/JobsWaitingResource/Widgets/JobsWaitingOverview.php @@ -8,11 +8,13 @@ use Moox\Jobs\Models\Job; use Moox\Jobs\Models\JobManager; use Moox\Jobs\Traits\FormatSeconds; +use Override; class JobsWaitingOverview extends BaseWidget { use FormatSeconds; + #[Override] protected function getCards(): array { $jobsWaiting = Job::query() diff --git a/packages/jobs/src/Traits/FormatSeconds.php b/packages/jobs/src/Traits/FormatSeconds.php index 8ac16b2f3..787801c38 100644 --- a/packages/jobs/src/Traits/FormatSeconds.php +++ b/packages/jobs/src/Traits/FormatSeconds.php @@ -18,27 +18,25 @@ public function formatSeconds(int $seconds): string $seconds -= $hours * (60 * 60); $minutes = floor($seconds / 60); - $seconds = $seconds - ($minutes * 60); + $seconds -= $minutes * 60; } $formattedSeconds = ''; if ($days > 0) { - $formattedSeconds .= "$days d "; + $formattedSeconds .= $days.' d '; } - if ($hours > 0 or $days > 0) { - $formattedSeconds .= "$hours h "; + if ($hours > 0 || $days > 0) { + $formattedSeconds .= $hours.' h '; } - if ($minutes > 0 or $hours > 0 or $days > 0) { - $formattedSeconds .= "$minutes m "; + if ($minutes > 0 || $hours > 0 || $days > 0) { + $formattedSeconds .= $minutes.' m '; } - if ($days == 0) { - if ($seconds > 0 or $minutes > 0 or $hours > 0) { - $formattedSeconds .= "$seconds s"; - } + if ($days == 0 && ($seconds > 0 || $minutes > 0 || $hours > 0)) { + $formattedSeconds .= $seconds.' s'; } return $formattedSeconds; diff --git a/packages/layout/tests/ArchTest.php b/packages/layout/tests/ArchTest.php index c69f1757f..caf54c94e 100644 --- a/packages/layout/tests/ArchTest.php +++ b/packages/layout/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\Layout') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\Layout\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\Layout'); arch()->preset()->php(); diff --git a/packages/layout/tests/Feature/ExampleTest.php b/packages/layout/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/layout/tests/Feature/ExampleTest.php +++ b/packages/layout/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/layout/tests/Pest.php b/packages/layout/tests/Pest.php index 92bfb133d..6d23f20bc 100644 --- a/packages/layout/tests/Pest.php +++ b/packages/layout/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/layout/tests/TestCase.php b/packages/layout/tests/TestCase.php index 532547be6..39f8348b4 100644 --- a/packages/layout/tests/TestCase.php +++ b/packages/layout/tests/TestCase.php @@ -13,7 +13,7 @@ protected function setUp(): void parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'VendorName\\Layout\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn (string $modelName): string => 'VendorName\\Layout\\Database\\Factories\\'.class_basename($modelName).'Factory' ); } @@ -24,7 +24,7 @@ protected function getPackageProviders($app) ]; } - public function getEnvironmentSetUp($app) + public function getEnvironmentSetUp($app): void { config()->set('database.default', 'testing'); diff --git a/packages/layout/tests/Unit/ExampleTest.php b/packages/layout/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/layout/tests/Unit/ExampleTest.php +++ b/packages/layout/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/locate/database/migrations/2023_09_10_000006_create_countries_table.php b/packages/locate/database/migrations/2023_09_10_000006_create_countries_table.php index 59755c85d..abf3d912c 100644 --- a/packages/locate/database/migrations/2023_09_10_000006_create_countries_table.php +++ b/packages/locate/database/migrations/2023_09_10_000006_create_countries_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('countries', function (Blueprint $table) { + Schema::create('countries', function (Blueprint $table): void { $table->bigIncrements('id'); $table->string('title'); $table->string('slug'); diff --git a/packages/locate/database/migrations/2023_09_10_000007_create_currencies_table.php b/packages/locate/database/migrations/2023_09_10_000007_create_currencies_table.php index d2f07b4e7..1eae2ea83 100644 --- a/packages/locate/database/migrations/2023_09_10_000007_create_currencies_table.php +++ b/packages/locate/database/migrations/2023_09_10_000007_create_currencies_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('currencies', function (Blueprint $table) { + Schema::create('currencies', function (Blueprint $table): void { $table->bigIncrements('id'); $table->timestamps(); diff --git a/packages/locate/database/migrations/2023_09_10_000008_create_country_currency_table.php b/packages/locate/database/migrations/2023_09_10_000008_create_country_currency_table.php index 649013f1a..7781b176c 100644 --- a/packages/locate/database/migrations/2023_09_10_000008_create_country_currency_table.php +++ b/packages/locate/database/migrations/2023_09_10_000008_create_country_currency_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('country_currency', function (Blueprint $table) { + Schema::create('country_currency', function (Blueprint $table): void { $table->unsignedBigInteger('country_id'); $table->unsignedBigInteger('currency_id'); }); diff --git a/packages/locate/database/migrations/2023_09_10_000009_create_country_language_table.php b/packages/locate/database/migrations/2023_09_10_000009_create_country_language_table.php index 7166d58f6..9f208a9f5 100644 --- a/packages/locate/database/migrations/2023_09_10_000009_create_country_language_table.php +++ b/packages/locate/database/migrations/2023_09_10_000009_create_country_language_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('country_language', function (Blueprint $table) { + Schema::create('country_language', function (Blueprint $table): void { $table->unsignedBigInteger('language_id'); $table->unsignedBigInteger('country_id'); }); diff --git a/packages/locate/database/migrations/2023_09_10_000010_create_country_timezone_table.php b/packages/locate/database/migrations/2023_09_10_000010_create_country_timezone_table.php index f3df1a204..fd394aeca 100644 --- a/packages/locate/database/migrations/2023_09_10_000010_create_country_timezone_table.php +++ b/packages/locate/database/migrations/2023_09_10_000010_create_country_timezone_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('country_timezone', function (Blueprint $table) { + Schema::create('country_timezone', function (Blueprint $table): void { $table->unsignedBigInteger('country_id'); $table->unsignedBigInteger('timezone_id'); }); diff --git a/packages/locate/database/migrations/2023_09_10_000013_create_languages_table.php b/packages/locate/database/migrations/2023_09_10_000013_create_languages_table.php index f07b785f9..5b955afa8 100644 --- a/packages/locate/database/migrations/2023_09_10_000013_create_languages_table.php +++ b/packages/locate/database/migrations/2023_09_10_000013_create_languages_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('languages', function (Blueprint $table) { + Schema::create('languages', function (Blueprint $table): void { $table->bigIncrements('id'); $table->string('title'); $table->string('slug'); diff --git a/packages/locate/database/migrations/2023_09_10_000014_create_timezones_table.php b/packages/locate/database/migrations/2023_09_10_000014_create_timezones_table.php index cef478297..598300a54 100644 --- a/packages/locate/database/migrations/2023_09_10_000014_create_timezones_table.php +++ b/packages/locate/database/migrations/2023_09_10_000014_create_timezones_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('timezones', function (Blueprint $table) { + Schema::create('timezones', function (Blueprint $table): void { $table->bigIncrements('id'); $table->string('zone_name'); $table->string('country_code', 2); diff --git a/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_areas_table.php b/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_areas_table.php index 60ce91169..abb8c7933 100644 --- a/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_areas_table.php +++ b/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_areas_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::table('areas', function (Blueprint $table) { + Schema::table('areas', function (Blueprint $table): void { $table ->foreign('parent_area_id') ->references('id') @@ -26,7 +26,7 @@ public function up(): void */ public function down(): void { - Schema::table('areas', function (Blueprint $table) { + Schema::table('areas', function (Blueprint $table): void { $table->dropForeign(['parent_continent_id']); }); } diff --git a/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_countries_table.php b/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_countries_table.php index c0f41d7ff..3f9031502 100644 --- a/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_countries_table.php +++ b/packages/locate/database/migrations/2023_09_10_009007_add_foreigns_to_countries_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::table('countries', function (Blueprint $table) { + Schema::table('countries', function (Blueprint $table): void { $table ->foreign('continent_id') ->references('id') @@ -26,7 +26,7 @@ public function up(): void */ public function down(): void { - Schema::table('countries', function (Blueprint $table) { + Schema::table('countries', function (Blueprint $table): void { $table->dropForeign(['continent_id']); }); } diff --git a/packages/locate/database/migrations/2023_09_10_009008_add_foreigns_to_country_currency_table.php b/packages/locate/database/migrations/2023_09_10_009008_add_foreigns_to_country_currency_table.php index 1fc6289bb..4aec66982 100644 --- a/packages/locate/database/migrations/2023_09_10_009008_add_foreigns_to_country_currency_table.php +++ b/packages/locate/database/migrations/2023_09_10_009008_add_foreigns_to_country_currency_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::table('country_currency', function (Blueprint $table) { + Schema::table('country_currency', function (Blueprint $table): void { $table ->foreign('country_id') ->references('id') @@ -33,7 +33,7 @@ public function up(): void */ public function down(): void { - Schema::table('country_currency', function (Blueprint $table) { + Schema::table('country_currency', function (Blueprint $table): void { $table->dropForeign(['country_id']); $table->dropForeign(['currency_id']); }); diff --git a/packages/locate/database/migrations/2023_09_10_009009_add_foreigns_to_country_language_table.php b/packages/locate/database/migrations/2023_09_10_009009_add_foreigns_to_country_language_table.php index 9bc8b9abe..72f04ea1b 100644 --- a/packages/locate/database/migrations/2023_09_10_009009_add_foreigns_to_country_language_table.php +++ b/packages/locate/database/migrations/2023_09_10_009009_add_foreigns_to_country_language_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::table('country_language', function (Blueprint $table) { + Schema::table('country_language', function (Blueprint $table): void { $table ->foreign('language_id') ->references('id') @@ -33,7 +33,7 @@ public function up(): void */ public function down(): void { - Schema::table('country_language', function (Blueprint $table) { + Schema::table('country_language', function (Blueprint $table): void { $table->dropForeign(['language_id']); $table->dropForeign(['country_id']); }); diff --git a/packages/locate/database/migrations/2023_09_10_009010_add_foreigns_to_country_timezone_table.php b/packages/locate/database/migrations/2023_09_10_009010_add_foreigns_to_country_timezone_table.php index 9d59eab93..1c2e159c4 100644 --- a/packages/locate/database/migrations/2023_09_10_009010_add_foreigns_to_country_timezone_table.php +++ b/packages/locate/database/migrations/2023_09_10_009010_add_foreigns_to_country_timezone_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::table('country_timezone', function (Blueprint $table) { + Schema::table('country_timezone', function (Blueprint $table): void { $table ->foreign('country_id') ->references('id') @@ -33,7 +33,7 @@ public function up(): void */ public function down(): void { - Schema::table('country_timezone', function (Blueprint $table) { + Schema::table('country_timezone', function (Blueprint $table): void { $table->dropForeign(['country_id']); $table->dropForeign(['timezone_id']); }); diff --git a/packages/locate/src/Commands/InstallCommand.php b/packages/locate/src/Commands/InstallCommand.php index a138dfc82..336ad0003 100644 --- a/packages/locate/src/Commands/InstallCommand.php +++ b/packages/locate/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Locate config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing Locates Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'locate-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/locate/src/Resources/AreaResource.php b/packages/locate/src/Resources/AreaResource.php index 8eb09bc09..506d5e729 100644 --- a/packages/locate/src/Resources/AreaResource.php +++ b/packages/locate/src/Resources/AreaResource.php @@ -14,6 +14,7 @@ use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Locate\Models\Area; use Moox\Locate\Resources\AreaResource\Pages\ListPage; +use Override; class AreaResource extends Resource { @@ -25,6 +26,7 @@ class AreaResource extends Resource protected static ?string $navigationIcon = 'gmdi-place'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -44,6 +46,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table->columns([ @@ -59,6 +62,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getPages(): array { return [ @@ -67,6 +71,7 @@ public static function getPages(): array ]; } + #[Override] public static function getNavigationSort(): ?int { return 8001; diff --git a/packages/locate/src/Resources/AreaResource/Pages/ListPage.php b/packages/locate/src/Resources/AreaResource/Pages/ListPage.php index e024ddd4a..1122fed0c 100644 --- a/packages/locate/src/Resources/AreaResource/Pages/ListPage.php +++ b/packages/locate/src/Resources/AreaResource/Pages/ListPage.php @@ -5,23 +5,26 @@ use Filament\Actions\CreateAction; use Filament\Resources\Pages\ListRecords; use Moox\Locate\Resources\AreaResource; +use Override; class ListPage extends ListRecords { public static string $resource = AreaResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ // LocateWidgets::class, ]; } + #[Override] public function getTitle(): string { return __('locate::translations.title'); @@ -31,9 +34,7 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): static { - return $model::create($data); - }), + ->using(fn (array $data, string $model): static => $model::create($data)), ]; } } diff --git a/packages/locate/src/Resources/AreaResource/Widgets/LocateWidgets.php b/packages/locate/src/Resources/AreaResource/Widgets/LocateWidgets.php index 867a97c49..13a3c75ed 100644 --- a/packages/locate/src/Resources/AreaResource/Widgets/LocateWidgets.php +++ b/packages/locate/src/Resources/AreaResource/Widgets/LocateWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Locate\Models\Area; +use Override; class LocateWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/login-link/config/login-link.php b/packages/login-link/config/login-link.php index 0c31c7616..f7dd0e8f5 100644 --- a/packages/login-link/config/login-link.php +++ b/packages/login-link/config/login-link.php @@ -1,5 +1,7 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, 'Moox Users' => \Moox\User\Models\User::class, ], diff --git a/packages/login-link/routes/web.php b/packages/login-link/routes/web.php index dd8366315..8c3b1bbbb 100644 --- a/packages/login-link/routes/web.php +++ b/packages/login-link/routes/web.php @@ -3,7 +3,7 @@ use Illuminate\Support\Facades\Route; use Moox\LoginLink\Http\Controllers\LoginLinkController; -Route::group(['middleware' => ['web']], function () { +Route::group(['middleware' => ['web']], function (): void { Route::get('/login-link', [LoginLinkController::class, 'requestForm'])->name('login-link.request'); Route::post('/login-link', [LoginLinkController::class, 'sendLink'])->name('login-link.send'); Route::get('/login-link/{userId}-{token}', [LoginLinkController::class, 'authenticate'])->name('login-link.authenticate'); diff --git a/packages/login-link/src/Commands/InstallCommand.php b/packages/login-link/src/Commands/InstallCommand.php index f9530b9d9..a7dc6feaa 100644 --- a/packages/login-link/src/Commands/InstallCommand.php +++ b/packages/login-link/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The LoginLink config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing LoginLinks Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'login-link-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/login-link/src/Http/Controllers/LoginLinkController.php b/packages/login-link/src/Http/Controllers/LoginLinkController.php index 98cfc15a1..7f594d4d0 100644 --- a/packages/login-link/src/Http/Controllers/LoginLinkController.php +++ b/packages/login-link/src/Http/Controllers/LoginLinkController.php @@ -36,13 +36,13 @@ public function sendLink(Request $request) return back()->with('message', 'Login link has been sent!'); } - public function sendLinkInternal($user) + public function sendLinkInternal($user): void { $token = Str::random(40); $loginLink = LoginLink::create([ 'user_id' => $user->id, - 'user_type' => get_class($user), + 'user_type' => $user::class, 'email' => $user->email, 'token' => $token, 'expires_at' => now()->addHours(config('login-link.expiration_time')), @@ -54,8 +54,8 @@ public function sendLinkInternal($user) public function authenticate($userId, $token) { try { - $userId = urldecode(decrypt($userId)); - } catch (DecryptException $e) { + $userId = urldecode((string) decrypt($userId)); + } catch (DecryptException) { return redirect()->route('login')->withErrors(['invalid' => 'Invalid or corrupted link.']); } @@ -64,11 +64,7 @@ public function authenticate($userId, $token) ->where('user_id', $userId) ->firstOrFail(); - if (isset($loginLink->user_type)) { - $userType = $loginLink->user_type; - } else { - $userType = 'App\Models\User'; - } + $userType = $loginLink->user_type ?? User::class; $loginLink->update(['used_at' => now()]); diff --git a/packages/login-link/src/Mail/LoginLinkEmail.php b/packages/login-link/src/Mail/LoginLinkEmail.php index daa854a81..85bf82918 100644 --- a/packages/login-link/src/Mail/LoginLinkEmail.php +++ b/packages/login-link/src/Mail/LoginLinkEmail.php @@ -9,8 +9,12 @@ class LoginLinkEmail extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; + /** + * @var LoginLink + */ public $loginLink; public function __construct(LoginLink $loginLink) @@ -21,7 +25,7 @@ public function __construct(LoginLink $loginLink) public function build() { $userId = urlencode(encrypt($this->loginLink->user_id)); - $url = url("/login-link/{$userId}-{$this->loginLink->token}"); + $url = url(sprintf('/login-link/%s-%s', $userId, $this->loginLink->token)); return $this->subject('Your Login Link') ->markdown('login-link::emails.loginlink', ['url' => $url]); diff --git a/packages/login-link/src/Models/LoginLink.php b/packages/login-link/src/Models/LoginLink.php index e5c4fc801..ba086fea0 100644 --- a/packages/login-link/src/Models/LoginLink.php +++ b/packages/login-link/src/Models/LoginLink.php @@ -2,9 +2,11 @@ namespace Moox\LoginLink\Models; +use App\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Str; +use Override; class LoginLink extends Model { @@ -35,11 +37,12 @@ public function __construct(array $attributes = []) // ]; } + #[Override] protected static function boot() { parent::boot(); - LoginLink::creating(function ($item) { + LoginLink::creating(function ($item): void { if (empty($item->token)) { $item->token = Str::random(40); } @@ -53,10 +56,10 @@ protected static function boot() */ public function user(): BelongsTo { - if (isset($this->user_type)) { + if (property_exists($this, 'user_type') && $this->user_type !== null) { return $this->belongsTo($this->user_type, 'user_id'); } else { - return $this->belongsTo('App\Models\User', 'user_id'); + return $this->belongsTo(User::class, 'user_id'); } } } diff --git a/packages/login-link/src/Resources/LoginLinkResource.php b/packages/login-link/src/Resources/LoginLinkResource.php index 7967c0698..330f7c3ef 100644 --- a/packages/login-link/src/Resources/LoginLinkResource.php +++ b/packages/login-link/src/Resources/LoginLinkResource.php @@ -19,15 +19,18 @@ use Moox\LoginLink\Models\LoginLink; use Moox\LoginLink\Resources\LoginLinkResource\Pages\ListPage; use Moox\LoginLink\Resources\LoginLinkResource\Widgets\LoginLinkWidgets; +use Override; class LoginLinkResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = LoginLink::class; protected static ?string $navigationIcon = 'gmdi-lock-clock-o'; + #[Override] public static function form(Form $form): Form { return $form @@ -52,13 +55,13 @@ public static function form(Form $form): Form ->label(__('core::core.used_at')), Select::make('user_type') ->label(__('core::user.user_type')) - ->options(function () { + ->options(function (): array { $models = Config::get('login-link.user_models', []); return array_flip($models); }) ->reactive() - ->afterStateUpdated(function (Set $set, $state) { + ->afterStateUpdated(function (Set $set, $state): void { $set('user_id', null); }) ->required(), @@ -77,6 +80,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -84,10 +88,10 @@ public static function table(Table $table): Table IconColumn::make('used') ->label(__('core::core.valid')) ->icons([ - 'heroicon-o-x-circle' => fn ($record) => empty($record->used_at), - 'heroicon-o-check-circle' => fn ($record) => ! empty($record->used_at), + 'heroicon-o-x-circle' => fn ($record): bool => empty($record->used_at), + 'heroicon-o-check-circle' => fn ($record): bool => ! empty($record->used_at), ]) - ->tooltip(fn ($record) => empty($record->used_at) ? 'Not Used' : 'Used') + ->tooltip(fn ($record): string => empty($record->used_at) ? 'Not Used' : 'Used') ->sortable(), TextColumn::make('email') ->label(__('core::user.email')) @@ -109,9 +113,7 @@ public static function table(Table $table): Table ->sortable(), TextColumn::make('user_id') ->label(__('core::user.user_id')) - ->getStateUsing(function ($record) { - return optional($record->user)->name ?? 'unknown'; - }) + ->getStateUsing(fn ($record) => optional($record->user)->name ?? 'unknown') ->sortable(), ]) ->actions([ @@ -122,6 +124,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -129,6 +132,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -136,6 +140,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -143,36 +148,43 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return config('login-link.resources.login-link.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('login-link.resources.login-link.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('login-link.resources.login-link.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('login-link.resources.login-link.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return config('login-link.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('login-link.navigation_sort') + 4; diff --git a/packages/login-link/src/Resources/LoginLinkResource/Pages/ListPage.php b/packages/login-link/src/Resources/LoginLinkResource/Pages/ListPage.php index bae0013c5..5b8288266 100644 --- a/packages/login-link/src/Resources/LoginLinkResource/Pages/ListPage.php +++ b/packages/login-link/src/Resources/LoginLinkResource/Pages/ListPage.php @@ -8,6 +8,7 @@ use Moox\LoginLink\Models\LoginLink; use Moox\LoginLink\Resources\LoginLinkResource; use Moox\LoginLink\Resources\LoginLinkResource\Widgets\LoginLinkWidgets; +use Override; class ListPage extends ListRecords { @@ -15,18 +16,20 @@ class ListPage extends ListRecords public static string $resource = LoginLinkResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ LoginLinkWidgets::class, ]; } + #[Override] public function getTitle(): string { return __('login-link::translations.title'); @@ -36,9 +39,7 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): LoginLink { - return $model::create($data); - }), + ->using(fn (array $data, string $model): LoginLink => $model::create($data)), ]; } diff --git a/packages/login-link/src/Resources/LoginLinkResource/Widgets/LoginLinkWidgets.php b/packages/login-link/src/Resources/LoginLinkResource/Widgets/LoginLinkWidgets.php index fa28edee1..4cfc4e093 100644 --- a/packages/login-link/src/Resources/LoginLinkResource/Widgets/LoginLinkWidgets.php +++ b/packages/login-link/src/Resources/LoginLinkResource/Widgets/LoginLinkWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\LoginLink\Models\LoginLink; +use Override; class LoginLinkWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/notifications/src/Commands/InstallCommand.php b/packages/notifications/src/Commands/InstallCommand.php index 725c9eb4a..f322e440f 100644 --- a/packages/notifications/src/Commands/InstallCommand.php +++ b/packages/notifications/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Notification config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing Notifications Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'notifications-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/notifications/src/Models/Notification.php b/packages/notifications/src/Models/Notification.php index f4da26aad..81200f719 100644 --- a/packages/notifications/src/Models/Notification.php +++ b/packages/notifications/src/Models/Notification.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; +use Override; class Notification extends Model { @@ -14,11 +15,12 @@ class Notification extends Model public $incrementing = false; + #[Override] protected static function boot() { parent::boot(); - static::creating(function ($model) { + static::creating(function ($model): void { if (empty($model->id)) { $model->id = (string) Str::uuid(); } diff --git a/packages/notifications/src/NotificationServiceProvider.php b/packages/notifications/src/NotificationServiceProvider.php index b59456b1d..c30681c52 100644 --- a/packages/notifications/src/NotificationServiceProvider.php +++ b/packages/notifications/src/NotificationServiceProvider.php @@ -23,7 +23,7 @@ public function configurePackage(Package $package): void ->hasCommand(InstallCommand::class); } - public function packageRegistered() + public function packageRegistered(): void { if (config('notifications.api')) { Route::get('/api/notifications/user/{user}/notificationBell', [NotificationController::class, 'getView']); diff --git a/packages/notifications/src/Resources/NotificationResource.php b/packages/notifications/src/Resources/NotificationResource.php index e979b4246..663ad3182 100644 --- a/packages/notifications/src/Resources/NotificationResource.php +++ b/packages/notifications/src/Resources/NotificationResource.php @@ -18,15 +18,18 @@ use Moox\Notification\Resources\NotificationResource\Pages\ListNotifications; use Moox\Notification\Resources\NotificationResource\Pages\ViewNotification; use Moox\Notification\Resources\NotificationResource\Widgets\NotificationWidgets; +use Override; class NotificationResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = Notification::class; protected static ?string $navigationIcon = 'gmdi-notifications'; + #[Override] public static function form(Form $form): Form { return $form @@ -45,6 +48,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -71,6 +75,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -78,6 +83,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -88,6 +94,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -95,26 +102,31 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return config('notifications.resources.notifications.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('notifications.resources.notifications.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('notifications.resources.notifications.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('notifications.resources.notifications.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -125,11 +137,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return config('notifications.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('notifications.navigation_sort') + 2; diff --git a/packages/notifications/src/Resources/NotificationResource/Widgets/NotificationWidgets.php b/packages/notifications/src/Resources/NotificationResource/Widgets/NotificationWidgets.php index 6764549fd..e8b954529 100644 --- a/packages/notifications/src/Resources/NotificationResource/Widgets/NotificationWidgets.php +++ b/packages/notifications/src/Resources/NotificationResource/Widgets/NotificationWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Notification\Models\Notification; +use Override; class NotificationWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/page/src/Commands/InstallCommand.php b/packages/page/src/Commands/InstallCommand.php index 72ffd7e88..7a3f41cc0 100644 --- a/packages/page/src/Commands/InstallCommand.php +++ b/packages/page/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Page config already exist. The config will not be published.'); } } @@ -125,22 +126,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -181,12 +182,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/page/src/Resources/PageResource.php b/packages/page/src/Resources/PageResource.php index 08962785d..bc974178f 100644 --- a/packages/page/src/Resources/PageResource.php +++ b/packages/page/src/Resources/PageResource.php @@ -15,6 +15,7 @@ use Moox\Page\Models\Page; use Moox\Page\Resources\PageResource\Pages\ListPage; use Moox\Page\Resources\PageResource\Widgets\PageWidgets; +use Override; class PageResource extends Resource { @@ -24,6 +25,7 @@ class PageResource extends Resource protected static ?string $navigationIcon = 'gmdi-pages'; + #[Override] public static function form(Form $form): Form { return $form @@ -37,6 +39,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -61,6 +64,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -68,6 +72,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -75,6 +80,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -82,31 +88,37 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return __('page::translations.single'); } + #[Override] public static function getPluralModelLabel(): string { return __('page::translations.plural'); } + #[Override] public static function getNavigationLabel(): string { return __('page::translations.navigation_label'); } + #[Override] public static function getNavigationGroup(): ?string { return __('page::translations.navigation_group'); } + #[Override] public static function getBreadcrumb(): string { return __('page::translations.breadcrumb'); } + #[Override] public static function getNavigationSort(): ?int { return config('page.navigation_sort'); diff --git a/packages/page/src/Resources/PageResource/Pages/ListPage.php b/packages/page/src/Resources/PageResource/Pages/ListPage.php index f4b4349fd..bc8ef5a04 100644 --- a/packages/page/src/Resources/PageResource/Pages/ListPage.php +++ b/packages/page/src/Resources/PageResource/Pages/ListPage.php @@ -7,23 +7,26 @@ use Moox\Page\Models\Page; use Moox\Page\Resources\PageResource; use Moox\Page\Resources\PageResource\Widgets\PageWidgets; +use Override; class ListPage extends ListRecords { public static string $resource = PageResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ PageWidgets::class, ]; } + #[Override] public function getTitle(): string { return __('page::translations.title'); @@ -33,9 +36,7 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Page { - return $model::create($data); - }), + ->using(fn (array $data, string $model): Page => $model::create($data)), ]; } } diff --git a/packages/page/src/Resources/PageResource/Widgets/PageWidgets.php b/packages/page/src/Resources/PageResource/Widgets/PageWidgets.php index 83d11536f..cb23d3e4c 100644 --- a/packages/page/src/Resources/PageResource/Widgets/PageWidgets.php +++ b/packages/page/src/Resources/PageResource/Widgets/PageWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Page\Models\Page; +use Override; class PageWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/passkey/config/passkey.php b/packages/passkey/config/passkey.php index eb47530e3..b6df1affc 100644 --- a/packages/passkey/config/passkey.php +++ b/packages/passkey/config/passkey.php @@ -1,5 +1,8 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, 'Moox Users' => \Moox\User\Models\User::class, ], @@ -111,6 +113,6 @@ | */ - 'device_model' => \Moox\UserDevice\Models\UserDevice::class, + 'device_model' => UserDevice::class, ]; diff --git a/packages/passkey/src/Commands/InstallCommand.php b/packages/passkey/src/Commands/InstallCommand.php index fd6055e90..82e8ba61b 100644 --- a/packages/passkey/src/Commands/InstallCommand.php +++ b/packages/passkey/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Passkey config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing Passkeys Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'passkey-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/passkey/src/Models/Passkey.php b/packages/passkey/src/Models/Passkey.php index 5894abfff..4d1f773cf 100644 --- a/packages/passkey/src/Models/Passkey.php +++ b/packages/passkey/src/Models/Passkey.php @@ -2,8 +2,11 @@ namespace Moox\Passkey\Models; +use App\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Moox\UserDevice\Models\UserDevice; +use Moox\UserSession\Models\UserSession; class Passkey extends Model { @@ -32,10 +35,10 @@ class Passkey extends Model */ public function user(): BelongsTo { - if (isset($this->user_type)) { + if (property_exists($this, 'user_type') && $this->user_type !== null) { return $this->belongsTo($this->user_type, 'user_id'); } else { - return $this->belongsTo('App\Models\User', 'user_id'); + return $this->belongsTo(User::class, 'user_id'); } } @@ -44,7 +47,7 @@ public function user(): BelongsTo */ public function userDevice(): BelongsTo { - return $this->belongsTo('Moox\UserDevice\Models\UserDevice', 'device_id'); + return $this->belongsTo(UserDevice::class, 'device_id'); } /** @@ -52,6 +55,6 @@ public function userDevice(): BelongsTo */ public function userSession(): BelongsTo { - return $this->belongsTo('Moox\UserSession\Models\UserSession', 'session_id'); + return $this->belongsTo(UserSession::class, 'session_id'); } } diff --git a/packages/passkey/src/Resources/PasskeyResource.php b/packages/passkey/src/Resources/PasskeyResource.php index 7f5f85cee..57054abbc 100644 --- a/packages/passkey/src/Resources/PasskeyResource.php +++ b/packages/passkey/src/Resources/PasskeyResource.php @@ -18,15 +18,18 @@ use Moox\Passkey\Models\Passkey; use Moox\Passkey\Resources\PasskeyResource\Pages\ListPage; use Moox\Passkey\Resources\PasskeyResource\Widgets\PasskeyWidgets; +use Override; class PasskeyResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = Passkey::class; protected static ?string $navigationIcon = 'gmdi-fingerprint-o'; + #[Override] public static function form(Form $form): Form { return $form @@ -44,13 +47,13 @@ public static function form(Form $form): Form ->required(), Select::make('user_type') ->label(__('core::user.user_type')) - ->options(function () { + ->options(function (): array { $models = Config::get('login-link.user_models', []); return array_flip($models); }) ->reactive() - ->afterStateUpdated(function (Set $set, $state) { + ->afterStateUpdated(function (Set $set, $state): void { $set('user_id', null); }) ->required(), @@ -75,6 +78,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -95,9 +99,7 @@ public static function table(Table $table): Table ->sortable(), TextColumn::make('user_id') ->label(__('core::user.user_id')) - ->getStateUsing(function ($record) { - return optional($record->user)->name ?? 'unknown'; - }) + ->getStateUsing(fn ($record) => optional($record->user)->name ?? 'unknown') ->sortable(), TextColumn::make('device_id') ->label(__('core::session.device_id')) @@ -115,6 +117,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -122,6 +125,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -129,6 +133,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -136,36 +141,43 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return config('passkey.resources.passkey.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('passkey.resources.passkey.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('passkey.resources.passkey.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('passkey.resources.passkey.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return config('passkey.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('passkey.navigation_sort') + 6; diff --git a/packages/passkey/src/Resources/PasskeyResource/Pages/ListPage.php b/packages/passkey/src/Resources/PasskeyResource/Pages/ListPage.php index 081892e83..4024a61a8 100644 --- a/packages/passkey/src/Resources/PasskeyResource/Pages/ListPage.php +++ b/packages/passkey/src/Resources/PasskeyResource/Pages/ListPage.php @@ -8,6 +8,7 @@ use Moox\Passkey\Models\Passkey; use Moox\Passkey\Resources\PasskeyResource; use Moox\Passkey\Resources\PasskeyResource\Widgets\PasskeyWidgets; +use Override; class ListPage extends ListRecords { @@ -15,18 +16,20 @@ class ListPage extends ListRecords public static string $resource = PasskeyResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ // PasskeyWidgets::class, ]; } + #[Override] public function getTitle(): string { return __('passkey::translations.title'); @@ -36,9 +39,7 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Passkey { - return $model::create($data); - }), + ->using(fn (array $data, string $model): Passkey => $model::create($data)), ]; } diff --git a/packages/passkey/src/Resources/PasskeyResource/Widgets/PasskeyWidgets.php b/packages/passkey/src/Resources/PasskeyResource/Widgets/PasskeyWidgets.php index 1d3dd81d2..a1aa4f2b6 100644 --- a/packages/passkey/src/Resources/PasskeyResource/Widgets/PasskeyWidgets.php +++ b/packages/passkey/src/Resources/PasskeyResource/Widgets/PasskeyWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Passkey\Models\Passkey; +use Override; class PasskeyWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/permission/config/permission.php b/packages/permission/config/permission.php index 5f0be8db0..83099c859 100644 --- a/packages/permission/config/permission.php +++ b/packages/permission/config/permission.php @@ -1,5 +1,10 @@ [ 'moox' => [ 'provider' => 'users', - 'model' => \App\Models\User::class, + 'model' => User::class, ], 'press' => [ 'provider' => 'press_users', - 'model' => \Moox\Press\Models\WpUser::class, + 'model' => WpUser::class, ], // Add more guards and user models as needed ], @@ -77,7 +80,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 @@ -88,7 +91,7 @@ * `Spatie\Permission\Contracts\Role` contract. */ - 'role' => Spatie\Permission\Models\Role::class, + 'role' => Role::class, ], @@ -231,7 +234,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. diff --git a/packages/permission/database/seeders/PressPermissionsSeeder.php b/packages/permission/database/seeders/PressPermissionsSeeder.php index 64509ef95..f74cb5170 100644 --- a/packages/permission/database/seeders/PressPermissionsSeeder.php +++ b/packages/permission/database/seeders/PressPermissionsSeeder.php @@ -9,10 +9,8 @@ class PressPermissionsSeeder extends Seeder { /** * Run the database seeds. - * - * @return void */ - public function run() + public function run(): void { $permissions = [ 'view', diff --git a/packages/permission/src/Commands/InstallCommand.php b/packages/permission/src/Commands/InstallCommand.php index 9054f432d..20f22936c 100644 --- a/packages/permission/src/Commands/InstallCommand.php +++ b/packages/permission/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Permission config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing Permissions Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'permission-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/permission/src/Policies/DefaultPolicy.php b/packages/permission/src/Policies/DefaultPolicy.php index 78699153f..a16913b30 100644 --- a/packages/permission/src/Policies/DefaultPolicy.php +++ b/packages/permission/src/Policies/DefaultPolicy.php @@ -2,6 +2,7 @@ namespace Moox\Permission\Policies; +use Exception; use Illuminate\Support\Facades\Auth; class DefaultPolicy @@ -10,12 +11,12 @@ class DefaultPolicy public function __construct($guard = null) { - $guard = $guard ?? Auth::getDefaultDriver(); + $guard ??= Auth::getDefaultDriver(); $this->user = Auth::guard($guard)->user(); if (! method_exists($this->user, 'hasPermissionTo')) { - throw new \Exception("The user object does not have the method 'hasPermissionTo'."); + throw new Exception("The user object does not have the method 'hasPermissionTo'."); } } @@ -54,22 +55,22 @@ public function publish() return $this->hasPermission('publish'); } - public function viewOwn($model) + public function viewOwn($model): bool { return $this->hasPermission('view own') && $model->user_id === $this->user->id; } - public function editOwn($model) + public function editOwn($model): bool { return $this->hasPermission('edit own') && $model->user_id === $this->user->id; } - public function deleteOwn($model) + public function deleteOwn($model): bool { return $this->hasPermission('delete own') && $model->user_id === $this->user->id; } - public function publishOwn($model) + public function publishOwn($model): bool { return $this->hasPermission('publish own') && $model->user_id === $this->user->id; } diff --git a/packages/permission/src/Resources/PermissionResource.php b/packages/permission/src/Resources/PermissionResource.php index 60a8c7fc9..e15d46e34 100644 --- a/packages/permission/src/Resources/PermissionResource.php +++ b/packages/permission/src/Resources/PermissionResource.php @@ -15,6 +15,7 @@ use Moox\Permission\Models\Permission; use Moox\Permission\Resources\PermissionResource\Pages\ListPage; use Moox\Permission\Resources\PermissionResource\Widgets\PermissionWidgets; +use Override; class PermissionResource extends Resource { @@ -24,6 +25,7 @@ class PermissionResource extends Resource protected static ?string $navigationIcon = 'gmdi-engineering'; + #[Override] public static function form(Form $form): Form { return $form @@ -37,6 +39,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -61,6 +64,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -68,6 +72,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -75,6 +80,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -82,26 +88,31 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return __('permission::translations.single'); } + #[Override] public static function getPluralModelLabel(): string { return __('permission::translations.plural'); } + #[Override] public static function getNavigationLabel(): string { return __('permission::translations.navigation_label'); } + #[Override] public static function getBreadcrumb(): string { return __('permission::translations.breadcrumb'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -112,11 +123,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return __('permission::translations.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('permission.navigation_sort'); diff --git a/packages/permission/src/Resources/PermissionResource/Pages/ListPage.php b/packages/permission/src/Resources/PermissionResource/Pages/ListPage.php index fd14dd30f..9df6e9de9 100644 --- a/packages/permission/src/Resources/PermissionResource/Pages/ListPage.php +++ b/packages/permission/src/Resources/PermissionResource/Pages/ListPage.php @@ -7,23 +7,26 @@ use Moox\Permission\Models\Permission; use Moox\Permission\Resources\PermissionResource; use Moox\Permission\Resources\PermissionResource\Widgets\PermissionWidgets; +use Override; class ListPage extends ListRecords { public static string $resource = PermissionResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ PermissionWidgets::class, ]; } + #[Override] public function getTitle(): string { return __('permission::translations.title'); @@ -33,9 +36,7 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Permission { - return $model::create($data); - }), + ->using(fn (array $data, string $model): Permission => $model::create($data)), ]; } } diff --git a/packages/permission/src/Resources/PermissionResource/Widgets/PermissionWidgets.php b/packages/permission/src/Resources/PermissionResource/Widgets/PermissionWidgets.php index d34c0d652..d8dde3845 100644 --- a/packages/permission/src/Resources/PermissionResource/Widgets/PermissionWidgets.php +++ b/packages/permission/src/Resources/PermissionResource/Widgets/PermissionWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\Permission\Models\Permission; +use Override; class PermissionWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/press-trainings/src/Commands/InstallCommand.php b/packages/press-trainings/src/Commands/InstallCommand.php index bf0ed1d4e..358dfdd86 100644 --- a/packages/press-trainings/src/Commands/InstallCommand.php +++ b/packages/press-trainings/src/Commands/InstallCommand.php @@ -31,7 +31,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -75,6 +75,7 @@ public function publishConfiguration(): void return; } + warning('The PressTrainings config already exist. The config will not be published.'); } } @@ -102,22 +103,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -158,12 +159,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/press-trainings/src/Models/WpTopic.php b/packages/press-trainings/src/Models/WpTopic.php index 1e9b0d165..215f5a92a 100644 --- a/packages/press-trainings/src/Models/WpTopic.php +++ b/packages/press-trainings/src/Models/WpTopic.php @@ -4,15 +4,17 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpTerm; +use Override; class WpTopic extends WpTerm { - public static function boot() + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('thema', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('thema', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'thema'); }); }); diff --git a/packages/press-trainings/src/Models/WpTraining.php b/packages/press-trainings/src/Models/WpTraining.php index 69add5fff..f2befed9c 100644 --- a/packages/press-trainings/src/Models/WpTraining.php +++ b/packages/press-trainings/src/Models/WpTraining.php @@ -4,14 +4,16 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpBasePost; +use Override; class WpTraining extends WpBasePost { - public static function boot() + #[Override] + protected static function boot() { parent::boot(); - static::addGlobalScope('training', function (Builder $builder) { + static::addGlobalScope('training', function (Builder $builder): void { $builder ->where('post_type', 'schulung') ->whereIn('post_status', ['publish', 'draft', 'pending', 'trash', 'future', 'private']) diff --git a/packages/press-trainings/src/Models/WpTrainingsTopic.php b/packages/press-trainings/src/Models/WpTrainingsTopic.php index b8fc1bee3..63931978e 100644 --- a/packages/press-trainings/src/Models/WpTrainingsTopic.php +++ b/packages/press-trainings/src/Models/WpTrainingsTopic.php @@ -4,15 +4,17 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpTerm; +use Override; class WpTrainingsTopic extends WpTerm { - public static function boot() + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('schulungen', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('schulungen', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'schulungen_rubrik'); }); }); diff --git a/packages/press-trainings/src/Resources/WpTopicResource.php b/packages/press-trainings/src/Resources/WpTopicResource.php index 817f4f5a7..01821ccb1 100644 --- a/packages/press-trainings/src/Resources/WpTopicResource.php +++ b/packages/press-trainings/src/Resources/WpTopicResource.php @@ -7,14 +7,18 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressWiki\Models\WpTopic; -use Moox\PressWiki\Resources\WpTopicResource\Pages; +use Moox\PressWiki\Resources\WpTopicResource\Pages\CreateWpTopic; +use Moox\PressWiki\Resources\WpTopicResource\Pages\EditWpTopic; +use Moox\PressWiki\Resources\WpTopicResource\Pages\ListWpTopics; +use Moox\PressWiki\Resources\WpTopicResource\Pages\ViewWpTopic; +use Override; class WpTopicResource extends Resource { @@ -26,6 +30,7 @@ class WpTopicResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -66,22 +71,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -91,46 +97,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTopics::route('/'), - 'create' => Pages\CreateWpTopic::route('/create'), - 'view' => Pages\ViewWpTopic::route('/{record}'), - 'edit' => Pages\EditWpTopic::route('/{record}/edit'), + 'index' => ListWpTopics::route('/'), + 'create' => CreateWpTopic::route('/create'), + 'view' => ViewWpTopic::route('/{record}'), + 'edit' => EditWpTopic::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-wiki.resources.topic.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-wiki.resources.topic.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-wiki.resources.topic.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-wiki.resources.topic.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-wiki.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-wiki.temp_navigation_sort') + 3; diff --git a/packages/press-trainings/src/Resources/WpTrainingResource.php b/packages/press-trainings/src/Resources/WpTrainingResource.php index 975cff040..d162f110e 100644 --- a/packages/press-trainings/src/Resources/WpTrainingResource.php +++ b/packages/press-trainings/src/Resources/WpTrainingResource.php @@ -9,19 +9,25 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\DeleteBulkAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressTrainings\Models\WpTraining; -use Moox\PressTrainings\Resources\WpTrainingResource\Pages; -use Moox\PressTrainings\Resources\WpTrainingResource\RelationManagers; +use Moox\PressTrainings\Resources\WpTrainingResource\Pages\CreateWpTraining; +use Moox\PressTrainings\Resources\WpTrainingResource\Pages\EditWpTraining; +use Moox\PressTrainings\Resources\WpTrainingResource\Pages\ListWpTrainings; +use Moox\PressTrainings\Resources\WpTrainingResource\Pages\ViewWpTraining; +use Moox\PressTrainings\Resources\WpTrainingResource\RelationManagers\WpCommentRelationManager; +use Moox\PressTrainings\Resources\WpTrainingResource\RelationManagers\WpTrainingMetaRelationManager; +use Override; class WpTrainingResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpTraining::class; @@ -29,6 +35,7 @@ class WpTrainingResource extends Resource protected static ?string $recordTitleAttribute = 'post_title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -270,76 +277,85 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_title') + TextColumn::make('post_title') ->label(__('core::post.post_title')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('trainingsTopic.name') + TextColumn::make('trainingsTopic.name') ->label('Schulung Rubrik') ->sortable() ->searchable(), - Tables\Columns\TextColumn::make('post_date') + TextColumn::make('post_date') ->label(__('core::post.post_date')) ->toggleable() ->dateTime(), ]) ->actions([ - Action::make('Edit')->url(fn ($record): string => "/wp/wp-admin/post.php?post={$record->ID}&action=edit"), + Action::make('Edit')->url(fn ($record): string => sprintf('/wp/wp-admin/post.php?post=%s&action=edit', $record->ID)), ]) ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ - RelationManagers\WpTrainingMetaRelationManager::class, - RelationManagers\WpCommentRelationManager::class, + WpTrainingMetaRelationManager::class, + WpCommentRelationManager::class, ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTrainings::route('/'), - 'create' => Pages\CreateWpTraining::route('/create'), - 'view' => Pages\ViewWpTraining::route('/{record}'), - 'edit' => Pages\EditWpTraining::route('/{record}/edit'), + 'index' => ListWpTrainings::route('/'), + 'create' => CreateWpTraining::route('/create'), + 'view' => ViewWpTraining::route('/{record}'), + 'edit' => EditWpTraining::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-trainings.resources.trainings.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-trainings.resources.trainings.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-trainings.resources.trainings.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-trainings.resources.trainings.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-trainings.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-trainings.temp_navigation_sort') + 4; diff --git a/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpCommentRelationManager.php b/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpCommentRelationManager.php index a5efce39d..70409c8d5 100644 --- a/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpCommentRelationManager.php +++ b/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpCommentRelationManager.php @@ -9,11 +9,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpCommentRelationManager extends RelationManager { @@ -21,6 +22,7 @@ class WpCommentRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -184,69 +186,69 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('comment_post_ID') + TextColumn::make('comment_post_ID') ->label(__('core::comment.comment_post_ID')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author') + TextColumn::make('comment_author') ->label(__('core::comment.comment_author')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_author_email') + TextColumn::make('comment_author_email') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_url') + TextColumn::make('comment_author_url') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_IP') + TextColumn::make('comment_author_IP') ->label(__('core::comment.comment_author_IP')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_date') + TextColumn::make('comment_date') ->label(__('core::comment.comment_date')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_date_gmt') + TextColumn::make('comment_date_gmt') ->label(__('core::comment.comment_date_gmt')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_content') + TextColumn::make('comment_content') ->label(__('core::comment.comment_contet')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_karma') + TextColumn::make('comment_karma') ->label(__('core::comment.comment_karma')) ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('comment_approved') + TextColumn::make('comment_approved') ->label(__('core::comment.comment_approved')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_agent') + TextColumn::make('comment_agent') ->label(__('core::comment.comment_agent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_type') + TextColumn::make('comment_type') ->label(__('core::comment.comment_type')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_parent') + TextColumn::make('comment_parent') ->label(__('core::comment.comment_parent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('user_id') + TextColumn::make('user_id') ->label(__('core::user.user_id')) ->toggleable() ->searchable(true, null, true) diff --git a/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpTrainingMetaRelationManager.php b/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpTrainingMetaRelationManager.php index 14815424a..80380e7e2 100644 --- a/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpTrainingMetaRelationManager.php +++ b/packages/press-trainings/src/Resources/WpTrainingResource/RelationManagers/WpTrainingMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpTrainingMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpTrainingMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,17 +67,17 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_id') + TextColumn::make('post_id') ->label(__('core::post.post_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpCommentRelationManager.php b/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpCommentRelationManager.php index beb4ada52..ad08d3e4b 100644 --- a/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpCommentRelationManager.php +++ b/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpCommentRelationManager.php @@ -9,11 +9,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpCommentRelationManager extends RelationManager { @@ -21,6 +22,7 @@ class WpCommentRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -184,69 +186,69 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('comment_post_ID') + TextColumn::make('comment_post_ID') ->label(__('core::comment.comment_post_ID')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author') + TextColumn::make('comment_author') ->label(__('core::comment.comment_author')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_author_email') + TextColumn::make('comment_author_email') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_url') + TextColumn::make('comment_author_url') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_IP') + TextColumn::make('comment_author_IP') ->label(__('core::comment.comment_author_IP')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_date') + TextColumn::make('comment_date') ->label(__('core::comment.comment_date')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_date_gmt') + TextColumn::make('comment_date_gmt') ->label(__('core::comment.comment_date_gmt')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_content') + TextColumn::make('comment_content') ->label(__('core::comment.comment_contet')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_karma') + TextColumn::make('comment_karma') ->label(__('core::comment.comment_karma')) ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('comment_approved') + TextColumn::make('comment_approved') ->label(__('core::comment.comment_approved')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_agent') + TextColumn::make('comment_agent') ->label(__('core::comment.comment_agent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_type') + TextColumn::make('comment_type') ->label(__('core::comment.comment_type')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_parent') + TextColumn::make('comment_parent') ->label(__('core::comment.comment_parent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('user_id') + TextColumn::make('user_id') ->label(__('core::user.user_id')) ->toggleable() ->searchable(true, null, true) diff --git a/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpPostMetaRelationManager.php b/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpPostMetaRelationManager.php index f4e4dff36..8a6e70251 100644 --- a/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpPostMetaRelationManager.php +++ b/packages/press-trainings/src/Resources/WpTrainingsResource/RelationManagers/WpPostMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpPostMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpPostMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,17 +67,17 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_id') + TextColumn::make('post_id') ->label(__('core::post.post_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press-trainings/src/Resources/WpTrainingsTopicResource.php b/packages/press-trainings/src/Resources/WpTrainingsTopicResource.php index f45d391ac..75ae42c97 100644 --- a/packages/press-trainings/src/Resources/WpTrainingsTopicResource.php +++ b/packages/press-trainings/src/Resources/WpTrainingsTopicResource.php @@ -7,19 +7,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressTrainings\Models\WpTrainingsTopic; -use Moox\PressTrainings\Resources\WpTrainingsTopicResource\Pages; +use Moox\PressTrainings\Resources\WpTrainingsTopicResource\Pages\CreateWpTrainingsTopic; +use Moox\PressTrainings\Resources\WpTrainingsTopicResource\Pages\EditWpTrainingsTopic; +use Moox\PressTrainings\Resources\WpTrainingsTopicResource\Pages\ListWpTrainingsTopics; +use Moox\PressTrainings\Resources\WpTrainingsTopicResource\Pages\ViewWpTrainingsTopic; +use Override; class WpTrainingsTopicResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpTrainingsTopic::class; @@ -27,6 +32,7 @@ class WpTrainingsTopicResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -67,22 +73,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -92,46 +99,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTrainingsTopics::route('/'), - 'create' => Pages\CreateWpTrainingsTopic::route('/create'), - 'view' => Pages\ViewWpTrainingsTopic::route('/{record}'), - 'edit' => Pages\EditWpTrainingsTopic::route('/{record}/edit'), + 'index' => ListWpTrainingsTopics::route('/'), + 'create' => CreateWpTrainingsTopic::route('/create'), + 'view' => ViewWpTrainingsTopic::route('/{record}'), + 'edit' => EditWpTrainingsTopic::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-trainings.resources.trainings-topic.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-trainings.resources.trainings-topic.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-trainings.resources.trainings-topic.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-trainings.resources.trainings-topic.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-trainings.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-trainings.temp_navigation_sort') + 3; diff --git a/packages/press-wiki/src/Commands/InstallCommand.php b/packages/press-wiki/src/Commands/InstallCommand.php index 3d9ebd431..c4a67f532 100644 --- a/packages/press-wiki/src/Commands/InstallCommand.php +++ b/packages/press-wiki/src/Commands/InstallCommand.php @@ -31,7 +31,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -75,6 +75,7 @@ public function publishConfiguration(): void return; } + warning('The PressWiki config already exist. The config will not be published.'); } } @@ -102,22 +103,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -158,12 +159,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/press-wiki/src/Models/WpWiki.php b/packages/press-wiki/src/Models/WpWiki.php index ca83f2d7d..8b6a7f8dd 100644 --- a/packages/press-wiki/src/Models/WpWiki.php +++ b/packages/press-wiki/src/Models/WpWiki.php @@ -4,14 +4,16 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpBasePost; +use Override; class WpWiki extends WpBasePost { - public static function boot() + #[Override] + protected static function boot() { parent::boot(); - static::addGlobalScope('wiki', function (Builder $builder) { + static::addGlobalScope('wiki', function (Builder $builder): void { $builder ->where('post_type', 'wiki') ->whereIn('post_status', ['publish', 'draft', 'pending', 'trash', 'future', 'private']) diff --git a/packages/press-wiki/src/Models/WpWikiCompanyTopic.php b/packages/press-wiki/src/Models/WpWikiCompanyTopic.php index e7b1f8b65..6ef7491b7 100644 --- a/packages/press-wiki/src/Models/WpWikiCompanyTopic.php +++ b/packages/press-wiki/src/Models/WpWikiCompanyTopic.php @@ -4,15 +4,17 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpTerm; +use Override; class WpWikiCompanyTopic extends WpTerm { - public static function boot() + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('company', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('company', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'wiki_firmen'); }); }); diff --git a/packages/press-wiki/src/Models/WpWikiDepartmentTopic.php b/packages/press-wiki/src/Models/WpWikiDepartmentTopic.php index 679b29234..b44a9d374 100644 --- a/packages/press-wiki/src/Models/WpWikiDepartmentTopic.php +++ b/packages/press-wiki/src/Models/WpWikiDepartmentTopic.php @@ -4,15 +4,17 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpTerm; +use Override; class WpWikiDepartmentTopic extends WpTerm { - public static function boot() + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('department', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('department', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'bereiche'); }); }); diff --git a/packages/press-wiki/src/Models/WpWikiLetterTopic.php b/packages/press-wiki/src/Models/WpWikiLetterTopic.php index 0a6510ef8..b44f14542 100644 --- a/packages/press-wiki/src/Models/WpWikiLetterTopic.php +++ b/packages/press-wiki/src/Models/WpWikiLetterTopic.php @@ -4,15 +4,17 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpTerm; +use Override; class WpWikiLetterTopic extends WpTerm { - public static function boot() + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('letter', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('letter', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'letter'); }); }); diff --git a/packages/press-wiki/src/Models/WpWikiLocationTopic.php b/packages/press-wiki/src/Models/WpWikiLocationTopic.php index a2a3ee02e..fa59f9180 100644 --- a/packages/press-wiki/src/Models/WpWikiLocationTopic.php +++ b/packages/press-wiki/src/Models/WpWikiLocationTopic.php @@ -4,15 +4,17 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpTerm; +use Override; class WpWikiLocationTopic extends WpTerm { - public static function boot() + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('location', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('location', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'standorte'); }); }); diff --git a/packages/press-wiki/src/Models/WpWikiTopic.php b/packages/press-wiki/src/Models/WpWikiTopic.php index d960214ca..7996cc0f0 100644 --- a/packages/press-wiki/src/Models/WpWikiTopic.php +++ b/packages/press-wiki/src/Models/WpWikiTopic.php @@ -4,15 +4,17 @@ use Illuminate\Database\Eloquent\Builder; use Moox\Press\Models\WpTerm; +use Override; class WpWikiTopic extends WpTerm { - public static function boot() + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('topic', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('topic', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'thema'); }); }); diff --git a/packages/press-wiki/src/Resources/WpWikiCompanyTopicResource.php b/packages/press-wiki/src/Resources/WpWikiCompanyTopicResource.php index b686fe0a9..1e8f82f19 100644 --- a/packages/press-wiki/src/Resources/WpWikiCompanyTopicResource.php +++ b/packages/press-wiki/src/Resources/WpWikiCompanyTopicResource.php @@ -7,19 +7,22 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressWiki\Models\WpWikiCompanyTopic; use Moox\PressWiki\Resources\WpWikiCompanyTopicResource\Pages; +use Moox\PressWiki\Resources\WpWikiCompanyTopicResource\Pages\ListWpWikiCompanyTopics; +use Override; class WpWikiCompanyTopicResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpWikiCompanyTopic::class; @@ -27,6 +30,7 @@ class WpWikiCompanyTopicResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -67,22 +71,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -92,46 +97,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpWikiCompanyTopics::route('/'), + 'index' => ListWpWikiCompanyTopics::route('/'), // 'create' => Pages\CreateWpWikiCompanyTopic::route('/create'), // 'view' => Pages\ViewWpWikiCompanyTopic::route('/{record}'), // 'edit' => Pages\EditWpWikiCompanyTopic::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-wiki.resources.wiki-company-topic.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-wiki.resources.wiki-company-topic.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-wiki.resources.wiki-company-topic.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-wiki.resources.wiki-company-topic.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-wiki.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-wiki.temp_navigation_sort') + 3; diff --git a/packages/press-wiki/src/Resources/WpWikiDepartmentTopicResource.php b/packages/press-wiki/src/Resources/WpWikiDepartmentTopicResource.php index 81f8ff925..addaf295d 100644 --- a/packages/press-wiki/src/Resources/WpWikiDepartmentTopicResource.php +++ b/packages/press-wiki/src/Resources/WpWikiDepartmentTopicResource.php @@ -7,19 +7,22 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressWiki\Models\WpWikiDepartmentTopic; use Moox\PressWiki\Resources\WpWikiDepartmentTopicResource\Pages; +use Moox\PressWiki\Resources\WpWikiDepartmentTopicResource\Pages\ListWpWikiDepartmentTopics; +use Override; class WpWikiDepartmentTopicResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpWikiDepartmentTopic::class; @@ -27,6 +30,7 @@ class WpWikiDepartmentTopicResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -67,22 +71,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -92,46 +97,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpWikiDepartmentTopics::route('/'), + 'index' => ListWpWikiDepartmentTopics::route('/'), // 'create' => Pages\CreateWpWikiDepartmentTopic::route('/create'), // 'view' => Pages\ViewWpWikiDepartmentTopic::route('/{record}'), // 'edit' => Pages\EditWpWikiDepartmentTopic::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-wiki.resources.wiki-department-topic.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-wiki.resources.wiki-department-topic.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-wiki.resources.wiki-department-topic.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-wiki.resources.wiki-department-topic.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-wiki.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-wiki.temp_navigation_sort') + 3; diff --git a/packages/press-wiki/src/Resources/WpWikiLetterTopicResource.php b/packages/press-wiki/src/Resources/WpWikiLetterTopicResource.php index 4a0e268a6..f09ad1672 100644 --- a/packages/press-wiki/src/Resources/WpWikiLetterTopicResource.php +++ b/packages/press-wiki/src/Resources/WpWikiLetterTopicResource.php @@ -7,19 +7,22 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressWiki\Models\WpWikiLetterTopic; use Moox\PressWiki\Resources\WpWikiLetterTopicResource\Pages; +use Moox\PressWiki\Resources\WpWikiLetterTopicResource\Pages\ListWpWikiLetterTopics; +use Override; class WpWikiLetterTopicResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpWikiLetterTopic::class; @@ -27,6 +30,7 @@ class WpWikiLetterTopicResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -67,22 +71,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -92,46 +97,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpWikiLetterTopics::route('/'), + 'index' => ListWpWikiLetterTopics::route('/'), // 'create' => Pages\CreateWpWikiLetterTopic::route('/create'), // 'view' => Pages\ViewWpWikiLetterTopic::route('/{record}'), // 'edit' => Pages\EditWpWikiLetterTopic::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-wiki.resources.wiki-letter-topic.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-wiki.resources.wiki-letter-topic.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-wiki.resources.wiki-letter-topic.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-wiki.resources.wiki-letter-topic.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-wiki.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-wiki.temp_navigation_sort') + 3; diff --git a/packages/press-wiki/src/Resources/WpWikiLocationTopicResource.php b/packages/press-wiki/src/Resources/WpWikiLocationTopicResource.php index ac5676575..a8246f016 100644 --- a/packages/press-wiki/src/Resources/WpWikiLocationTopicResource.php +++ b/packages/press-wiki/src/Resources/WpWikiLocationTopicResource.php @@ -7,19 +7,22 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressWiki\Models\WpWikiLocationTopic; use Moox\PressWiki\Resources\WpWikiLocationTopicResource\Pages; +use Moox\PressWiki\Resources\WpWikiLocationTopicResource\Pages\ListWpWikiLocationTopics; +use Override; class WpWikiLocationTopicResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpWikiLocationTopic::class; @@ -27,6 +30,7 @@ class WpWikiLocationTopicResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -67,22 +71,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -92,46 +97,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpWikiLocationTopics::route('/'), + 'index' => ListWpWikiLocationTopics::route('/'), // 'create' => Pages\CreateWpWikiLocationTopic::route('/create'), // 'view' => Pages\ViewWpWikiLocationTopic::route('/{record}'), // 'edit' => Pages\EditWpWikiLocationTopic::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-wiki.resources.wiki-location-topic.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-wiki.resources.wiki-location-topic.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-wiki.resources.wiki-location-topic.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-wiki.resources.wiki-location-topic.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-wiki.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-wiki.temp_navigation_sort') + 3; diff --git a/packages/press-wiki/src/Resources/WpWikiResource.php b/packages/press-wiki/src/Resources/WpWikiResource.php index a07419837..5f9cf857b 100644 --- a/packages/press-wiki/src/Resources/WpWikiResource.php +++ b/packages/press-wiki/src/Resources/WpWikiResource.php @@ -9,20 +9,23 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\DeleteBulkAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressWiki\Models\WpWiki; use Moox\PressWiki\Resources\WpWikiResource\Pages; +use Moox\PressWiki\Resources\WpWikiResource\Pages\ListWpWikis; use Moox\PressWiki\Resources\WpWikiResource\RelationManagers\WpCommentRelationManager; use Moox\PressWiki\Resources\WpWikiResource\RelationManagers\WpPostMetaRelationManager; +use Override; class WpWikiResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpWiki::class; @@ -30,6 +33,7 @@ class WpWikiResource extends Resource protected static ?string $recordTitleAttribute = 'post_title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -272,44 +276,46 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_title') + TextColumn::make('post_title') ->label(__('core::post.post_title')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('author.display_name') + TextColumn::make('author.display_name') ->label(__('core::post.post_author')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('departmentTopics.name') + TextColumn::make('departmentTopics.name') ->label(__('press-wiki::translations.wiki-department-topics')), - Tables\Columns\TextColumn::make('letterTopics.name') + TextColumn::make('letterTopics.name') ->label(__('press-wiki::translations.wiki-letter-topics')) ->alignCenter(), - Tables\Columns\TextColumn::make('companyTopics.name') + TextColumn::make('companyTopics.name') ->label(__('press-wiki::translations.wiki-company-topics')), - Tables\Columns\TextColumn::make('locationTopics.name') + TextColumn::make('locationTopics.name') ->label(__('press-wiki::translations.wiki-location-topics')), - Tables\Columns\TextColumn::make('wikiTopics.name') + TextColumn::make('wikiTopics.name') ->label(__('press-wiki::translations.wiki-topics')), - Tables\Columns\TextColumn::make('post_date') + TextColumn::make('post_date') ->label(__('core::post.post_date')) ->toggleable() ->dateTime() ->sortable(), ]) ->actions([ - Action::make('Edit')->url(fn ($record): string => "/wp/wp-admin/post.php?post={$record->ID}&action=edit"), + Action::make('Edit')->url(fn ($record): string => sprintf('/wp/wp-admin/post.php?post=%s&action=edit', $record->ID)), ]) ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ @@ -318,41 +324,48 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpWikis::route('/'), + 'index' => ListWpWikis::route('/'), // 'create' => Pages\CreateWpWiki::route('/create'), // 'view' => Pages\ViewWpWiki::route('/{record}'), // 'edit' => Pages\EditWpWiki::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-wiki.resources.wiki.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-wiki.resources.wiki.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-wiki.resources.wiki.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-wiki.resources.wiki.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-wiki.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-wiki.temp_navigation_sort'); diff --git a/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpCommentRelationManager.php b/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpCommentRelationManager.php index beb4ada52..ad08d3e4b 100644 --- a/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpCommentRelationManager.php +++ b/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpCommentRelationManager.php @@ -9,11 +9,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpCommentRelationManager extends RelationManager { @@ -21,6 +22,7 @@ class WpCommentRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -184,69 +186,69 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('comment_post_ID') + TextColumn::make('comment_post_ID') ->label(__('core::comment.comment_post_ID')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author') + TextColumn::make('comment_author') ->label(__('core::comment.comment_author')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_author_email') + TextColumn::make('comment_author_email') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_url') + TextColumn::make('comment_author_url') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_IP') + TextColumn::make('comment_author_IP') ->label(__('core::comment.comment_author_IP')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_date') + TextColumn::make('comment_date') ->label(__('core::comment.comment_date')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_date_gmt') + TextColumn::make('comment_date_gmt') ->label(__('core::comment.comment_date_gmt')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_content') + TextColumn::make('comment_content') ->label(__('core::comment.comment_contet')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_karma') + TextColumn::make('comment_karma') ->label(__('core::comment.comment_karma')) ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('comment_approved') + TextColumn::make('comment_approved') ->label(__('core::comment.comment_approved')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_agent') + TextColumn::make('comment_agent') ->label(__('core::comment.comment_agent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_type') + TextColumn::make('comment_type') ->label(__('core::comment.comment_type')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_parent') + TextColumn::make('comment_parent') ->label(__('core::comment.comment_parent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('user_id') + TextColumn::make('user_id') ->label(__('core::user.user_id')) ->toggleable() ->searchable(true, null, true) diff --git a/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpPostMetaRelationManager.php b/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpPostMetaRelationManager.php index f4e4dff36..8a6e70251 100644 --- a/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpPostMetaRelationManager.php +++ b/packages/press-wiki/src/Resources/WpWikiResource/RelationManagers/WpPostMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpPostMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpPostMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,17 +67,17 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_id') + TextColumn::make('post_id') ->label(__('core::post.post_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press-wiki/src/Resources/WpWikiTopicResource.php b/packages/press-wiki/src/Resources/WpWikiTopicResource.php index 1a670019a..df2969f63 100644 --- a/packages/press-wiki/src/Resources/WpWikiTopicResource.php +++ b/packages/press-wiki/src/Resources/WpWikiTopicResource.php @@ -7,19 +7,22 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\PressWiki\Models\WpWikiTopic; use Moox\PressWiki\Resources\WpWikiTopicResource\Pages; +use Moox\PressWiki\Resources\WpWikiTopicResource\Pages\ListWpWikiTopics; +use Override; class WpWikiTopicResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpWikiTopic::class; @@ -27,6 +30,7 @@ class WpWikiTopicResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -67,22 +71,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -92,46 +97,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpWikiTopics::route('/'), + 'index' => ListWpWikiTopics::route('/'), // 'create' => Pages\CreateWpWikiTopic::route('/create'), // 'view' => Pages\ViewWpWikiTopic::route('/{record}'), // 'edit' => Pages\EditWpWikiTopic::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press-wiki.resources.wiki-topic.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press-wiki.resources.wiki-topic.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press-wiki.resources.wiki-topic.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press-wiki.resources.wiki-topic.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press-wiki.temp_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press-wiki.temp_navigation_sort') + 3; diff --git a/packages/press/config/press.php b/packages/press/config/press.php index e9114e7dd..e8eaa96ad 100644 --- a/packages/press/config/press.php +++ b/packages/press/config/press.php @@ -1,5 +1,8 @@ Moox\Press\Models\WpUser::class, + 'wpModel' => WpUser::class, /* |-------------------------------------------------------------------------- @@ -1272,7 +1274,7 @@ 'password' => [ 'validation' => [ - 'rules' => Illuminate\Validation\Rules\Password::min(20) + 'rules' => Password::min(20) ->max(64) ->mixedCase() ->numbers() diff --git a/packages/press/database/factories/WpUserFactory.php b/packages/press/database/factories/WpUserFactory.php index 349186a98..41d1435e3 100644 --- a/packages/press/database/factories/WpUserFactory.php +++ b/packages/press/database/factories/WpUserFactory.php @@ -3,6 +3,7 @@ namespace Moox\Press\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; +use Illuminate\Database\Eloquent\Model; use Moox\Press\Models\WpUser; use Moox\Security\Helper\PasswordHash; @@ -11,7 +12,7 @@ class WpUserFactory extends Factory /** * The name of the factory's corresponding model. * - * @var class-string<\Illuminate\Database\Eloquent\Model> + * @var class-string */ protected $model = WpUser::class; @@ -38,7 +39,7 @@ public function definition(): array ]; } - public function generatePassword($length = 12) + public function generatePassword($length = 12): string { // Define the character set for the password $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_'; diff --git a/packages/press/routes/api.php b/packages/press/routes/api.php index a7f4eaf00..43ac27bed 100644 --- a/packages/press/routes/api.php +++ b/packages/press/routes/api.php @@ -9,14 +9,11 @@ if ($config['enabled']) { $middleware = []; if (! $config['public']) { - if ($config['auth_type'] === 'platform') { - $middleware[] = 'auth.platformtoken'; - } else { - $middleware[] = 'auth:sanctum'; - } + $middleware[] = $config['auth_type'] === 'platform' ? 'auth.platformtoken' : 'auth:sanctum'; } - Route::middleware($middleware)->group(function () use ($entity) { - Route::apiResource("/$entity/wpuser", WpUserController::class)->only(config('press.entities.wp_users.api.route_only')); + + Route::middleware($middleware)->group(function () use ($entity): void { + Route::apiResource(sprintf('/%s/wpuser', $entity), WpUserController::class)->only(config('press.entities.wp_users.api.route_only')); }); } } diff --git a/packages/press/routes/web.php b/packages/press/routes/web.php index 3c8cc4bb2..cda6786d7 100644 --- a/packages/press/routes/web.php +++ b/packages/press/routes/web.php @@ -4,11 +4,9 @@ use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\Route; -Route::middleware('web')->group(function () { +Route::middleware('web')->group(function (): void { if (config('press.redirect_index') === true) { - Route::get('/', function () { - return Redirect::to('https://'.$_SERVER['SERVER_NAME'].config('press.wordpress_slug')); - }); + Route::get('/', fn () => Redirect::to('https://'.$_SERVER['SERVER_NAME'].config('press.wordpress_slug'))); } if (config('press.redirect_logout') === true) { @@ -34,7 +32,7 @@ // this must be the last route if (config('press.redirect_to_wp') === true) { Route::any('{any}', function ($any) { - if (! str_contains(request()->server()['REQUEST_URI'], config('press.wordpress_slug').'/')) { + if (! str_contains((string) request()->server()['REQUEST_URI'], config('press.wordpress_slug').'/')) { return redirect('/wp/'.ltrim(request()->path(), '/')); } })->where('any', '.*'); diff --git a/packages/press/src/Commands/InstallCommand.php b/packages/press/src/Commands/InstallCommand.php index 6b7969405..0dd57426f 100644 --- a/packages/press/src/Commands/InstallCommand.php +++ b/packages/press/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -79,6 +79,7 @@ public function publishConfiguration(): void return; } + warning('The Press config already exist. The config will not be published.'); } } @@ -126,22 +127,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +183,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/press/src/Commands/InstallWordPress.php b/packages/press/src/Commands/InstallWordPress.php index 3e02f4f5f..b96aac228 100644 --- a/packages/press/src/Commands/InstallWordPress.php +++ b/packages/press/src/Commands/InstallWordPress.php @@ -2,8 +2,11 @@ namespace Moox\Press\Commands; +use DB; +use Exception; use Illuminate\Console\Command; use Illuminate\Support\Facades\File; +use Symfony\Component\Process\Process; use function Laravel\Prompts\alert; use function Laravel\Prompts\info; @@ -29,12 +32,12 @@ class InstallWordPress extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); $this->checkDotenv(); - $env = $this->getDotenv(); + $this->getDotenv(); $this->testDatabaseConnection(); $this->prepareComposer(); $this->composerInstall(); @@ -129,10 +132,10 @@ public function getDotenv(): array } } - if (! empty($missingVariables)) { + if ($missingVariables !== []) { warning('The following required variables are missing from your .env file:'); foreach ($missingVariables as $variable) { - $this->line("- $variable"); + $this->line('- '.$variable); } warning('Please add the missing variables to your .env file and rerun this command.'); @@ -150,11 +153,11 @@ public function testDatabaseConnection(): void try { // Attempt to connect to the database - \DB::connection()->getPdo(); + DB::connection()->getPdo(); info('Database connection successful.'); - } catch (\Exception $e) { + } catch (Exception $exception) { alert('Failed to connect to the database. Please check your database credentials in the .env file.'); - $this->line($e->getMessage()); + $this->line($exception->getMessage()); exit(1); } } @@ -168,7 +171,7 @@ public function prepareComposer(): void if (File::exists($composerDestination)) { $overwrite = $this->ask('The composer.json file already exists in /public. Do you want to overwrite it? (yes/no)', 'no'); - if (strtolower($overwrite) !== 'yes') { + if (strtolower((string) $overwrite) !== 'yes') { info('composer.json file was not overwritten.'); } else { File::copy($composerSource, $composerDestination); @@ -186,7 +189,7 @@ public function composerInstall(): void $publicDirectory = public_path(); - $process = new \Symfony\Component\Process\Process(['composer', 'install'], $publicDirectory); + $process = new Process(['composer', 'install'], $publicDirectory); $process->setTimeout(null); $process->run(); @@ -205,13 +208,13 @@ public function prepareWpConfig(): void info('Preparing wp-config.php file...'); $wpPath = env('WP_PATH', '/public/wp'); - $fullWpPath = base_path(trim($wpPath, '/')); + $fullWpPath = base_path(trim((string) $wpPath, '/')); if (! File::exists($fullWpPath)) { File::makeDirectory($fullWpPath, 0755, true); - info("WordPress directory created at {$fullWpPath}."); + info(sprintf('WordPress directory created at %s.', $fullWpPath)); } else { - info("WordPress directory already exists at {$fullWpPath}."); + info(sprintf('WordPress directory already exists at %s.', $fullWpPath)); } $wpConfigSource = __DIR__.'/../../wordpress/wp-config.php'; @@ -219,7 +222,7 @@ public function prepareWpConfig(): void if (File::exists($wpConfigDestination)) { $overwrite = $this->ask('The wp-config.php file already exists in the WordPress directory. Do you want to overwrite it? (yes/no)', 'no'); - if (strtolower($overwrite) !== 'yes') { + if (strtolower((string) $overwrite) !== 'yes') { info('wp-config.php file was not overwritten.'); } else { File::copy($wpConfigSource, $wpConfigDestination); @@ -235,7 +238,7 @@ public function useOrInstallWpCli(): void { $this->info('Checking for wp-cli...'); - $process = new \Symfony\Component\Process\Process(['wp', '--version']); + $process = new Process(['wp', '--version']); $process->run(); if ($process->isSuccessful()) { @@ -248,7 +251,7 @@ public function useOrInstallWpCli(): void $this->info('Downloading wp-cli.phar...'); - $downloadProcess = new \Symfony\Component\Process\Process([ + $downloadProcess = new Process([ 'curl', '-O', 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar', @@ -265,7 +268,7 @@ public function useOrInstallWpCli(): void if (PHP_OS_FAMILY !== 'Windows') { $this->info('Making wp-cli.phar executable...'); - $chmodProcess = new \Symfony\Component\Process\Process([ + $chmodProcess = new Process([ 'chmod', '+x', base_path('wp-cli.phar'), @@ -302,7 +305,7 @@ public function useOrInstallWpCli(): void } } else { $this->info('Moving wp-cli.phar to /usr/local/bin/wp...'); - $moveProcess = new \Symfony\Component\Process\Process([ + $moveProcess = new Process([ 'mv', base_path('wp-cli.phar'), '/usr/local/bin/wp', @@ -326,7 +329,7 @@ public function wpInstall(): void $env = $this->getDotenv(); - $wpPath = base_path(trim($env['WP_PATH'], '/')); + $wpPath = base_path(trim((string) $env['WP_PATH'], '/')); if (! File::exists($wpPath.'/wp-config.php')) { alert('wp-config.php not found! Please ensure the file is created and configured.'); exit(1); @@ -339,7 +342,7 @@ public function wpInstall(): void $adminPassword = $this->generateSecurePassword(); $adminEmail = $this->ask('Please enter the admin email'); - info("A secure password has been generated: $adminPassword"); + info('A secure password has been generated: '.$adminPassword); warning('Please make sure to save this password as it will not be shown again.'); $command = [ @@ -359,7 +362,7 @@ public function wpInstall(): void } } - $process = new \Symfony\Component\Process\Process($command, $wpPath, $env); + $process = new Process($command, $wpPath, $env); $process->setTimeout(null); $process->run(); @@ -379,7 +382,7 @@ protected function installAndActivateDefaultTheme(string $fullWpPath): void { $this->info('Ensuring a default theme is installed and activated...'); - $checkThemeProcess = new \Symfony\Component\Process\Process([ + $checkThemeProcess = new Process([ 'wp', 'theme', 'is-installed', @@ -390,7 +393,7 @@ protected function installAndActivateDefaultTheme(string $fullWpPath): void if (! $checkThemeProcess->isSuccessful()) { $this->info('Default theme twentytwentyfour is not installed. Installing it now...'); - $installThemeProcess = new \Symfony\Component\Process\Process([ + $installThemeProcess = new Process([ 'wp', 'theme', 'install', @@ -417,7 +420,7 @@ public function pressPluginInstall(): void info('Installing the Moox Press plugin...'); $wpPath = env('WP_PATH', '/public/wp'); - $fullWpPath = base_path(trim($wpPath, '/')); + $fullWpPath = base_path(trim((string) $wpPath, '/')); $pluginsPath = $fullWpPath.'/wp-content/plugins'; @@ -431,7 +434,7 @@ public function pressPluginInstall(): void if (File::exists($pluginDestination)) { $overwrite = $this->ask('The Moox Press plugin already exists in the plugins directory. Do you want to overwrite it? (yes/no)', 'no'); - if (strtolower($overwrite) !== 'yes') { + if (strtolower((string) $overwrite) !== 'yes') { info('Moox Press plugin was not overwritten.'); return; @@ -445,7 +448,7 @@ public function pressPluginInstall(): void info('Activating the Moox Press plugin...'); $activateCommand = ['wp', 'plugin', 'activate', 'moox-press']; - $process = new \Symfony\Component\Process\Process($activateCommand, $fullWpPath); + $process = new Process($activateCommand, $fullWpPath); $process->setTimeout(null); $process->run(); diff --git a/packages/press/src/Commands/UpdateWordPressPlugin.php b/packages/press/src/Commands/UpdateWordPressPlugin.php index 60203ca6d..77577be0b 100644 --- a/packages/press/src/Commands/UpdateWordPressPlugin.php +++ b/packages/press/src/Commands/UpdateWordPressPlugin.php @@ -29,12 +29,12 @@ class UpdateWordPressPlugin extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); $this->checkDotenv(); - $env = $this->getDotenv(); + $this->getDotenv(); $this->pressPluginInstall(); $this->updateWpConfig(); $this->sayGoodbye(); @@ -101,10 +101,10 @@ public function getDotenv(): array } } - if (! empty($missingVariables)) { + if ($missingVariables !== []) { warning('The following required variables are missing from your .env file:'); foreach ($missingVariables as $variable) { - $this->line("- $variable"); + $this->line('- '.$variable); } warning('Please add the missing variables to your .env file and rerun this command.'); @@ -121,7 +121,7 @@ public function pressPluginInstall(): void info('Updating the Moox Press plugin...'); $wpPath = env('WP_PATH', '/public/wp'); - $fullWpPath = base_path(trim($wpPath, '/')); + $fullWpPath = base_path(trim((string) $wpPath, '/')); $pluginsPath = $fullWpPath.'/wp-content/plugins'; @@ -147,7 +147,7 @@ public function updateWpConfig(): void info('Updating the wp-config.php file...'); $wpPath = env('WP_PATH', '/public/wp'); - $fullWpPath = base_path(trim($wpPath, '/')); + $fullWpPath = base_path(trim((string) $wpPath, '/')); $wpconfigPath = $fullWpPath.'/wp-config.php'; diff --git a/packages/press/src/Commands/UpdateWordPressURL.php b/packages/press/src/Commands/UpdateWordPressURL.php index e3bc91a9f..4efdfeeaa 100644 --- a/packages/press/src/Commands/UpdateWordPressURL.php +++ b/packages/press/src/Commands/UpdateWordPressURL.php @@ -11,7 +11,7 @@ class UpdateWordPressURL extends Command protected $description = 'Update WordPress Site URL in wp_options and all database tables.'; - public function handle() + public function handle(): void { $prefix = config('press.wordpress_prefix'); @@ -32,7 +32,7 @@ public function handle() DB::table($prefix.'options')->where('option_name', 'siteurl')->update(['option_value' => $newUrl]); DB::table($prefix.'options')->where('option_name', 'home')->update(['option_value' => $newUrl]); - $this->info("URL in wp_options updated from $oldUrl to $newUrl."); + $this->info(sprintf('URL in wp_options updated from %s to %s.', $oldUrl, $newUrl)); $query = "SHOW TABLES LIKE '".$prefix."%'"; $tables = DB::select($query); @@ -43,12 +43,12 @@ public function handle() foreach ($columns as $column) { DB::table($tableName) - ->where($column, 'like', "%$oldUrl%") + ->where($column, 'like', sprintf('%%%s%%', $oldUrl)) // TODO: Test and improve this query // https://stackoverflow.com/questions/52229588/laravel-eloquent-how-to-query-not-like - ->where($column, 'not like', "%$newUrl%") + ->where($column, 'not like', sprintf('%%%s%%', $newUrl)) ->update([ - $column => DB::raw("REPLACE($column, '$oldUrl', '$newUrl')"), + $column => DB::raw(sprintf("REPLACE(%s, '%s', '%s')", $column, $oldUrl, $newUrl)), ]); } } diff --git a/packages/press/src/Handlers/WpUserSyncHandler.php b/packages/press/src/Handlers/WpUserSyncHandler.php index f36f22d75..fd7804e8e 100644 --- a/packages/press/src/Handlers/WpUserSyncHandler.php +++ b/packages/press/src/Handlers/WpUserSyncHandler.php @@ -50,6 +50,7 @@ protected function syncMetaData($mainRecordId) { $metaData = $this->getMetaData(); $metaData = $this->ensureAllFieldsHaveValue($metaData); + $foreignKeyName = $this->getForeignKeyName(); foreach ($metaData as $key => $value) { @@ -65,9 +66,7 @@ protected function syncMetaData($mainRecordId) protected function ensureAllFieldsHaveValue(array $data): array { - return array_map(function ($value) { - return $value ?? ''; - }, $data); + return array_map(fn ($value) => $value ?? '', $data); } protected function getMainTableData(): array diff --git a/packages/press/src/Http/Controllers/WpUserController.php b/packages/press/src/Http/Controllers/WpUserController.php index eebe95a68..a4cfe5f3f 100644 --- a/packages/press/src/Http/Controllers/WpUserController.php +++ b/packages/press/src/Http/Controllers/WpUserController.php @@ -51,7 +51,7 @@ public function store(Request $request) /** * Display the specified resource. */ - public function show($id) + public function show($id): WpUserResource { $user = WpUser::with('userMeta')->findOrFail($id); @@ -64,8 +64,8 @@ public function show($id) public function update(Request $request, $id) { $wpUser = new WpUser; - $wpUserData = $request->only($wpUser->getFillable()); - $wpUserMeta = $request->except($wpUser->getFillable()); + $request->only($wpUser->getFillable()); + $request->except($wpUser->getFillable()); $validator = Validator::make($request->all(), [ 'user_login' => 'required|string|max:255', diff --git a/packages/press/src/Http/Resources/WpUserResource.php b/packages/press/src/Http/Resources/WpUserResource.php index ca892fbc3..8c6cbffc8 100644 --- a/packages/press/src/Http/Resources/WpUserResource.php +++ b/packages/press/src/Http/Resources/WpUserResource.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; +use Override; class WpUserResource extends JsonResource { @@ -12,6 +13,7 @@ class WpUserResource extends JsonResource * * @return array */ + #[Override] public function toArray(Request $request): array { $data = [ diff --git a/packages/press/src/Models/WpBasePost.php b/packages/press/src/Models/WpBasePost.php index 0f13f9ef3..8fd35a3a0 100644 --- a/packages/press/src/Models/WpBasePost.php +++ b/packages/press/src/Models/WpBasePost.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Str; +use Override; /** * @property int $ID @@ -18,7 +19,8 @@ */ class WpBasePost extends Model { - use HasFactory, Mutable; + use HasFactory; + use Mutable; protected $fillable = [ 'post_author', @@ -45,13 +47,18 @@ class WpBasePost extends Model 'comment_count', ]; - protected $appends; + protected $appends = [ + 'verantwortlicher', + 'gultig_bis', + 'turnus', + 'fruhwarnung', + ]; protected $wpPrefix; protected $table; - protected $metatable; + protected string $metatable; protected $primaryKey = 'ID'; @@ -67,15 +74,10 @@ public function __construct(array $attributes = []) $this->wpPrefix = config('press.wordpress_prefix'); $this->table = $this->wpPrefix.'posts'; $this->metatable = $this->wpPrefix.'postmeta'; - $this->appends = [ - 'verantwortlicher', - 'gultig_bis', - 'turnus', - 'fruhwarnung', - ]; $this->initializeMetaField(); } + #[Override] protected static function boot() { parent::boot(); @@ -93,13 +95,14 @@ protected function initializeMetaField() if ($this->metaFieldsInitialized) { return; } + $this->metaFieldsInitialized = true; } public function metaKey($key) { if (! Str::startsWith($key, $this->wpPrefix)) { - $key = "{$this->wpPrefix}{$key}"; + $key = $this->wpPrefix.$key; } return $this->getMeta($key); @@ -110,6 +113,7 @@ protected function getMeta($key) if (! $this->relationLoaded('postMeta')) { $this->load('postMeta'); } + $meta = $this->postMeta->where('meta_key', $key)->first(); return $meta ? $meta->meta_value : null; @@ -139,6 +143,7 @@ public function setAttribute($key, $value) return $this; } + #[Override] public function toArray() { $attributes = parent::toArray(); @@ -151,6 +156,7 @@ public function toArray() return $attributes; } + #[Override] public function toJson($options = 0) { return json_encode($this->toArray(), $options); @@ -164,7 +170,7 @@ protected function addOrUpdateMeta($key, $value) ); } - protected function isMetaField($key) + protected function isMetaField($key): bool { return array_key_exists($key, config('press.default_post_meta', [])); } @@ -211,7 +217,7 @@ public function getVerantwortlicherAttribute() return $this->getMeta('verantwortlicher') ?? null; } - public function setVerantwortlicherAttribute($value) + public function setVerantwortlicherAttribute($value): void { $this->addOrUpdateMeta('verantwortlicher', $value); } @@ -221,7 +227,7 @@ public function getGultigBisAttribute() return $this->getMeta('gultig_bis') ?? null; } - public function setGultigBisAttribute($value) + public function setGultigBisAttribute($value): void { $this->addOrUpdateMeta('gultig_bis', $value); } @@ -231,7 +237,7 @@ public function getTurnusAttribute() return $this->getMeta('turnus') ?? null; } - public function setTurnusAttribute($value) + public function setTurnusAttribute($value): void { $this->addOrUpdateMeta('turnus', $value); } @@ -241,7 +247,7 @@ public function getFruhwarnungAttribute() return $this->getMeta('fruhwarnung') ?? null; } - public function setFruhwarnungAttribute($value) + public function setFruhwarnungAttribute($value): void { $this->addOrUpdateMeta('fruhwarnung', $value); } diff --git a/packages/press/src/Models/WpCategory.php b/packages/press/src/Models/WpCategory.php index df2262db9..a2aa1f26e 100644 --- a/packages/press/src/Models/WpCategory.php +++ b/packages/press/src/Models/WpCategory.php @@ -3,17 +3,19 @@ namespace Moox\Press\Models; use Illuminate\Database\Eloquent\Builder; +use Override; class WpCategory extends WpTerm { protected $taxonomy = 'category'; - public static function boot() + #[Override] + protected static function boot() { parent::boot(); - static::addGlobalScope('category', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('category', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'category'); }); }); diff --git a/packages/press/src/Models/WpMedia.php b/packages/press/src/Models/WpMedia.php index 88167bd9c..6e9c476c5 100644 --- a/packages/press/src/Models/WpMedia.php +++ b/packages/press/src/Models/WpMedia.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; +use Override; class WpMedia extends WpBasePost { @@ -23,15 +24,17 @@ public function __construct(array $attributes = []) $this->table = $this->wpPrefix.'posts'; } - public static function boot() + #[Override] + protected static function boot() { parent::boot(); - static::addGlobalScope('media', function (Builder $builder) { + static::addGlobalScope('media', function (Builder $builder): void { $builder->where('post_type', 'attachment'); }); } + #[Override] public function postMeta(): HasMany { return $this->hasMany(WpPostMeta::class, 'post_id', 'ID'); @@ -47,7 +50,7 @@ public function getAssetAttribute() $file = $this->image_url; $wpslug = config('press.wordpress_slug'); - $wpslug = ltrim($wpslug, $wpslug[0]); + $wpslug = ltrim((string) $wpslug, $wpslug[0]); // TODO: Check if the file is an image // TODO: Read wp-config.php to get the upload path @@ -62,12 +65,12 @@ public function getImageSizesAttribute() return $sizes ? unserialize($sizes)['sizes'] : []; } - public function setImageUrlAttribute($value) + public function setImageUrlAttribute($value): void { $this->postMeta()->updateOrCreate(['meta_key' => '_wp_attached_file'], ['meta_value' => $value]); } - public function setImageSizesAttribute($value) + public function setImageSizesAttribute($value): void { $this->postMeta()->updateOrCreate(['meta_key' => '_wp_attachment_metadata'], ['meta_value' => serialize($value)]); } diff --git a/packages/press/src/Models/WpPage.php b/packages/press/src/Models/WpPage.php index 757b3c76c..8c54fc711 100644 --- a/packages/press/src/Models/WpPage.php +++ b/packages/press/src/Models/WpPage.php @@ -3,14 +3,16 @@ namespace Moox\Press\Models; use Illuminate\Database\Eloquent\Builder; +use Override; class WpPage extends WpBasePost { - public static function boot() + #[Override] + protected static function boot() { parent::boot(); - static::addGlobalScope('page', function (Builder $builder) { + static::addGlobalScope('page', function (Builder $builder): void { $builder->where('post_type', 'page'); }); } diff --git a/packages/press/src/Models/WpPost.php b/packages/press/src/Models/WpPost.php index bb3647982..f6f3f7d91 100644 --- a/packages/press/src/Models/WpPost.php +++ b/packages/press/src/Models/WpPost.php @@ -3,14 +3,16 @@ namespace Moox\Press\Models; use Illuminate\Database\Eloquent\Builder; +use Override; class WpPost extends WpBasePost { - public static function boot() + #[Override] + protected static function boot() { parent::boot(); - static::addGlobalScope('post', function (Builder $builder) { + static::addGlobalScope('post', function (Builder $builder): void { $builder ->where('post_type', 'post') ->whereIn('post_status', ['publish', 'draft', 'pending', 'trash', 'future', 'private']) diff --git a/packages/press/src/Models/WpTag.php b/packages/press/src/Models/WpTag.php index 209ebc106..e3dd655a2 100644 --- a/packages/press/src/Models/WpTag.php +++ b/packages/press/src/Models/WpTag.php @@ -3,17 +3,19 @@ namespace Moox\Press\Models; use Illuminate\Database\Eloquent\Builder; +use Override; class WpTag extends WpTerm { protected $taxonomy = 'tag'; - public static function boot(): void + #[Override] + protected static function boot(): void { parent::boot(); - static::addGlobalScope('tag', function (Builder $builder) { - $builder->whereHas('termTaxonomy', function ($query) { + static::addGlobalScope('tag', function (Builder $builder): void { + $builder->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'post_tag'); }); }); diff --git a/packages/press/src/Models/WpTerm.php b/packages/press/src/Models/WpTerm.php index 5e6cbd9b2..fcd6730b0 100644 --- a/packages/press/src/Models/WpTerm.php +++ b/packages/press/src/Models/WpTerm.php @@ -5,10 +5,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Moox\Core\Traits\RequestInModel; +use Override; class WpTerm extends Model { - use HasFactory, RequestInModel; + use HasFactory; + use RequestInModel; protected $taxonomy = 'term'; @@ -46,11 +48,12 @@ public function __construct(array $attributes = []) $this->table = $this->wpPrefix.'terms'; } - public static function boot() + #[Override] + protected static function boot() { parent::boot(); - static::created(function ($wpTerm) { + static::created(function ($wpTerm): void { $taxonomy = $wpTerm->taxonomy; $description = $wpTerm->getRequestData('description') ?? ''; $parent = $wpTerm->getRequestData('parent') ?? 0; @@ -64,7 +67,7 @@ public static function boot() ]); }); - static::updated(function ($wpTerm) { + static::updated(function ($wpTerm): void { $taxonomy = $wpTerm->taxonomy; $description = $wpTerm->getRequestData('description') ?? $wpTerm->getOriginal('description') ?? ''; $parent = $wpTerm->getRequestData('parent') ?? $wpTerm->getOriginal('parent') ?? 0; @@ -78,7 +81,7 @@ public static function boot() ]); }); - static::deleting(function ($wpTerm) { + static::deleting(function ($wpTerm): void { $wpTerm->termTaxonomy()->delete(); }); } @@ -108,28 +111,28 @@ public function getCountAttribute() return $this->termTaxonomy->count ?? 0; } - public function setTaxonomyAttribute($value) + public function setTaxonomyAttribute($value): void { if ($this->term_id) { $this->termTaxonomy()->updateOrCreate([], ['taxonomy' => $value]); } } - public function setDescriptionAttribute($value) + public function setDescriptionAttribute($value): void { if ($this->term_id) { $this->termTaxonomy()->updateOrCreate([], ['description' => $value]); } } - public function setParentAttribute($value) + public function setParentAttribute($value): void { if ($this->term_id) { $this->termTaxonomy()->updateOrCreate([], ['parent' => $value]); } } - public function setCountAttribute($value) + public function setCountAttribute($value): void { if ($this->term_id) { $this->termTaxonomy()->updateOrCreate([], ['count' => $value]); diff --git a/packages/press/src/Models/WpTermTaxonomy.php b/packages/press/src/Models/WpTermTaxonomy.php index 1b228b496..bb49b810d 100644 --- a/packages/press/src/Models/WpTermTaxonomy.php +++ b/packages/press/src/Models/WpTermTaxonomy.php @@ -12,7 +12,7 @@ * @property string $description * @property int $parent * @property int $count - * @property \Moox\Press\Models\WpTerm $term + * @property WpTerm $term */ class WpTermTaxonomy extends Model { diff --git a/packages/press/src/Models/WpUser.php b/packages/press/src/Models/WpUser.php index 336743a87..616614ac5 100644 --- a/packages/press/src/Models/WpUser.php +++ b/packages/press/src/Models/WpUser.php @@ -12,13 +12,16 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Moox\Press\QueryBuilder\UserQueryBuilder; +use Override; /** * @property string $user_email */ class WpUser extends Authenticatable implements FilamentUser { - use HasFactory, Mutable, Notifiable; + use HasFactory; + use Mutable; + use Notifiable; protected $fillable = [ 'user_login', @@ -46,7 +49,7 @@ class WpUser extends Authenticatable implements FilamentUser protected $table; - protected $metatable; + protected string $metatable; protected $primaryKey = 'ID'; @@ -69,30 +72,31 @@ public function __construct(array $attributes = []) $this->initializeMetaFields(); } + #[Override] protected static function boot() { parent::boot(); - static::created(function ($model) { + static::created(function ($model): void { $model->addOrUpdateMeta('created_at', now()->toDateTimeString()); }); - static::saving(function ($post) { + static::saving(function ($post): void { // Überprüfe, ob das Datum ungültig ist, und setze es auf NULL oder ein Standarddatum if ($post->post_modified == '0000-00-00 00:00:00') { $post->post_modified = null; // oder ein anderes gültiges Datum wie '1970-01-01 00:00:00' } }); - static::updated(function ($model) { + static::updated(function ($model): void { $model->addOrUpdateMeta('updated_at', now()->toDateTimeString()); }); - static::deleted(function ($model) { + static::deleted(function ($model): void { $model->userMeta()->delete(); }); - static::addGlobalScope('addAttributes', function (Builder $builder) { + static::addGlobalScope('addAttributes', function (Builder $builder): void { $builder->addSelect([ 'ID', 'ID as id', @@ -146,6 +150,7 @@ public function setAttribute($key, $value) return $this; } + #[Override] public function toArray() { $attributes = parent::toArray(); @@ -159,6 +164,7 @@ public function toArray() return $attributes; } + #[Override] public function toJson($options = 0) { return json_encode($this->toArray(), $options); @@ -175,7 +181,7 @@ public function getMeta($key) return $meta ? $meta->meta_value : null; } - public function addOrUpdateMeta($key, $value) + public function addOrUpdateMeta($key, $value): void { WpUserMeta::updateOrCreate( ['user_id' => $this->ID, 'meta_key' => $key], @@ -193,6 +199,7 @@ public function attachment(): BelongsTo return $this->belongsTo(WpMedia::class, 'mm_sua_attachment_id', 'ID'); } + #[Override] protected function newBaseQueryBuilder() { $connection = $this->getConnection(); @@ -202,12 +209,15 @@ protected function newBaseQueryBuilder() return new UserQueryBuilder($connection, $grammar, $processor); } - protected function isMetaField($key) + protected function isMetaField($key): bool { return array_key_exists($key, config('press.default_user_meta', [])); } - public function getAllMetaAttributes() + /** + * @return mixed[] + */ + public function getAllMetaAttributes(): array { $metaFields = config('press.default_user_meta', []); $attributes = []; @@ -239,7 +249,7 @@ public function getEmailAttribute() return $this->getAttribute('user_email'); } - public function setEmailAttribute($value) + public function setEmailAttribute($value): void { $this->setAttribute('user_email', $value); } @@ -249,7 +259,7 @@ public function getPasswordAttribute() return $this->getAttribute('user_pass'); } - public function setPasswordAttribute($value) + public function setPasswordAttribute($value): void { $this->setAttribute('user_pass', $value); } diff --git a/packages/press/src/PressServiceProvider.php b/packages/press/src/PressServiceProvider.php index 616e3c18c..f66df142a 100644 --- a/packages/press/src/PressServiceProvider.php +++ b/packages/press/src/PressServiceProvider.php @@ -10,6 +10,7 @@ use Moox\Press\Commands\UpdateWordPressPlugin; use Moox\Press\Commands\UpdateWordPressURL; use Moox\Press\Providers\WordPressUserProvider; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -31,12 +32,11 @@ public function configurePackage(Package $package): void ); } - public function boot() + #[Override] + public function boot(): void { parent::boot(); - Auth::provider('wpuser-provider', function ($app, array $config) { - return new WordPressUserProvider($app['hash'], $config['model']); - }); + Auth::provider('wpuser-provider', fn ($app, array $config): WordPressUserProvider => new WordPressUserProvider($app['hash'], $config['model'])); } } diff --git a/packages/press/src/Providers/WordPressUserProvider.php b/packages/press/src/Providers/WordPressUserProvider.php index f1364096a..fc807b3fd 100644 --- a/packages/press/src/Providers/WordPressUserProvider.php +++ b/packages/press/src/Providers/WordPressUserProvider.php @@ -4,18 +4,21 @@ use Illuminate\Auth\EloquentUserProvider; use Illuminate\Contracts\Auth\Authenticatable as UserContract; +use Illuminate\Contracts\Hashing\Hasher; use Moox\Press\Services\WordPressAuthService; +use Override; class WordPressUserProvider extends EloquentUserProvider { - protected $wpAuthService; + protected WordPressAuthService $wpAuthService; - public function __construct($hasher, $model) + public function __construct(Hasher $hasher, $model) { parent::__construct($hasher, $model); $this->wpAuthService = new WordPressAuthService; } + #[Override] public function validateCredentials(UserContract $user, array $credentials) { $plain = $credentials['password']; diff --git a/packages/press/src/QueryBuilder/UserQueryBuilder.php b/packages/press/src/QueryBuilder/UserQueryBuilder.php index c2d5ca45a..bcb3809a8 100644 --- a/packages/press/src/QueryBuilder/UserQueryBuilder.php +++ b/packages/press/src/QueryBuilder/UserQueryBuilder.php @@ -3,6 +3,7 @@ namespace Moox\Press\QueryBuilder; use Illuminate\Database\Query\Builder; +use Override; class UserQueryBuilder extends Builder { @@ -13,6 +14,7 @@ class UserQueryBuilder extends Builder 'id' => 'ID', ]; + #[Override] public function where($column, $operator = null, $value = null, $boolean = 'and') { if (is_string($column) && array_key_exists($column, $this->aliasMap)) { @@ -22,6 +24,7 @@ public function where($column, $operator = null, $value = null, $boolean = 'and' return parent::where($column, $operator, $value, $boolean); } + #[Override] public function orderBy($column, $direction = 'asc') { if (is_string($column) && array_key_exists($column, $this->aliasMap)) { diff --git a/packages/press/src/Resolver/WpUserFileResolver.php b/packages/press/src/Resolver/WpUserFileResolver.php index 45524a565..46fb28c5b 100644 --- a/packages/press/src/Resolver/WpUserFileResolver.php +++ b/packages/press/src/Resolver/WpUserFileResolver.php @@ -5,10 +5,11 @@ use Illuminate\Support\Facades\Storage; use Moox\Press\Models\WpUser; use Moox\Sync\Resolver\AbstractFileResolver; +use Override; class WpUserFileResolver extends AbstractFileResolver { - protected $wpUser; + protected WpUser $wpUser; public function __construct(WpUser $wpUser) { @@ -23,7 +24,7 @@ public function getFileFields(): array foreach ($this->wpUser->getAttributes() as $field => $value) { foreach ($fieldsToCheck as $keyword) { - if (stripos($field, $keyword) !== false) { + if (stripos((string) $field, (string) $keyword) !== false) { $fileFields[] = $field; break; } @@ -39,13 +40,10 @@ public function getFileFields(): array return array_unique($fileFields); } + #[Override] public function getFileData(string $field): ?array { - if ($field === 'wp_user_avatar') { - $attachmentPath = $this->wpUser->getMeta('wp_user_avatar_path'); - } else { - $attachmentPath = $this->wpUser->$field; - } + $attachmentPath = $field === 'wp_user_avatar' ? $this->wpUser->getMeta('wp_user_avatar_path') : $this->wpUser->$field; if (! $attachmentPath || ! Storage::exists($attachmentPath)) { return null; @@ -56,7 +54,7 @@ public function getFileData(string $field): ?array 'size' => Storage::size($attachmentPath), 'last_modified' => Storage::lastModified($attachmentPath), 'mime_type' => Storage::mimeType($attachmentPath), - 'extension' => pathinfo($attachmentPath, PATHINFO_EXTENSION), + 'extension' => pathinfo((string) $attachmentPath, PATHINFO_EXTENSION), ]; } } diff --git a/packages/press/src/Resources/WpCategoryResource.php b/packages/press/src/Resources/WpCategoryResource.php index 70171ca37..acf3cecb2 100644 --- a/packages/press/src/Resources/WpCategoryResource.php +++ b/packages/press/src/Resources/WpCategoryResource.php @@ -9,20 +9,25 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpCategory; use Moox\Press\Models\WpTerm; -use Moox\Press\Resources\WpCategoryResource\Pages; +use Moox\Press\Resources\WpCategoryResource\Pages\CreateWpCategory; +use Moox\Press\Resources\WpCategoryResource\Pages\EditWpCategory; +use Moox\Press\Resources\WpCategoryResource\Pages\ListWpCategories; +use Moox\Press\Resources\WpCategoryResource\Pages\ViewWpCategory; +use Override; class WpCategoryResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpCategory::class; @@ -30,6 +35,7 @@ class WpCategoryResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -101,35 +107,36 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('description') + TextColumn::make('description') ->label(__('core::core.description')) ->toggleable(isToggledHiddenByDefault: true) ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('parent') + TextColumn::make('parent') ->label(__('core::core.parent')) ->toggleable() ->searchable(), - Tables\Columns\TextColumn::make('count') + TextColumn::make('count') ->label(__('core::core.count')) ->toggleable() ->searchable(), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable(isToggledHiddenByDefault: true) ->searchable() @@ -139,46 +146,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpCategories::route('/'), - 'create' => Pages\CreateWpCategory::route('/create'), - 'view' => Pages\ViewWpCategory::route('/{record}'), - 'edit' => Pages\EditWpCategory::route('/{record}/edit'), + 'index' => ListWpCategories::route('/'), + 'create' => CreateWpCategory::route('/create'), + 'view' => ViewWpCategory::route('/{record}'), + 'edit' => EditWpCategory::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.category.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.category.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.category.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.category.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.press_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.press_navigation_sort') + 4; diff --git a/packages/press/src/Resources/WpCommentMetaResource.php b/packages/press/src/Resources/WpCommentMetaResource.php index 9c9f3ecb4..8b101b4ef 100644 --- a/packages/press/src/Resources/WpCommentMetaResource.php +++ b/packages/press/src/Resources/WpCommentMetaResource.php @@ -8,19 +8,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpCommentMeta; -use Moox\Press\Resources\WpCommentMetaResource\Pages; +use Moox\Press\Resources\WpCommentMetaResource\Pages\CreateWpCommentMeta; +use Moox\Press\Resources\WpCommentMetaResource\Pages\EditWpCommentMeta; +use Moox\Press\Resources\WpCommentMetaResource\Pages\ListWpCommentMetas; +use Moox\Press\Resources\WpCommentMetaResource\Pages\ViewWpCommentMeta; +use Override; class WpCommentMetaResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpCommentMeta::class; @@ -28,6 +33,7 @@ class WpCommentMetaResource extends Resource protected static ?string $recordTitleAttribute = 'meta_key'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -68,22 +74,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('comment_id') + TextColumn::make('comment_id') ->label(__('core::comment.comment_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() @@ -93,46 +100,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpCommentMetas::route('/'), - 'create' => Pages\CreateWpCommentMeta::route('/create'), - 'view' => Pages\ViewWpCommentMeta::route('/{record}'), - 'edit' => Pages\EditWpCommentMeta::route('/{record}/edit'), + 'index' => ListWpCommentMetas::route('/'), + 'create' => CreateWpCommentMeta::route('/create'), + 'view' => ViewWpCommentMeta::route('/{record}'), + 'edit' => EditWpCommentMeta::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.commentMeta.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.commentMeta.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.commentMeta.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.commentMeta.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.meta_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.meta_navigation_sort') + 1; diff --git a/packages/press/src/Resources/WpCommentResource.php b/packages/press/src/Resources/WpCommentResource.php index f9da2f180..709700d95 100644 --- a/packages/press/src/Resources/WpCommentResource.php +++ b/packages/press/src/Resources/WpCommentResource.php @@ -9,20 +9,25 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpComment; -use Moox\Press\Resources\WpCommentResource\Pages; +use Moox\Press\Resources\WpCommentResource\Pages\CreateWpComment; +use Moox\Press\Resources\WpCommentResource\Pages\EditWpComment; +use Moox\Press\Resources\WpCommentResource\Pages\ListWpComments; +use Moox\Press\Resources\WpCommentResource\Pages\ViewWpComment; use Moox\Press\Resources\WpCommentResource\RelationManagers\WpCommentMetaRelationManager; +use Override; class WpCommentResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpComment::class; @@ -30,6 +35,7 @@ class WpCommentResource extends Resource protected static ?string $recordTitleAttribute = 'comment_author'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -189,74 +195,75 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('comment_post_ID') + TextColumn::make('comment_post_ID') ->label(__('core::comment.comment_post_ID')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author') + TextColumn::make('comment_author') ->label(__('core::comment.comment_author')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_author_email') + TextColumn::make('comment_author_email') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_url') + TextColumn::make('comment_author_url') ->label(__('core::comment.comment_author_url')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_IP') + TextColumn::make('comment_author_IP') ->label(__('core::comment.comment_author_IP')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_date') + TextColumn::make('comment_date') ->label(__('core::comment.comment_date')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_date_gmt') + TextColumn::make('comment_date_gmt') ->label(__('core::comment.comment_date_gmt')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_content') + TextColumn::make('comment_content') ->label(__('core::comment.comment_content')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_karma') + TextColumn::make('comment_karma') ->label(__('core::comment.comment_karma')) ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('comment_approved') + TextColumn::make('comment_approved') ->label(__('core::comment.comment_approved')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_agent') + TextColumn::make('comment_agent') ->label(__('core::comment.comment_agent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_type') + TextColumn::make('comment_type') ->label(__('core::comment.comment_type')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_parent') + TextColumn::make('comment_parent') ->label(__('core::comment.comment_parent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('user_id') + TextColumn::make('user_id') ->label(__('core::user.user_id')) ->toggleable() ->searchable(true, null, true) @@ -266,6 +273,7 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ @@ -273,41 +281,48 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpComments::route('/'), - 'create' => Pages\CreateWpComment::route('/create'), - 'view' => Pages\ViewWpComment::route('/{record}'), - 'edit' => Pages\EditWpComment::route('/{record}/edit'), + 'index' => ListWpComments::route('/'), + 'create' => CreateWpComment::route('/create'), + 'view' => ViewWpComment::route('/{record}'), + 'edit' => EditWpComment::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.comment.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.comment.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.comment.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.comment.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.press_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.press_navigation_sort') + 6; diff --git a/packages/press/src/Resources/WpCommentResource/RelationManagers/WpCommentMetaRelationManager.php b/packages/press/src/Resources/WpCommentResource/RelationManagers/WpCommentMetaRelationManager.php index 26f98fce7..c8663f1c7 100644 --- a/packages/press/src/Resources/WpCommentResource/RelationManagers/WpCommentMetaRelationManager.php +++ b/packages/press/src/Resources/WpCommentResource/RelationManagers/WpCommentMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpCommentMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpCommentMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'comment_id'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,17 +67,17 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('comment_id') + TextColumn::make('comment_id') ->label(__('core::comment.comment_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press/src/Resources/WpMediaResource.php b/packages/press/src/Resources/WpMediaResource.php index a62467440..3f842bb7c 100644 --- a/packages/press/src/Resources/WpMediaResource.php +++ b/packages/press/src/Resources/WpMediaResource.php @@ -19,12 +19,17 @@ use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpMedia; -use Moox\Press\Resources\WpMediaResource\Pages; +use Moox\Press\Resources\WpMediaResource\Pages\CreateWpPost; +use Moox\Press\Resources\WpMediaResource\Pages\EditWpPost; +use Moox\Press\Resources\WpMediaResource\Pages\ListWpPosts; +use Moox\Press\Resources\WpMediaResource\Pages\ViewWpPost; use Moox\Press\Resources\WpMediaResource\RelationManagers\WpPostMetaRelationManager; +use Override; class WpMediaResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpMedia::class; @@ -32,6 +37,7 @@ class WpMediaResource extends Resource protected static ?string $recordTitleAttribute = 'post_title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -274,6 +280,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -361,6 +368,7 @@ public static function table(Table $table): Table // ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ @@ -368,41 +376,48 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpPosts::route('/'), - 'create' => Pages\CreateWpPost::route('/create'), - 'view' => Pages\ViewWpPost::route('/{record}'), - 'edit' => Pages\EditWpPost::route('/{record}/edit'), + 'index' => ListWpPosts::route('/'), + 'create' => CreateWpPost::route('/create'), + 'view' => ViewWpPost::route('/{record}'), + 'edit' => EditWpPost::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.media.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.media.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.media.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.media.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.press_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.press_navigation_sort') + 3; diff --git a/packages/press/src/Resources/WpMediaResource/RelationManagers/WpPostMetaRelationManager.php b/packages/press/src/Resources/WpMediaResource/RelationManagers/WpPostMetaRelationManager.php index 77cc31837..baba92ff5 100644 --- a/packages/press/src/Resources/WpMediaResource/RelationManagers/WpPostMetaRelationManager.php +++ b/packages/press/src/Resources/WpMediaResource/RelationManagers/WpPostMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpPostMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpPostMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,17 +67,17 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_id') + TextColumn::make('post_id') ->label(__('core::post.post_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press/src/Resources/WpOptionResource.php b/packages/press/src/Resources/WpOptionResource.php index 525cc6a23..31fa1cfad 100644 --- a/packages/press/src/Resources/WpOptionResource.php +++ b/packages/press/src/Resources/WpOptionResource.php @@ -8,19 +8,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpOption; -use Moox\Press\Resources\WpOptionResource\Pages; +use Moox\Press\Resources\WpOptionResource\Pages\CreateWpOption; +use Moox\Press\Resources\WpOptionResource\Pages\EditWpOption; +use Moox\Press\Resources\WpOptionResource\Pages\ListWpOptions; +use Moox\Press\Resources\WpOptionResource\Pages\ViewWpOption; +use Override; class WpOptionResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpOption::class; @@ -28,6 +33,7 @@ class WpOptionResource extends Resource protected static ?string $recordTitleAttribute = 'option_name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -68,22 +74,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('option_name') + TextColumn::make('option_name') ->label(__('core::core.option_name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('option_value') + TextColumn::make('option_value') ->label(__('core::core.option_value')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('autoload') + TextColumn::make('autoload') ->label(__('core::core.autoload')) ->toggleable() ->searchable(true, null, true) @@ -93,46 +100,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpOptions::route('/'), - 'create' => Pages\CreateWpOption::route('/create'), - 'view' => Pages\ViewWpOption::route('/{record}'), - 'edit' => Pages\EditWpOption::route('/{record}/edit'), + 'index' => ListWpOptions::route('/'), + 'create' => CreateWpOption::route('/create'), + 'view' => ViewWpOption::route('/{record}'), + 'edit' => EditWpOption::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.option.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.option.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.option.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.option.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.system_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.press_navigation_sort') + 1; diff --git a/packages/press/src/Resources/WpPageResource.php b/packages/press/src/Resources/WpPageResource.php index 890201a55..455e0019f 100644 --- a/packages/press/src/Resources/WpPageResource.php +++ b/packages/press/src/Resources/WpPageResource.php @@ -9,21 +9,26 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpPage; -use Moox\Press\Resources\WpPageResource\Pages; +use Moox\Press\Resources\WpPageResource\Pages\CreateWpPage; +use Moox\Press\Resources\WpPageResource\Pages\EditWpPage; +use Moox\Press\Resources\WpPageResource\Pages\ListWpPage; +use Moox\Press\Resources\WpPageResource\Pages\ViewWpPage; use Moox\Press\Resources\WpPageResource\RelationManagers\WpPostMetaRelationManager; +use Override; class WpPageResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpPage::class; @@ -31,6 +36,7 @@ class WpPageResource extends Resource protected static ?string $recordTitleAttribute = 'post_title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -273,112 +279,113 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_author') + TextColumn::make('post_author') ->label(__('core::post.post_author')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('post_date') + TextColumn::make('post_date') ->label(__('core::post.post_date')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('post_date_gmt') + TextColumn::make('post_date_gmt') ->label(__('core::post.post_date_gmt')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('post_content') + TextColumn::make('post_content') ->label(__('core::post.post_content')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_title') + TextColumn::make('post_title') ->label(__('core::post.post_title')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_excerpt') + TextColumn::make('post_excerpt') ->label(__('core::post.post_excerpt')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_status') + TextColumn::make('post_status') ->label(__('core::post.post_status')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_status') + TextColumn::make('comment_status') ->label(__('core::comment.comment_status')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('ping_status') + TextColumn::make('ping_status') ->label(__('core::post.ping_status')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('post_password') + TextColumn::make('post_password') ->label(__('core::post.post_password')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('post_name') + TextColumn::make('post_name') ->label(__('core::post.post_name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('to_ping') + TextColumn::make('to_ping') ->label(__('core::post.to_ping')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('pinged') + TextColumn::make('pinged') ->label(__('core::post.pinged')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_modified') + TextColumn::make('post_modified') ->label(__('core::post.post_modified')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('post_modified_gmt') + TextColumn::make('post_modified_gmt') ->label(__('core::post.post_modified_gmt')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('post_content_filtered') + TextColumn::make('post_content_filtered') ->label(__('core::post.post_content_filtered')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_parent') + TextColumn::make('post_parent') ->label(__('core::post.post_parent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('guid') + TextColumn::make('guid') ->label(__('core::core.guid')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('menu_order') + TextColumn::make('menu_order') ->label(__('core::core.menu_order')) ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('post_type') + TextColumn::make('post_type') ->label(__('core::post.post_type')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('post_mime_type') + TextColumn::make('post_mime_type') ->label(__('core::post.post_mime_type')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_count') + TextColumn::make('comment_count') ->label(__('core::comment.comment_count')) ->toggleable() ->searchable(true, null, true) @@ -387,11 +394,12 @@ public static function table(Table $table): Table ->actions([ ViewAction::make(), EditAction::make(), - Action::make('Wp Edit')->url(fn ($record): string => "/wp/wp-admin/post.php?post={$record->ID}&action=edit"), + Action::make('Wp Edit')->url(fn ($record): string => sprintf('/wp/wp-admin/post.php?post=%s&action=edit', $record->ID)), ]) ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ @@ -399,41 +407,48 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpPage::route('/'), - 'create' => Pages\CreateWpPage::route('/create'), - 'view' => Pages\ViewWpPage::route('/{record}'), - 'edit' => Pages\EditWpPage::route('/{record}/edit'), + 'index' => ListWpPage::route('/'), + 'create' => CreateWpPage::route('/create'), + 'view' => ViewWpPage::route('/{record}'), + 'edit' => EditWpPage::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.page.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.page.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.page.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.page.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.press_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.press_navigation_sort') + 2; diff --git a/packages/press/src/Resources/WpPageResource/RelationManagers/WpPostMetaRelationManager.php b/packages/press/src/Resources/WpPageResource/RelationManagers/WpPostMetaRelationManager.php index 1a952fa7e..5c36eaf6a 100644 --- a/packages/press/src/Resources/WpPageResource/RelationManagers/WpPostMetaRelationManager.php +++ b/packages/press/src/Resources/WpPageResource/RelationManagers/WpPostMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpPostMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpPostMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,17 +67,17 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_id') + TextColumn::make('post_id') ->label(__('core::post.post_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press/src/Resources/WpPostMetaResource.php b/packages/press/src/Resources/WpPostMetaResource.php index 3f4264a94..0a678dc9a 100644 --- a/packages/press/src/Resources/WpPostMetaResource.php +++ b/packages/press/src/Resources/WpPostMetaResource.php @@ -8,19 +8,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpPostMeta; -use Moox\Press\Resources\WpPostMetaResource\Pages; +use Moox\Press\Resources\WpPostMetaResource\Pages\CreateWpPostMeta; +use Moox\Press\Resources\WpPostMetaResource\Pages\EditWpPostMeta; +use Moox\Press\Resources\WpPostMetaResource\Pages\ListWpPostMetas; +use Moox\Press\Resources\WpPostMetaResource\Pages\ViewWpPostMeta; +use Override; class WpPostMetaResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpPostMeta::class; @@ -28,6 +33,7 @@ class WpPostMetaResource extends Resource protected static ?string $recordTitleAttribute = 'meta_key'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -68,22 +74,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_id') + TextColumn::make('post_id') ->label(__('core::post.post_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() @@ -93,46 +100,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpPostMetas::route('/'), - 'create' => Pages\CreateWpPostMeta::route('/create'), - 'view' => Pages\ViewWpPostMeta::route('/{record}'), - 'edit' => Pages\EditWpPostMeta::route('/{record}/edit'), + 'index' => ListWpPostMetas::route('/'), + 'create' => CreateWpPostMeta::route('/create'), + 'view' => ViewWpPostMeta::route('/{record}'), + 'edit' => EditWpPostMeta::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.postMeta.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.postMeta.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.postMeta.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.postMeta.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.meta_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.meta_navigation_sort') + 2; diff --git a/packages/press/src/Resources/WpPostResource.php b/packages/press/src/Resources/WpPostResource.php index 2260bfbef..1ce3567f4 100644 --- a/packages/press/src/Resources/WpPostResource.php +++ b/packages/press/src/Resources/WpPostResource.php @@ -9,20 +9,25 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\DeleteBulkAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpPost; -use Moox\Press\Resources\WpPostResource\Pages; +use Moox\Press\Resources\WpPostResource\Pages\CreateWpPost; +use Moox\Press\Resources\WpPostResource\Pages\EditWpPost; +use Moox\Press\Resources\WpPostResource\Pages\ListWpPosts; +use Moox\Press\Resources\WpPostResource\Pages\ViewWpPost; use Moox\Press\Resources\WpPostResource\RelationManagers\WpCommentRelationManager; use Moox\Press\Resources\WpPostResource\RelationManagers\WpPostMetaRelationManager; +use Override; class WpPostResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpPost::class; @@ -30,6 +35,7 @@ class WpPostResource extends Resource protected static ?string $recordTitleAttribute = 'post_title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -272,52 +278,54 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_author') + TextColumn::make('post_author') ->label(__('core::post.post_author')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_title') + TextColumn::make('post_title') ->label(__('core::post.post_title')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_status') + TextColumn::make('post_status') ->label(__('core::post.post_status')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('post_date') + TextColumn::make('post_date') ->label(__('core::post.post_date')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('post_modified') + TextColumn::make('post_modified') ->label(__('core::post.post_modified')) ->sortable() ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('post_parent') + TextColumn::make('post_parent') ->label(__('core::post.post_parent')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_count') + TextColumn::make('comment_count') ->label(__('core::comment.comment_count')) ->toggleable() ->searchable() ->limit(50), ]) ->actions([ - Action::make('Edit')->url(fn ($record): string => "/wp/wp-admin/post.php?post={$record->ID}&action=edit"), + Action::make('Edit')->url(fn ($record): string => sprintf('/wp/wp-admin/post.php?post=%s&action=edit', $record->ID)), ]) ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ @@ -326,41 +334,48 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpPosts::route('/'), - 'create' => Pages\CreateWpPost::route('/create'), - 'view' => Pages\ViewWpPost::route('/{record}'), - 'edit' => Pages\EditWpPost::route('/{record}/edit'), + 'index' => ListWpPosts::route('/'), + 'create' => CreateWpPost::route('/create'), + 'view' => ViewWpPost::route('/{record}'), + 'edit' => EditWpPost::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.post.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.post.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.post.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.post.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.press_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.press_navigation_sort') + 1; diff --git a/packages/press/src/Resources/WpPostResource/RelationManagers/WpCommentRelationManager.php b/packages/press/src/Resources/WpPostResource/RelationManagers/WpCommentRelationManager.php index 87394e4e6..871f22e41 100644 --- a/packages/press/src/Resources/WpPostResource/RelationManagers/WpCommentRelationManager.php +++ b/packages/press/src/Resources/WpPostResource/RelationManagers/WpCommentRelationManager.php @@ -9,11 +9,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpCommentRelationManager extends RelationManager { @@ -21,6 +22,7 @@ class WpCommentRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -184,69 +186,69 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('comment_post_ID') + TextColumn::make('comment_post_ID') ->label(__('core::comment.comment_post_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author') + TextColumn::make('comment_author') ->label(__('core::comment.comment_author')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_author_email') + TextColumn::make('comment_author_email') ->label(__('core::comment.comment_author_email')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_url') + TextColumn::make('comment_author_url') ->label(__('core::comment.comment_author_url')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_author_IP') + TextColumn::make('comment_author_IP') ->label(__('core::comment.comment_author_IP')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_date') + TextColumn::make('comment_date') ->label(__('core::comment.comment_date')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_date_gmt') + TextColumn::make('comment_date_gmt') ->label(__('core::comment.comment_date_gmt')) ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('comment_content') + TextColumn::make('comment_content') ->label(__('core::comment.comment_content')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('comment_karma') + TextColumn::make('comment_karma') ->label(__('core::comment.comment_karma')) ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('comment_approved') + TextColumn::make('comment_approved') ->label(__('core::comment.comment_approved')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_agent') + TextColumn::make('comment_agent') ->label(__('core::comment.comment_agent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_type') + TextColumn::make('comment_type') ->label(__('core::comment.comment_type')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('comment_parent') + TextColumn::make('comment_parent') ->label(__('core::comment.comment_parent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('user_id') + TextColumn::make('user_id') ->label(__('core::user.user_id')) ->toggleable() ->searchable(true, null, true) diff --git a/packages/press/src/Resources/WpPostResource/RelationManagers/WpPostMetaRelationManager.php b/packages/press/src/Resources/WpPostResource/RelationManagers/WpPostMetaRelationManager.php index e17722873..e44ab6577 100644 --- a/packages/press/src/Resources/WpPostResource/RelationManagers/WpPostMetaRelationManager.php +++ b/packages/press/src/Resources/WpPostResource/RelationManagers/WpPostMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpPostMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpPostMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,17 +67,17 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('post_id') + TextColumn::make('post_id') ->label(__('core::user.user_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press/src/Resources/WpTagResource.php b/packages/press/src/Resources/WpTagResource.php index 85a28e01b..0df2ff043 100644 --- a/packages/press/src/Resources/WpTagResource.php +++ b/packages/press/src/Resources/WpTagResource.php @@ -7,20 +7,25 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpTerm; -use Moox\Press\Resources\WpTagResource\Pages; +use Moox\Press\Resources\WpTagResource\Pages\CreateWpTag; +use Moox\Press\Resources\WpTagResource\Pages\EditWpTag; +use Moox\Press\Resources\WpTagResource\Pages\ListWpTags; +use Moox\Press\Resources\WpTagResource\Pages\ViewWpTag; +use Override; class WpTagResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpTerm::class; @@ -28,14 +33,16 @@ class WpTagResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function getEloquentQuery(): Builder { return parent::getEloquentQuery() - ->whereHas('termTaxonomy', function ($query) { + ->whereHas('termTaxonomy', function ($query): void { $query->where('taxonomy', 'post_tag'); }); } + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -76,22 +83,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_group') + TextColumn::make('term_group') ->label(__('core::core.term_group')) ->toggleable() ->searchable(true, null, true) @@ -101,46 +109,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTags::route('/'), - 'create' => Pages\CreateWpTag::route('/create'), - 'view' => Pages\ViewWpTag::route('/{record}'), - 'edit' => Pages\EditWpTag::route('/{record}/edit'), + 'index' => ListWpTags::route('/'), + 'create' => CreateWpTag::route('/create'), + 'view' => ViewWpTag::route('/{record}'), + 'edit' => EditWpTag::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.tag.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.tag.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.tag.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.tag.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.press_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.press_navigation_sort') + 5; diff --git a/packages/press/src/Resources/WpTermMetaResource.php b/packages/press/src/Resources/WpTermMetaResource.php index 4997b364d..cc78464fa 100644 --- a/packages/press/src/Resources/WpTermMetaResource.php +++ b/packages/press/src/Resources/WpTermMetaResource.php @@ -8,19 +8,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpTermMeta; -use Moox\Press\Resources\WpTermMetaResource\Pages; +use Moox\Press\Resources\WpTermMetaResource\Pages\CreateWpTermMeta; +use Moox\Press\Resources\WpTermMetaResource\Pages\EditWpTermMeta; +use Moox\Press\Resources\WpTermMetaResource\Pages\ListWpTermMetas; +use Moox\Press\Resources\WpTermMetaResource\Pages\ViewWpTermMeta; +use Override; class WpTermMetaResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpTermMeta::class; @@ -28,6 +33,7 @@ class WpTermMetaResource extends Resource protected static ?string $recordTitleAttribute = 'meta_key'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -68,22 +74,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('term_id') + TextColumn::make('term_id') ->label(__('core::core.term_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.met_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() @@ -93,46 +100,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTermMetas::route('/'), - 'create' => Pages\CreateWpTermMeta::route('/create'), - 'view' => Pages\ViewWpTermMeta::route('/{record}'), - 'edit' => Pages\EditWpTermMeta::route('/{record}/edit'), + 'index' => ListWpTermMetas::route('/'), + 'create' => CreateWpTermMeta::route('/create'), + 'view' => ViewWpTermMeta::route('/{record}'), + 'edit' => EditWpTermMeta::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.termMeta.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.termMeta.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.termMeta.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.termMeta.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.meta_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.meta_navigation_sort') + 3; diff --git a/packages/press/src/Resources/WpTermRelationshipResource.php b/packages/press/src/Resources/WpTermRelationshipResource.php index d5c46255b..905d71f17 100644 --- a/packages/press/src/Resources/WpTermRelationshipResource.php +++ b/packages/press/src/Resources/WpTermRelationshipResource.php @@ -7,19 +7,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpTermRelationship; -use Moox\Press\Resources\WpTermRelationshipResource\Pages; +use Moox\Press\Resources\WpTermRelationshipResource\Pages\CreateWpTermRelationship; +use Moox\Press\Resources\WpTermRelationshipResource\Pages\EditWpTermRelationship; +use Moox\Press\Resources\WpTermRelationshipResource\Pages\ListWpTermRelationships; +use Moox\Press\Resources\WpTermRelationshipResource\Pages\ViewWpTermRelationship; +use Override; class WpTermRelationshipResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpTermRelationship::class; @@ -27,6 +32,7 @@ class WpTermRelationshipResource extends Resource protected static ?string $recordTitleAttribute = 'object_id'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -57,17 +63,18 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('term_taxonomy_id') + TextColumn::make('term_taxonomy_id') ->label(__('core::core.term_taxonomy_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('term_order') + TextColumn::make('term_order') ->label(__('core::core.term_order')) ->toggleable() ->searchable(true, null, true), @@ -76,46 +83,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTermRelationships::route('/'), - 'create' => Pages\CreateWpTermRelationship::route('/create'), - 'view' => Pages\ViewWpTermRelationship::route('/{record}'), - 'edit' => Pages\EditWpTermRelationship::route('/{record}/edit'), + 'index' => ListWpTermRelationships::route('/'), + 'create' => CreateWpTermRelationship::route('/create'), + 'view' => ViewWpTermRelationship::route('/{record}'), + 'edit' => EditWpTermRelationship::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.termRelationships.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.termRelationships.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.termRelationships.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.termRelationships.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.meta_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.meta_navigation_sort') + 4; diff --git a/packages/press/src/Resources/WpTermResource.php b/packages/press/src/Resources/WpTermResource.php index 37e7d326c..5ddff063c 100644 --- a/packages/press/src/Resources/WpTermResource.php +++ b/packages/press/src/Resources/WpTermResource.php @@ -9,20 +9,25 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpTerm; -use Moox\Press\Resources\WpTermResource\Pages; +use Moox\Press\Resources\WpTermResource\Pages\CreateWpTerm; +use Moox\Press\Resources\WpTermResource\Pages\EditWpTerm; +use Moox\Press\Resources\WpTermResource\Pages\ListWpTerms; +use Moox\Press\Resources\WpTermResource\Pages\ViewWpTerm; +use Override; class WpTermResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpTerm::class; @@ -30,11 +35,13 @@ class WpTermResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function getEloquentQuery(): Builder { return parent::getEloquentQuery()->with('termTaxonomy'); } + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -105,31 +112,32 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('core::core.name')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->label(__('core::core.slug')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('description') + TextColumn::make('description') ->label(__('core::core.description')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('parent') + TextColumn::make('parent') ->label(__('core::core.parent')) ->toggleable() ->searchable(), - Tables\Columns\TextColumn::make('count') + TextColumn::make('count') ->label(__('core::core.count')) ->toggleable() ->searchable(), @@ -138,46 +146,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTerms::route('/'), - 'create' => Pages\CreateWpTerm::route('/create'), - 'view' => Pages\ViewWpTerm::route('/{record}'), - 'edit' => Pages\EditWpTerm::route('/{record}/edit'), + 'index' => ListWpTerms::route('/'), + 'create' => CreateWpTerm::route('/create'), + 'view' => ViewWpTerm::route('/{record}'), + 'edit' => EditWpTerm::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.term.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.term.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.term.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.term.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.meta_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.meta_navigation_sort') + 5; diff --git a/packages/press/src/Resources/WpTermTaxonomyResource.php b/packages/press/src/Resources/WpTermTaxonomyResource.php index f83e0cc88..5a640b9ee 100644 --- a/packages/press/src/Resources/WpTermTaxonomyResource.php +++ b/packages/press/src/Resources/WpTermTaxonomyResource.php @@ -8,19 +8,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpTermTaxonomy; -use Moox\Press\Resources\WpTermTaxonomyResource\Pages; +use Moox\Press\Resources\WpTermTaxonomyResource\Pages\CreateWpTermTaxonomy; +use Moox\Press\Resources\WpTermTaxonomyResource\Pages\EditWpTermTaxonomy; +use Moox\Press\Resources\WpTermTaxonomyResource\Pages\ListWpTermTaxonomies; +use Moox\Press\Resources\WpTermTaxonomyResource\Pages\ViewWpTermTaxonomy; +use Override; class WpTermTaxonomyResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpTermTaxonomy::class; @@ -28,6 +33,7 @@ class WpTermTaxonomyResource extends Resource protected static ?string $recordTitleAttribute = 'taxonomy'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -90,32 +96,33 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('term_id') + TextColumn::make('term_id') ->label(__('core::core.term_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('taxonomy') + TextColumn::make('taxonomy') ->label(__('core::core.taxonomy')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('description') + TextColumn::make('description') ->label(__('core::core.description')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('parent') + TextColumn::make('parent') ->label(__('core::core.parent')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('count') + TextColumn::make('count') ->label(__('core::core.count')) ->toggleable() ->searchable(true, null, true) @@ -125,46 +132,54 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpTermTaxonomies::route('/'), - 'create' => Pages\CreateWpTermTaxonomy::route('/create'), - 'view' => Pages\ViewWpTermTaxonomy::route('/{record}'), - 'edit' => Pages\EditWpTermTaxonomy::route('/{record}/edit'), + 'index' => ListWpTermTaxonomies::route('/'), + 'create' => CreateWpTermTaxonomy::route('/create'), + 'view' => ViewWpTermTaxonomy::route('/{record}'), + 'edit' => EditWpTermTaxonomy::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.termTaxonomy.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.termTaxonomy.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.termTaxonomy.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.termTaxonomy.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.meta_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.meta_navigation_sort') + 6; diff --git a/packages/press/src/Resources/WpUserMetaResource.php b/packages/press/src/Resources/WpUserMetaResource.php index 89b8778a5..2823ac68b 100644 --- a/packages/press/src/Resources/WpUserMetaResource.php +++ b/packages/press/src/Resources/WpUserMetaResource.php @@ -8,19 +8,24 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Moox\Core\Traits\Base\BaseInResource; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Press\Models\WpUserMeta; -use Moox\Press\Resources\WpUserMetaResource\Pages; +use Moox\Press\Resources\WpUserMetaResource\Pages\CreateWpUserMeta; +use Moox\Press\Resources\WpUserMetaResource\Pages\EditWpUserMeta; +use Moox\Press\Resources\WpUserMetaResource\Pages\ListWpUserMetas; +use Moox\Press\Resources\WpUserMetaResource\Pages\ViewWpUserMeta; +use Override; class WpUserMetaResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpUserMeta::class; @@ -28,6 +33,7 @@ class WpUserMetaResource extends Resource protected static ?string $recordTitleAttribute = 'meta_key'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -68,22 +74,23 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('user_id') + TextColumn::make('user_id') ->label(__('core::user.user_id')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() @@ -93,41 +100,48 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListWpUserMetas::route('/'), - 'create' => Pages\CreateWpUserMeta::route('/create'), - 'view' => Pages\ViewWpUserMeta::route('/{record}'), - 'edit' => Pages\EditWpUserMeta::route('/{record}/edit'), + 'index' => ListWpUserMetas::route('/'), + 'create' => CreateWpUserMeta::route('/create'), + 'view' => ViewWpUserMeta::route('/{record}'), + 'edit' => EditWpUserMeta::route('/{record}/edit'), ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.userMeta.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.userMeta.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.userMeta.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.userMeta.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.meta_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.meta_navigation_sort') + 8; diff --git a/packages/press/src/Resources/WpUserResource.php b/packages/press/src/Resources/WpUserResource.php index 25fc5cae1..5ac026533 100644 --- a/packages/press/src/Resources/WpUserResource.php +++ b/packages/press/src/Resources/WpUserResource.php @@ -10,11 +10,11 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\ImageColumn; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Illuminate\Validation\Rules\Password; use Moox\Core\Traits\Base\BaseInResource; @@ -27,10 +27,12 @@ use Moox\Press\Resources\WpUserResource\RelationManagers\WpUserMetaRelationManager; use Moox\Security\FilamentActions\Passwords\SendPasswordResetLinksBulkAction; use Moox\Security\Helper\PasswordHash; +use Override; class WpUserResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = WpUser::class; @@ -42,9 +44,7 @@ protected static function getCapabilitiesOptions(): array { $userCapabilities = config('press.wp_roles'); - return collect($userCapabilities)->mapWithKeys(function ($key, $value) { - return [$key => $value]; - })->toArray(); + return collect($userCapabilities)->mapWithKeys(fn ($key, $value) => [$key => $value])->toArray(); } protected static function getUserLevel($serializedRole) @@ -66,6 +66,7 @@ protected static function getUserLevel($serializedRole) return 0; } + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -77,7 +78,7 @@ public static function form(Form $form): Form ->disk('press') ->directory(now()->year.'/'.sprintf('%02d', now()->month)) ->preserveFilenames() - ->afterStateUpdated(function ($state, $set) { + ->afterStateUpdated(function ($state, $set): void { if ($state) { $tempPath = $state->store('livewire-tmp'); $originalName = $state->getClientOriginalName(); @@ -103,7 +104,7 @@ public static function form(Form $form): Form ->columnSpan(12) ->dehydrateStateUsing(fn ($state) => $state) // Speichert den Rollenwert direkt ->live() - ->afterStateUpdated(function ($state, $set) { + ->afterStateUpdated(function ($state, $set): void { $roleLevel = self::getUserLevel($state); $set(config('press.wordpress_prefix').'user_level', $roleLevel); }), @@ -118,7 +119,7 @@ public static function form(Form $form): Form 'md' => 12, 'lg' => 12, ]) - ->afterStateUpdated(function ($state, $set, $get) { + ->afterStateUpdated(function ($state, $set, $get): void { $set('user_nicename', strtolower($get('first_name').'-'.$get('last_name'))); $set('display_name', ucwords($get('first_name').' '.$get('last_name'))); }), @@ -133,7 +134,7 @@ public static function form(Form $form): Form 'lg' => 12, ]) ->live(debounce: 1000) - ->afterStateUpdated(function ($state, $set, $get) { + ->afterStateUpdated(function ($state, $set, $get): void { $set('user_nicename', strtolower($get('first_name').'-'.$get('last_name'))); $set('display_name', ucwords($get('first_name').' '.$get('last_name'))); }), @@ -296,7 +297,7 @@ public static function form(Form $form): Form ->label(__('core::user.user_pass')) ->password() ->visibleOn('create') - ->dehydrateStateUsing(function ($state) { + ->dehydrateStateUsing(function ($state): string { $passwordHash = new PasswordHash(8, true); return $passwordHash->HashPassword($state); @@ -363,6 +364,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -376,25 +378,25 @@ public static function table(Table $table): Table ->toggleable() ->limit(50), - Tables\Columns\TextColumn::make('display_name') + TextColumn::make('display_name') ->label(__('core::user.name')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('user_email') + TextColumn::make('user_email') ->label(__('core::user.user_email')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('user_login') + TextColumn::make('user_login') ->label(__('core::user.user_login')) ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make(config('press.wordpress_prefix').'capabilities') + TextColumn::make(config('press.wordpress_prefix').'capabilities') ->label(__('core::user.role')) ->toggleable() ->limit(50) @@ -414,6 +416,7 @@ public static function table(Table $table): Table ])); } + #[Override] public static function getRelations(): array { return [ @@ -421,6 +424,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -431,31 +435,37 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('press.resources.user.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('press.resources.user.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('press.resources.user.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('press.resources.user.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('press.user_navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('press.user_navigation_sort') + 1; diff --git a/packages/press/src/Resources/WpUserResource/Pages/CreateWpUser.php b/packages/press/src/Resources/WpUserResource/Pages/CreateWpUser.php index bde4648fd..f695cffcd 100644 --- a/packages/press/src/Resources/WpUserResource/Pages/CreateWpUser.php +++ b/packages/press/src/Resources/WpUserResource/Pages/CreateWpUser.php @@ -2,6 +2,7 @@ namespace Moox\Press\Resources\WpUserResource\Pages; +use Exception; use Filament\Resources\Pages\CreateRecord; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; @@ -27,24 +28,24 @@ public function afterCreate(): void $mimeType = $mimeTypes->guessMimeType(storage_path('app/'.$temporaryFilePath)); if (! in_array($mimeType, ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'])) { - throw new \Exception('The file must be an image of type: jpeg, png, gif, webp. or svg.'); + throw new Exception('The file must be an image of type: jpeg, png, gif, webp. or svg.'); } $currentYear = now()->year; $currentMonth = sprintf('%02d', now()->month); - $relativeDirectory = "{$currentYear}/{$currentMonth}"; + $relativeDirectory = sprintf('%d/%s', $currentYear, $currentMonth); - $filenameWithoutExtension = pathinfo($originalName, PATHINFO_FILENAME); - $extension = pathinfo($originalName, PATHINFO_EXTENSION); - $filename = "{$filenameWithoutExtension}.{$extension}"; + $filenameWithoutExtension = pathinfo((string) $originalName, PATHINFO_FILENAME); + $extension = pathinfo((string) $originalName, PATHINFO_EXTENSION); + $filename = sprintf('%s.%s', $filenameWithoutExtension, $extension); $disk = Storage::disk('press'); - $newPath = "{$relativeDirectory}/{$filename}"; + $newPath = sprintf('%s/%s', $relativeDirectory, $filename); $fileSize = $disk->size($newPath); $imageSize = getimagesize($disk->path($newPath)); $imageMeta = [ - 'file' => "{$relativeDirectory}/{$filename}", + 'file' => sprintf('%s/%s', $relativeDirectory, $filename), 'width' => $imageSize[0], 'height' => $imageSize[1], 'filesize' => $fileSize, @@ -90,10 +91,8 @@ public function afterCreate(): void foreach ($metaDataConfig as $metaKey => $defaultValue) { $metaValue = $this->data[$metaKey] ?? $defaultValue; - if ($metaKey === 'mm_sua_attachment_id') { - if ($temporaryFilePath) { - $metaValue = $attachmentId; - } + if ($metaKey === 'mm_sua_attachment_id' && $temporaryFilePath) { + $metaValue = $attachmentId; } if ($this->record instanceof WpUser) { diff --git a/packages/press/src/Resources/WpUserResource/Pages/EditWpUser.php b/packages/press/src/Resources/WpUserResource/Pages/EditWpUser.php index c25662e9d..d14891830 100644 --- a/packages/press/src/Resources/WpUserResource/Pages/EditWpUser.php +++ b/packages/press/src/Resources/WpUserResource/Pages/EditWpUser.php @@ -2,6 +2,7 @@ namespace Moox\Press\Resources\WpUserResource\Pages; +use Exception; use Filament\Actions\DeleteAction; use Filament\Resources\Pages\EditRecord; use Illuminate\Support\Facades\Auth; @@ -12,6 +13,7 @@ use Moox\Press\Models\WpPostMeta; use Moox\Press\Models\WpUser; use Moox\Press\Resources\WpUserResource; +use Override; use Symfony\Component\Mime\MimeTypes; class EditWpUser extends EditRecord @@ -23,6 +25,7 @@ protected function getHeaderActions(): array return [DeleteAction::make()]; } + #[Override] protected function mutateFormDataBeforeFill(array $data): array { $user = WpUser::with(['userMeta', 'attachment'])->find($data['ID']); @@ -76,7 +79,7 @@ protected function afterSave(): void Log::error('User record is not an instance of WpUser in EditWpUser::afterSave'); } - Event::dispatch('eloquent.updated: '.get_class($this->record), $this->record); + Event::dispatch('eloquent.updated: '.($this->record !== null ? $this->record::class : self::class), $this->record); } protected function handleAvatarUpload(WpUser $user, ?string $userAvatarMetaKey): void @@ -89,19 +92,19 @@ protected function handleAvatarUpload(WpUser $user, ?string $userAvatarMetaKey): $mimeType = $mimeTypes->guessMimeType(storage_path('app/'.$temporaryFilePath)); if (! in_array($mimeType, ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'])) { - throw new \Exception('The file must be an image of type: jpeg, png, gif, webp, or svg.'); + throw new Exception('The file must be an image of type: jpeg, png, gif, webp, or svg.'); } $currentYear = now()->year; $currentMonth = sprintf('%02d', now()->month); - $relativeDirectory = "{$currentYear}/{$currentMonth}"; + $relativeDirectory = sprintf('%d/%s', $currentYear, $currentMonth); - $filenameWithoutExtension = pathinfo($originalName, PATHINFO_FILENAME); - $extension = pathinfo($originalName, PATHINFO_EXTENSION); - $filename = "{$filenameWithoutExtension}.{$extension}"; + $filenameWithoutExtension = pathinfo((string) $originalName, PATHINFO_FILENAME); + $extension = pathinfo((string) $originalName, PATHINFO_EXTENSION); + $filename = sprintf('%s.%s', $filenameWithoutExtension, $extension); $disk = Storage::disk('press'); - $newPath = "{$relativeDirectory}/{$filename}"; + $newPath = sprintf('%s/%s', $relativeDirectory, $filename); $disk->put($newPath, Storage::get($temporaryFilePath)); diff --git a/packages/press/src/Resources/WpUserResource/Pages/ViewWpUser.php b/packages/press/src/Resources/WpUserResource/Pages/ViewWpUser.php index 3ed8a5726..8d6f50e1b 100644 --- a/packages/press/src/Resources/WpUserResource/Pages/ViewWpUser.php +++ b/packages/press/src/Resources/WpUserResource/Pages/ViewWpUser.php @@ -7,6 +7,7 @@ use Filament\Resources\Pages\ViewRecord; use Moox\Press\Models\WpUser; use Moox\Press\Resources\WpUserResource; +use Override; class ViewWpUser extends ViewRecord { @@ -17,6 +18,7 @@ protected function getHeaderActions(): array return [EditAction::make(), DeleteAction::make()]; } + #[Override] protected function mutateFormDataBeforeFill(array $data): array { $user = WpUser::with(['userMeta', 'attachment'])->find($data['ID']); diff --git a/packages/press/src/Resources/WpUserResource/RelationManagers/WpUserMetaRelationManager.php b/packages/press/src/Resources/WpUserResource/RelationManagers/WpUserMetaRelationManager.php index 04673e5cc..39f312b93 100644 --- a/packages/press/src/Resources/WpUserResource/RelationManagers/WpUserMetaRelationManager.php +++ b/packages/press/src/Resources/WpUserResource/RelationManagers/WpUserMetaRelationManager.php @@ -8,11 +8,12 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class WpUserMetaRelationManager extends RelationManager { @@ -20,6 +21,7 @@ class WpUserMetaRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -65,12 +67,12 @@ public function table(Table $table): Table return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('meta_key') + TextColumn::make('meta_key') ->label(__('core::core.meta_key')) ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('meta_value') + TextColumn::make('meta_value') ->label(__('core::core.meta_value')) ->toggleable() ->searchable() diff --git a/packages/press/src/Services/Login.php b/packages/press/src/Services/Login.php index d5c726400..60e30cbcf 100644 --- a/packages/press/src/Services/Login.php +++ b/packages/press/src/Services/Login.php @@ -23,13 +23,17 @@ use Illuminate\Support\HtmlString; use Illuminate\Validation\ValidationException; use Jenssegers\Agent\Agent; +use Moox\UserDevice\Services\UserDeviceTracker; +use Moox\UserSession\Services\SessionRelationService; +use Override; /** * @property Form $form */ class Login extends SimplePage { - use InteractsWithFormActions, WithRateLimiting; + use InteractsWithFormActions; + use WithRateLimiting; protected $userDeviceTracker; @@ -47,12 +51,12 @@ class Login extends SimplePage public function __construct() { - if (class_exists(\Moox\UserDevice\Services\UserDeviceTracker::class)) { - $this->userDeviceTracker = app(\Moox\UserDevice\Services\UserDeviceTracker::class); + if (class_exists(UserDeviceTracker::class)) { + $this->userDeviceTracker = app(UserDeviceTracker::class); } - if (class_exists(\Moox\UserSession\Services\SessionRelationService::class)) { - $this->sessionRelationService = app(\Moox\UserSession\Services\SessionRelationService::class); + if (class_exists(SessionRelationService::class)) { + $this->sessionRelationService = app(SessionRelationService::class); } } @@ -113,10 +117,10 @@ public function authenticate(): Redirector|RedirectResponse|LoginResponse|null $data = $this->form->getState(); $credentials = $this->getCredentialsFromFormData($data); $credentialKey = array_key_first($credentials); - $guardProvider = config("auth.guards.$guardName.provider"); - $userModel = config("auth.providers.$guardProvider.model"); - $userModelUsername = config("press.auth.$guardName.username"); - $userModelEmail = config("press.auth.$guardName.email"); + $guardProvider = config(sprintf('auth.guards.%s.provider', $guardName)); + $userModel = config(sprintf('auth.providers.%s.model', $guardProvider)); + $userModelUsername = config(sprintf('press.auth.%s.username', $guardName)); + $userModelEmail = config(sprintf('press.auth.%s.email', $guardName)); $query = $userModel::query(); if (! empty($userModelUsername) && $credentialKey === 'name') { @@ -134,15 +138,12 @@ public function authenticate(): Redirector|RedirectResponse|LoginResponse|null $user = $query->first(); if (config('press.wpModel') && $user instanceof (config('press.wpModel'))) { - $wpAuthService = new \Moox\Press\Services\WordPressAuthService; - + $wpAuthService = new WordPressAuthService; if (! $wpAuthService->checkPassword($credentials['password'], $user->user_pass)) { $this->throwFailureValidationException(); } - } else { - if (! Auth::guard($guardName)->attempt($credentials, $data['remember'] ?? false)) { - $this->throwFailureValidationException(); - } + } elseif (! Auth::guard($guardName)->attempt($credentials, $data['remember'] ?? false)) { + $this->throwFailureValidationException(); } Auth::guard($guardName)->login($user, $data['remember'] ?? false); @@ -163,8 +164,8 @@ public function authenticate(): Redirector|RedirectResponse|LoginResponse|null && config('press.auth_wordpress') === true ) { $payload = base64_encode($user->ID); - $signature = hash_hmac('sha256', $payload, env('APP_KEY')); - $token = "{$payload}.{$signature}"; + $signature = hash_hmac('sha256', $payload, (string) env('APP_KEY')); + $token = sprintf('%s.%s', $payload, $signature); $redirectTarget = config('press.redirect_after_login', 'wp-admin'); $redirectParam = $redirectTarget === 'frontend' ? '&redirect_to=frontend' : ''; @@ -242,11 +243,13 @@ public function registerAction(): Action ->url(filament()->getRegistrationUrl()); } + #[Override] public function getTitle(): string|Htmlable { return __('filament-panels::pages/auth/login.title'); } + #[Override] public function getHeading(): string|Htmlable { return __('filament-panels::pages/auth/login.heading'); @@ -284,6 +287,7 @@ private function isWhitelisted(): bool if (is_array($ipWhiteList) && in_array($ipAddress, $ipWhiteList)) { return true; } + if ($ipWhiteList === $ipAddress) { return true; } diff --git a/packages/press/src/Services/WordPressAuthService.php b/packages/press/src/Services/WordPressAuthService.php index 10ede8ca2..2cd912fb4 100644 --- a/packages/press/src/Services/WordPressAuthService.php +++ b/packages/press/src/Services/WordPressAuthService.php @@ -6,19 +6,19 @@ class WordPressAuthService { - protected $hasher; + protected PasswordHash $hasher; public function __construct() { $this->hasher = new PasswordHash(8, true); } - public function hashPassword($password) + public function hashPassword(string $password): string { return $this->hasher->HashPassword($password); } - public function checkPassword($password, $hashedPassword) + public function checkPassword(string $password, $hashedPassword): bool { return $this->hasher->CheckPassword($password, $hashedPassword); } diff --git a/packages/press/src/Transformer/WpUserTransformer.php b/packages/press/src/Transformer/WpUserTransformer.php index 187173bcc..6e9c404aa 100644 --- a/packages/press/src/Transformer/WpUserTransformer.php +++ b/packages/press/src/Transformer/WpUserTransformer.php @@ -5,12 +5,13 @@ use Moox\Core\Traits\LogLevel; use Moox\Press\Models\WpUser; use Moox\Sync\Transformer\AbstractTransformer; +use Override; class WpUserTransformer extends AbstractTransformer { use LogLevel; - protected $wpUser; + protected WpUser $wpUser; public function __construct(WpUser $wpUser) { @@ -43,7 +44,7 @@ protected function transformCustomFields(array $data): array $metaFields = $this->getMetaFields(); foreach ($metaFields as $metaKey) { if (! isset($data[$metaKey])) { - $data[$metaKey] = $this->wpUser->getMeta($metaKey) ?? config("press.default_user_meta.{$metaKey}", ''); + $data[$metaKey] = $this->wpUser->getMeta($metaKey) ?? config('press.default_user_meta.'.$metaKey, ''); } } @@ -63,16 +64,19 @@ protected function getMainFields(): array ]; } + #[Override] protected function getMetaFields(): array { return array_keys(config('press.default_user_meta', [])); } + #[Override] public function getDelay(): int { return 1; } + #[Override] public function transform(): array { $this->logDebug('WpUserTransformer: Starting transformation', ['user_id' => $this->wpUser->ID]); diff --git a/packages/press/wordpress/plugins/moox-press/moox-press.php b/packages/press/wordpress/plugins/moox-press/moox-press.php index ab4301f91..f4a7ad436 100644 --- a/packages/press/wordpress/plugins/moox-press/moox-press.php +++ b/packages/press/wordpress/plugins/moox-press/moox-press.php @@ -39,16 +39,15 @@ $redirectAfterLogin = REDIRECT_AFTER_LOGIN; } -function moox_lock_wp_frontend() +function moox_lock_wp_frontend(): void { global $lockWp; - if ($lockWp === 'true') { - if (! is_user_logged_in() && $GLOBALS['pagenow'] !== 'wp-login.php') { - auth_redirect(); - } + if ($lockWp === 'true' && (! is_user_logged_in() && $GLOBALS['pagenow'] !== 'wp-login.php')) { + auth_redirect(); } } + add_action('template_redirect', 'moox_lock_wp_frontend'); /* @@ -92,7 +91,7 @@ function moox_auth_token() add_action('init', 'moox_auth_token'); */ -function moox_redirect_logout() +function moox_redirect_logout(): void { global $redirectLogout; @@ -106,11 +105,12 @@ function moox_redirect_logout() } } } + add_action('init', 'moox_redirect_logout'); /* Uses the Moox (Laravel) login page */ -function moox_redirect_login() +function moox_redirect_login(): void { global $redirectLogin; global $adminSlug; @@ -124,9 +124,10 @@ function moox_redirect_login() } } } + add_action('init', 'moox_redirect_login'); -function enqueue_moox_admin_script() +function enqueue_moox_admin_script(): void { global $redirectEditor; @@ -140,9 +141,10 @@ function enqueue_moox_admin_script() ); } } + add_action('admin_enqueue_scripts', 'enqueue_moox_admin_script'); -function decrypt_laravel_data($encryptedData) +function decrypt_laravel_data($encryptedData): ?string { $key = defined('LARAVEL_KEY') ? LARAVEL_KEY : null; if (! $key) { @@ -152,13 +154,13 @@ function decrypt_laravel_data($encryptedData) } // Decode the base64 encoded key - $key = base64_decode(substr($key, 7)); + $key = base64_decode(substr((string) $key, 7)); error_log('Decoded key length: '.strlen($key)); $cipher = 'AES-256-CBC'; $ivLength = openssl_cipher_iv_length($cipher); - $data = base64_decode($encryptedData); + $data = base64_decode((string) $encryptedData); error_log('Base64 decoded data length: '.strlen($data)); $iv = substr($data, 0, $ivLength); @@ -178,12 +180,13 @@ function decrypt_laravel_data($encryptedData) return $decrypted !== false ? $decrypted : null; } -function moox_check_laravel_db_session() +function moox_check_laravel_db_session(): void { static $already_checked = false; if ($already_checked || did_action('moox_session_checked')) { return; } + $already_checked = true; do_action('moox_session_checked'); @@ -191,7 +194,7 @@ function moox_check_laravel_db_session() if (isset($_COOKIE['moox_session'])) { $encryptedSession = $_COOKIE['moox_session']; - $sessionData = json_decode(base64_decode($encryptedSession), true); + $sessionData = json_decode(base64_decode((string) $encryptedSession), true); error_log('Found moox_session: '.$encryptedSession); @@ -238,7 +241,7 @@ function moox_check_laravel_db_session() } } -function get_user_id_from_laravel_session($sessionId) +function get_user_id_from_laravel_session(string $sessionId) { error_log('Attempting to get user ID for session: '.$sessionId); @@ -249,9 +252,9 @@ function get_user_id_from_laravel_session($sessionId) $pass = DB_PASSWORD; $charset = DB_CHARSET; - error_log("Attempting to connect to Laravel database: host=$host, db=$db, user=$user"); + error_log(sprintf('Attempting to connect to Laravel database: host=%s, db=%s, user=%s', $host, $db, $user)); - $dsn = "mysql:host=$host;dbname=$db;charset=$charset"; + $dsn = sprintf('mysql:host=%s;dbname=%s;charset=%s', $host, $db, $charset); $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, @@ -268,13 +271,13 @@ function get_user_id_from_laravel_session($sessionId) $result = $stmt->fetch(); if ($result) { - $payload = unserialize(base64_decode($result['payload'])); + $payload = unserialize(base64_decode((string) $result['payload'])); error_log('Session payload: '.print_r($payload, true)); // Look for a key that starts with 'login_press_' $loginPressKey = null; foreach ($payload as $key => $value) { - if (strpos($key, 'login_press_') === 0) { + if (str_starts_with((string) $key, 'login_press_')) { $loginPressKey = $key; break; } @@ -295,8 +298,8 @@ function get_user_id_from_laravel_session($sessionId) return null; } - } catch (\PDOException $e) { - error_log('Database connection error: '.$e->getMessage()); + } catch (PDOException $pdoException) { + error_log('Database connection error: '.$pdoException->getMessage()); error_log('DSN: '.$dsn); return null; diff --git a/packages/press/wordpress/wp-config.php b/packages/press/wordpress/wp-config.php index 79f71a839..d60dbc3f8 100644 --- a/packages/press/wordpress/wp-config.php +++ b/packages/press/wordpress/wp-config.php @@ -6,7 +6,7 @@ $dotenv = Dotenv::createImmutable(__DIR__.'/../../'); $dotenv->load(); -$isCli = (php_sapi_name() == 'cli'); +$isCli = (PHP_SAPI === 'cli'); if ($isCli) { $env = [ @@ -107,23 +107,23 @@ define('MOOX_HASH', $env['MOOX_HASH']); define('ADMIN_SLUG', $env['ADMIN_SLUG']); -define('LOCK_WP', isset($env['LOCK_WP']) ? $env['LOCK_WP'] : false); -define('AUTH_WP', isset($env['AUTH_WP']) ? $env['AUTH_WP'] : false); -define('REDIRECT_AFTER_LOGIN', isset($env['REDIRECT_AFTER_LOGIN']) ? $env['REDIRECT_AFTER_LOGIN'] : 'wp-admin'); -define('REDIRECT_INDEX', isset($env['REDIRECT_INDEX']) ? $env['REDIRECT_INDEX'] : false); -define('REDIRECT_TO_WP', isset($env['REDIRECT_TO_WP']) ? $env['REDIRECT_TO_WP'] : false); -define('REDIRECT_LOGIN', isset($env['REDIRECT_LOGIN']) ? $env['REDIRECT_LOGIN'] : false); -define('REDIRECT_LOGOUT', isset($env['REDIRECT_LOGOUT']) ? $env['REDIRECT_LOGOUT'] : false); -define('FORGOT_PASSWORD', isset($env['FORGOT_PASSWORD']) ? $env['FORGOT_PASSWORD'] : false); -define('REDIRECT_EDITOR', isset($env['REDIRECT_EDITOR']) ? $env['REDIRECT_EDITOR'] : false); -define('REGISTRATION', isset($env['REGISTRATION']) ? $env['REGISTRATION'] : false); -define('ENABLE_MFA', isset($env['ENABLE_MFA']) ? $env['ENABLE_MFA'] : false); +define('LOCK_WP', $env['LOCK_WP'] ?? false); +define('AUTH_WP', $env['AUTH_WP'] ?? false); +define('REDIRECT_AFTER_LOGIN', $env['REDIRECT_AFTER_LOGIN'] ?? 'wp-admin'); +define('REDIRECT_INDEX', $env['REDIRECT_INDEX'] ?? false); +define('REDIRECT_TO_WP', $env['REDIRECT_TO_WP'] ?? false); +define('REDIRECT_LOGIN', $env['REDIRECT_LOGIN'] ?? false); +define('REDIRECT_LOGOUT', $env['REDIRECT_LOGOUT'] ?? false); +define('FORGOT_PASSWORD', $env['FORGOT_PASSWORD'] ?? false); +define('REDIRECT_EDITOR', $env['REDIRECT_EDITOR'] ?? false); +define('REGISTRATION', $env['REGISTRATION'] ?? false); +define('ENABLE_MFA', $env['ENABLE_MFA'] ?? false); -define('WP_DEBUG', ($env['WP_DEBUG'] === 'true' ? true : false)); -define('WP_DEBUG_LOG', ($env['WP_DEBUG_LOG'] === 'true' ? true : false)); -define('WP_DEBUG_DISPLAY', ($env['WP_DEBUG_DISPLAY'] === 'true' ? true : false)); +define('WP_DEBUG', ($env['WP_DEBUG'] === 'true')); +define('WP_DEBUG_LOG', ($env['WP_DEBUG_LOG'] === 'true')); +define('WP_DEBUG_DISPLAY', ($env['WP_DEBUG_DISPLAY'] === 'true')); -define('WP_MEMORY_LIMIT', ($env['WP_MEMORY_LIMIT'] ? $env['WP_MEMORY_LIMIT'] : '512M')); +define('WP_MEMORY_LIMIT', ($env['WP_MEMORY_LIMIT'] ?: '512M')); if (! defined('ABSPATH')) { define('ABSPATH', __DIR__.'/'); diff --git a/packages/security/config/security.php b/packages/security/config/security.php index 50a45d2a6..afa6c3b1c 100644 --- a/packages/security/config/security.php +++ b/packages/security/config/security.php @@ -1,5 +1,7 @@ [ - 'model' => Moox\User\Models\User::class, + 'model' => User::class, ], /* diff --git a/packages/security/src/Auth/Passwords/DatabaseTokenRepository.php b/packages/security/src/Auth/Passwords/DatabaseTokenRepository.php index d960e62fd..010428968 100644 --- a/packages/security/src/Auth/Passwords/DatabaseTokenRepository.php +++ b/packages/security/src/Auth/Passwords/DatabaseTokenRepository.php @@ -4,6 +4,7 @@ use Illuminate\Auth\Passwords\DatabaseTokenRepository as DatabaseTokenRepositoryBase; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; +use Override; class DatabaseTokenRepository extends DatabaseTokenRepositoryBase { @@ -12,6 +13,7 @@ class DatabaseTokenRepository extends DatabaseTokenRepositoryBase * * @return string */ + #[Override] public function create(CanResetPasswordContract $user) { $email = $user->getEmailForPasswordReset(); @@ -34,6 +36,7 @@ public function create(CanResetPasswordContract $user) * @param string $token * @return bool */ + #[Override] public function exists(CanResetPasswordContract $user, $token) { $email = $user->getEmailForPasswordReset(); @@ -45,16 +48,15 @@ public function exists(CanResetPasswordContract $user, $token) ->first(); if ($record) { - $isValid = ! $this->tokenExpired($record->created_at) && + return ! $this->tokenExpired($record->created_at) && $this->hasher->check($token, $record->token); - - return $isValid; } return false; } - public function delete(CanResetPasswordContract $user) + #[Override] + public function delete(CanResetPasswordContract $user): void { $email = $user->getEmailForPasswordReset(); $userType = $this->getUserType($user); @@ -88,8 +90,8 @@ protected function createPayload(string $email, string $token, string $userType) ]; } - protected function getUserType(CanResetPasswordContract $user) + protected function getUserType(CanResetPasswordContract $user): string { - return get_class($user); + return $user::class; } } diff --git a/packages/security/src/Auth/Passwords/PasswordBrokerManager.php b/packages/security/src/Auth/Passwords/PasswordBrokerManager.php index 8b0879386..5dfbaa1ea 100644 --- a/packages/security/src/Auth/Passwords/PasswordBrokerManager.php +++ b/packages/security/src/Auth/Passwords/PasswordBrokerManager.php @@ -3,21 +3,24 @@ namespace Moox\Security\Auth\Passwords; use Illuminate\Auth\Passwords\PasswordBrokerManager as PasswordBrokerManagerBase; +use Illuminate\Auth\Passwords\TokenRepositoryInterface; use Illuminate\Support\Str; +use Override; class PasswordBrokerManager extends PasswordBrokerManagerBase { /** * Create a token repository instance based on the given configuration. * - * @return \Illuminate\Auth\Passwords\TokenRepositoryInterface + * @return TokenRepositoryInterface */ + #[Override] protected function createTokenRepository(array $config) { $key = $this->app['config']['app.key']; if (Str::startsWith($key, 'base64:')) { - $key = base64_decode(substr($key, 7)); + $key = base64_decode(substr((string) $key, 7)); } $connection = $config['connection'] ?? null; diff --git a/packages/security/src/Commands/GetPasswordResetLinksCommand.php b/packages/security/src/Commands/GetPasswordResetLinksCommand.php index 096e712f0..c1395df1c 100644 --- a/packages/security/src/Commands/GetPasswordResetLinksCommand.php +++ b/packages/security/src/Commands/GetPasswordResetLinksCommand.php @@ -16,7 +16,7 @@ public function __construct() parent::__construct(); } - public function handle() + public function handle(): void { $this->info('Starting Sending Reset Password Links'); diff --git a/packages/security/src/Commands/InstallCommand.php b/packages/security/src/Commands/InstallCommand.php index ed6813718..f195cf274 100644 --- a/packages/security/src/Commands/InstallCommand.php +++ b/packages/security/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Security config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing Securitys Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'security-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/security/src/FilamentActions/Passwords/SendPasswordResetLinksBulkAction.php b/packages/security/src/FilamentActions/Passwords/SendPasswordResetLinksBulkAction.php index 4ba908be5..2bf82d758 100644 --- a/packages/security/src/FilamentActions/Passwords/SendPasswordResetLinksBulkAction.php +++ b/packages/security/src/FilamentActions/Passwords/SendPasswordResetLinksBulkAction.php @@ -11,16 +11,19 @@ use Illuminate\Contracts\Auth\CanResetPassword; use Illuminate\Database\Eloquent\Collection; use Moox\Security\Notifications\Passwords\PasswordResetNotification; +use Override; class SendPasswordResetLinksBulkAction extends BulkAction { - use CanCustomizeProcess, WithRateLimiting; + use CanCustomizeProcess; + use WithRateLimiting; public static function getDefaultName(): ?string { return 'sendPasswordResetLinks'; } + #[Override] protected function setUp(): void { parent::setUp(); @@ -28,18 +31,18 @@ protected function setUp(): void $this ->label(__('security::translations.Send Password Reset Links')) ->requiresConfirmation() - ->action(function (Collection $records) { + ->action(function (Collection $records): void { try { $this->rateLimit(2); - } catch (TooManyRequestsException $exception) { + } catch (TooManyRequestsException $tooManyRequestsException) { Notification::make() ->title(__('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled.title', [ - 'seconds' => $exception->secondsUntilAvailable, - 'minutes' => ceil($exception->secondsUntilAvailable / 60), + 'seconds' => $tooManyRequestsException->secondsUntilAvailable, + 'minutes' => ceil($tooManyRequestsException->secondsUntilAvailable / 60), ])) ->body(array_key_exists('body', __('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled') ?: []) ? __('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled.body', [ - 'seconds' => $exception->secondsUntilAvailable, - 'minutes' => ceil($exception->secondsUntilAvailable / 60), + 'seconds' => $tooManyRequestsException->secondsUntilAvailable, + 'minutes' => ceil($tooManyRequestsException->secondsUntilAvailable / 60), ]) : null) ->danger() ->send(); @@ -49,8 +52,8 @@ protected function setUp(): void foreach ($records as $record) { if (! $record instanceof CanResetPassword) { - $recordClass = get_class($record); - throw new Exception("Model [{$recordClass}] must implement [Illuminate\Contracts\Auth\CanResetPassword] interface."); + $recordClass = $record::class; + throw new Exception(sprintf('Model [%s] must implement [Illuminate\Contracts\Auth\CanResetPassword] interface.', $recordClass)); } $user = $record; @@ -60,7 +63,7 @@ protected function setUp(): void if (! method_exists($user, 'notify')) { $userClass = $user::class; - throw new Exception("Model [{$userClass}] does not have a [notify()] method."); + throw new Exception(sprintf('Model [%s] does not have a [notify()] method.', $userClass)); } $notification = new PasswordResetNotification($token); diff --git a/packages/security/src/Helper/PasswordHash.php b/packages/security/src/Helper/PasswordHash.php index 72e0f6f86..1a4700193 100644 --- a/packages/security/src/Helper/PasswordHash.php +++ b/packages/security/src/Helper/PasswordHash.php @@ -29,13 +29,11 @@ // class PasswordHash { - private $itoa64; + private string $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; private $iteration_count_log2; - private $portable_hashes; - - private $random_state; + private string $random_state; /** * Constructor @@ -43,16 +41,13 @@ class PasswordHash * @param int $iteration_count_log2 * @param bool $portable_hashes */ - public function __construct($iteration_count_log2, $portable_hashes) + public function __construct($iteration_count_log2, private $portable_hashes) { - $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) { $iteration_count_log2 = 8; } - $this->iteration_count_log2 = $iteration_count_log2; - $this->portable_hashes = $portable_hashes; + $this->iteration_count_log2 = $iteration_count_log2; $this->random_state = microtime(); if (function_exists('getmypid')) { @@ -63,9 +58,8 @@ public function __construct($iteration_count_log2, $portable_hashes) /** * @param int $iteration_count_log2 * @param bool $portable_hashes - * @return void */ - public function PasswordHash($iteration_count_log2, $portable_hashes) + public function PasswordHash($iteration_count_log2, $portable_hashes): void { self::__construct($iteration_count_log2, $portable_hashes); } @@ -74,7 +68,7 @@ public function PasswordHash($iteration_count_log2, $portable_hashes) * @param int $count * @return string */ - public function get_random_bytes($count) + public function get_random_bytes($count): string|false { $output = ''; if (@is_readable('/dev/urandom') && @@ -90,6 +84,7 @@ public function get_random_bytes($count) md5(microtime().$this->random_state); $output .= md5($this->random_state, true); } + $output = substr($output, 0, $count); } @@ -99,9 +94,8 @@ public function get_random_bytes($count) /** * @param string $input * @param int $count - * @return string */ - public function encode64($input, $count) + public function encode64($input, $count): string { $output = ''; $i = 0; @@ -111,17 +105,21 @@ public function encode64($input, $count) if ($i < $count) { $value |= ord($input[$i]) << 8; } + $output .= $this->itoa64[($value >> 6) & 0x3F]; if ($i++ >= $count) { break; } + if ($i < $count) { $value |= ord($input[$i]) << 16; } + $output .= $this->itoa64[($value >> 12) & 0x3F]; if ($i++ >= $count) { break; } + $output .= $this->itoa64[($value >> 18) & 0x3F]; } while ($i < $count); @@ -130,24 +128,20 @@ public function encode64($input, $count) /** * @param string $input - * @return string */ - public function gensalt_private($input) + public function gensalt_private($input): string { $output = '$P$'; $output .= $this->itoa64[min($this->iteration_count_log2 + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; - $output .= $this->encode64($input, 6); - return $output; + return $output.$this->encode64($input, 6); } /** - * @param string $password * @param string $setting - * @return string */ - public function crypt_private($password, $setting) + public function crypt_private(string $password, $setting): string { $output = '*0'; if (substr($setting, 0, 2) === $output) { @@ -184,16 +178,14 @@ public function crypt_private($password, $setting) } while (--$count); $output = substr($setting, 0, 12); - $output .= $this->encode64($hash, 16); - return $output; + return $output.$this->encode64($hash, 16); } /** * @param string $input - * @return string */ - public function gensalt_blowfish($input) + public function gensalt_blowfish($input): string { // This one needs to use a different order of characters and a // different encoding scheme from the one in encode64() above. @@ -234,14 +226,11 @@ public function gensalt_blowfish($input) return $output; } - /** - * @param string $password - */ - public function HashPassword($password) + public function HashPassword(string $password): string { $random = ''; - if (CRYPT_BLOWFISH === 1 && ! $this->portable_hashes) { + if (! $this->portable_hashes) { $random = $this->get_random_bytes(16); $hash = crypt($password, $this->gensalt_blowfish($random)); @@ -253,6 +242,7 @@ public function HashPassword($password) if (strlen($random) < 6) { $random = $this->get_random_bytes(6); } + $hash = $this->crypt_private($password, $this->gensalt_private($random)); @@ -267,11 +257,9 @@ public function HashPassword($password) } /** - * @param string $password * @param string $stored_hash - * @return bool */ - public function CheckPassword($password, $stored_hash) + public function CheckPassword(string $password, $stored_hash): bool { $hash = $this->crypt_private($password, $stored_hash); if ($hash[0] === '*') { diff --git a/packages/security/src/Jobs/Passwords/SendPasswordResetLinksJob.php b/packages/security/src/Jobs/Passwords/SendPasswordResetLinksJob.php index 5a06b6ce3..571fc6c4e 100644 --- a/packages/security/src/Jobs/Passwords/SendPasswordResetLinksJob.php +++ b/packages/security/src/Jobs/Passwords/SendPasswordResetLinksJob.php @@ -12,25 +12,33 @@ class SendPasswordResetLinksJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 3; - $this->timeout = 300; - $this->maxExceptions = 1; - $this->backoff = 350; - } - - public function handle() + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 3; + + /** + * @var int + */ + public $timeout = 300; + + /** + * @var int + */ + public $maxExceptions = 1; + + /** + * @var int + */ + public $backoff = 350; + + public function handle(): void { $usermodel = config('security.password_reset_links.model'); $users = $usermodel::all(); diff --git a/packages/security/src/Notifications/Passwords/PasswordResetNotification.php b/packages/security/src/Notifications/Passwords/PasswordResetNotification.php index 2d6bdc307..d67bc000f 100644 --- a/packages/security/src/Notifications/Passwords/PasswordResetNotification.php +++ b/packages/security/src/Notifications/Passwords/PasswordResetNotification.php @@ -6,7 +6,10 @@ use Filament\Facades\Filament; use Filament\Panel; use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Auth\Authenticatable; +use Illuminate\Contracts\Auth\CanResetPassword; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; @@ -16,15 +19,15 @@ class PasswordResetNotification extends Notification implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - - public string $token; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; protected Panel $panel; - public function __construct($token) + public function __construct(public string $token) { - $this->token = $token; $this->panel = Filament::getCurrentPanel(); } @@ -33,13 +36,13 @@ public function via($notifiable): array return ['mail']; } - public function toMail($notifiable): MailMessage + public function toMail(CanResetPassword|Model|Authenticatable $notifiable): MailMessage { $mailRecipientName = config('security.mail_recipient_name') ?? 'name'; return (new MailMessage) ->subject(__('security::translations.Reset Password Message')) - ->greeting(__('security::translations.Hello')." {$notifiable->$mailRecipientName},") + ->greeting(__('security::translations.Hello').sprintf(' %s,', $notifiable->$mailRecipientName)) ->line(__('security::translations.You are receiving this email because we received a password reset request for your account.')) ->action(__('security::translations.Reset Password'), $this->resetUrl($notifiable)) ->line(__('security::translations.This password reset link will expire').' '.$this->getReadableExpiryTime().'.') @@ -47,7 +50,7 @@ public function toMail($notifiable): MailMessage ->salutation(new HtmlString(__('security::translations.Regards').'
'.config('mail.from.name'))); } - protected function resetUrl($notifiable): string + protected function resetUrl(CanResetPassword|Model|Authenticatable $notifiable): string { return $this->panel->getResetPasswordUrl($this->token, $notifiable); } diff --git a/packages/security/src/PasswordResetServiceProvider.php b/packages/security/src/PasswordResetServiceProvider.php index c3d535363..f03e89e73 100644 --- a/packages/security/src/PasswordResetServiceProvider.php +++ b/packages/security/src/PasswordResetServiceProvider.php @@ -4,6 +4,7 @@ use Illuminate\Auth\Passwords\PasswordResetServiceProvider as PasswordResetServiceProviderBase; use Moox\Security\Auth\Passwords\PasswordBrokerManager; +use Override; class PasswordResetServiceProvider extends PasswordResetServiceProviderBase { @@ -12,14 +13,11 @@ class PasswordResetServiceProvider extends PasswordResetServiceProviderBase * * @return void */ + #[Override] protected function registerPasswordBroker() { - $this->app->singleton('auth.password', function ($app) { - return new PasswordBrokerManager($app); - }); + $this->app->singleton('auth.password', fn ($app): PasswordBrokerManager => new PasswordBrokerManager($app)); - $this->app->bind('auth.password.broker', function ($app) { - return $app->make('auth.password')->broker(); - }); + $this->app->bind('auth.password.broker', fn ($app) => $app->make('auth.password')->broker()); } } diff --git a/packages/security/src/Resources/ResetPasswordResource.php b/packages/security/src/Resources/ResetPasswordResource.php index 2482dbe15..0a8dc616b 100644 --- a/packages/security/src/Resources/ResetPasswordResource.php +++ b/packages/security/src/Resources/ResetPasswordResource.php @@ -12,10 +12,12 @@ use Moox\Security\Models\ResetPassword; use Moox\Security\Resources\ResetPasswordResource\Pages\ListPage; use Moox\Security\Resources\ResetPasswordResource\Widgets\ResetPasswordWidgets; +use Override; class ResetPasswordResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $modelLabel = 'Reset Tokens'; @@ -23,6 +25,7 @@ class ResetPasswordResource extends Resource protected static ?string $navigationIcon = 'gmdi-token'; + #[Override] public static function form(Form $form): Form { return $form @@ -31,6 +34,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -54,6 +58,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -61,6 +66,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -68,6 +74,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -75,31 +82,37 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return config('security.resources.security.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('security.resources.security.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('security.resources.security.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('security.resources.security.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('security.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('security.navigation_sort') + 5; diff --git a/packages/security/src/Resources/ResetPasswordResource/Pages/ListPage.php b/packages/security/src/Resources/ResetPasswordResource/Pages/ListPage.php index 7e0580680..a6f1a4832 100644 --- a/packages/security/src/Resources/ResetPasswordResource/Pages/ListPage.php +++ b/packages/security/src/Resources/ResetPasswordResource/Pages/ListPage.php @@ -9,6 +9,7 @@ use Moox\Security\Models\Security; use Moox\Security\Resources\ResetPasswordResource; use Moox\Security\Resources\ResetPasswordResource\Widgets\ResetPasswordWidgets; +use Override; class ListPage extends ListRecords { @@ -16,18 +17,20 @@ class ListPage extends ListRecords public static string $resource = ResetPasswordResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ ResetPasswordWidgets::class, ]; } + #[Override] public function getTitle(): string { return __('security::translations.title'); diff --git a/packages/security/src/SecurityServiceProvider.php b/packages/security/src/SecurityServiceProvider.php index 57e470f5f..ad45b0de8 100644 --- a/packages/security/src/SecurityServiceProvider.php +++ b/packages/security/src/SecurityServiceProvider.php @@ -4,8 +4,10 @@ namespace Moox\Security; +use Illuminate\Auth\Passwords\PasswordResetServiceProvider; use Moox\Security\Commands\GetPasswordResetLinksCommand; use Moox\Security\Commands\InstallCommand; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -22,11 +24,12 @@ public function configurePackage(Package $package): void ->hasCommands(InstallCommand::class, GetPasswordResetLinksCommand::class); } - public function register() + #[Override] + public function register(): void { parent::register(); - $this->app->registerDeferredProvider(\Illuminate\Auth\Passwords\PasswordResetServiceProvider::class); + $this->app->registerDeferredProvider(PasswordResetServiceProvider::class); $this->app->register(\Moox\Security\PasswordResetServiceProvider::class); } diff --git a/packages/security/src/Services/RequestPasswordReset.php b/packages/security/src/Services/RequestPasswordReset.php index 700836b2c..2999239bf 100644 --- a/packages/security/src/Services/RequestPasswordReset.php +++ b/packages/security/src/Services/RequestPasswordReset.php @@ -19,6 +19,7 @@ use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Facades\Password; use Moox\Security\Notifications\Passwords\PasswordResetNotification; +use Override; /** * @property Form $form @@ -51,15 +52,15 @@ public function request(): void { try { $this->rateLimit(2); - } catch (TooManyRequestsException $exception) { + } catch (TooManyRequestsException $tooManyRequestsException) { Notification::make() ->title(__('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled.title', [ - 'seconds' => $exception->secondsUntilAvailable, - 'minutes' => ceil($exception->secondsUntilAvailable / 60), + 'seconds' => $tooManyRequestsException->secondsUntilAvailable, + 'minutes' => ceil($tooManyRequestsException->secondsUntilAvailable / 60), ])) ->body(array_key_exists('body', __('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled') ?: []) ? __('filament-panels::pages/auth/password-reset/request-password-reset.notifications.throttled.body', [ - 'seconds' => $exception->secondsUntilAvailable, - 'minutes' => ceil($exception->secondsUntilAvailable / 60), + 'seconds' => $tooManyRequestsException->secondsUntilAvailable, + 'minutes' => ceil($tooManyRequestsException->secondsUntilAvailable / 60), ]) : null) ->danger() ->send(); @@ -75,7 +76,7 @@ function (CanResetPassword $user, string $token): void { if (! method_exists($user, 'notify')) { $userClass = $user::class; - throw new Exception("Model [{$userClass}] does not have a [notify()] method."); + throw new Exception(sprintf('Model [%s] does not have a [notify()] method.', $userClass)); } $notification = new PasswordResetNotification($token); @@ -144,11 +145,13 @@ public function loginAction(): Action ->url(filament()->getLoginUrl()); } + #[Override] public function getTitle(): string|Htmlable { return __('filament-panels::pages/auth/password-reset/request-password-reset.title'); } + #[Override] public function getHeading(): string|Htmlable { return __('filament-panels::pages/auth/password-reset/request-password-reset.heading'); diff --git a/packages/security/src/Services/ResetPassword.php b/packages/security/src/Services/ResetPassword.php index 274c96800..3f6ed5556 100644 --- a/packages/security/src/Services/ResetPassword.php +++ b/packages/security/src/Services/ResetPassword.php @@ -23,6 +23,7 @@ use Illuminate\Support\Str; use Livewire\Attributes\Locked; use Moox\Security\Helper\PasswordHash; +use Override; /** * @property Form $form @@ -64,15 +65,15 @@ public function resetPassword(): ?PasswordResetResponse { try { $this->rateLimit(2); - } catch (TooManyRequestsException $exception) { + } catch (TooManyRequestsException $tooManyRequestsException) { Notification::make() ->title(__('filament-panels::pages/auth/password-reset/reset-password.notifications.throttled.title', [ - 'seconds' => $exception->secondsUntilAvailable, - 'minutes' => ceil($exception->secondsUntilAvailable / 60), + 'seconds' => $tooManyRequestsException->secondsUntilAvailable, + 'minutes' => ceil($tooManyRequestsException->secondsUntilAvailable / 60), ])) ->body(array_key_exists('body', __('filament-panels::pages/auth/password-reset/reset-password.notifications.throttled') ?: []) ? __('filament-panels::pages/auth/password-reset/reset-password.notifications.throttled.body', [ - 'seconds' => $exception->secondsUntilAvailable, - 'minutes' => ceil($exception->secondsUntilAvailable / 60), + 'seconds' => $tooManyRequestsException->secondsUntilAvailable, + 'minutes' => ceil($tooManyRequestsException->secondsUntilAvailable / 60), ]) : null) ->danger() ->send(); @@ -87,7 +88,7 @@ public function resetPassword(): ?PasswordResetResponse $status = Password::broker(Filament::getAuthPasswordBroker())->reset( $data, - function (CanResetPassword|Model|Authenticatable $user) use ($data) { + function (CanResetPassword|Model|Authenticatable $user) use ($data): void { $passwordHash = new PasswordHash(8, true); $user->forceFill([ 'user_pass' => $passwordHash->HashPassword($data['password']), @@ -156,11 +157,13 @@ protected function getPasswordConfirmationFormComponent(): Component ->dehydrated(false); } + #[Override] public function getTitle(): string|Htmlable { return __('filament-panels::pages/auth/password-reset/reset-password.title'); } + #[Override] public function getHeading(): string|Htmlable { return __('filament-panels::pages/auth/password-reset/reset-password.heading'); diff --git a/packages/skeleton/build.php b/packages/skeleton/build.php index 5d6d7a716..f86c880cc 100644 --- a/packages/skeleton/build.php +++ b/packages/skeleton/build.php @@ -4,7 +4,7 @@ function ask(string $question, string $default = ''): string { - $answer = readline($question.($default ? " ({$default})" : null).': '); + $answer = readline($question.($default !== '' && $default !== '0' ? sprintf(' (%s)', $default) : null).': '); if (! $answer) { return $default; @@ -17,25 +17,22 @@ function confirm(string $question, bool $default = false): bool { $answer = ask($question.' ('.($default ? 'Y/n' : 'y/N').')'); - if (! $answer) { + if ($answer === '' || $answer === '0') { return $default; } return strtolower($answer) === 'y'; } -function isValidPackageName($packageName) +function isValidPackageName($packageName): bool { if (empty($packageName)) { return false; } $reservedName = 'skeleton'; - if (str_contains(strtolower($packageName), $reservedName)) { - return false; - } - return true; + return ! str_contains(strtolower((string) $packageName), $reservedName); } function writeln(string $line): void @@ -61,7 +58,7 @@ function str_after(string $subject, string $search): string function slugify(string $subject): string { - return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $subject), '-')); + return strtolower(trim((string) preg_replace('/[^A-Za-z0-9-]+/', '-', $subject), '-')); } function title_case(string $subject): string @@ -107,7 +104,7 @@ function replace_readme_paragraphs(string $file, string $content): void ); } -function safeUnlink(string $filename) +function safeUnlink(string $filename): void { if (file_exists($filename) && is_file($filename)) { unlink($filename); @@ -173,14 +170,14 @@ function replaceForAllOtherOSes(): array $className = title_case($packageName); $className = ask('Class name', $className); $variableName = lcfirst($className); -$description = ask('Package description', "This is my package {$packageSlug}"); +$description = ask('Package description', 'This is my package '.$packageSlug); writeln('------'); -writeln("Author : {$authorName}"); -writeln("Author Email : {$authorEmail}"); -writeln("Namespace : Moox\\{$className}"); -writeln("Packagename : moox\\{$packageSlug}"); -writeln("Class name : {$className}Plugin"); +writeln('Author : '.$authorName); +writeln('Author Email : '.$authorEmail); +writeln('Namespace : Moox\\'.$className); +writeln('Packagename : moox\\'.$packageSlug); +writeln(sprintf('Class name : %sPlugin', $className)); writeln('------'); writeln('This script will replace the above values in all relevant files in the project directory.'); @@ -201,16 +198,21 @@ function replaceForAllOtherOSes(): array ]); match (true) { - str_contains($file, determineSeparator('src/SkeletonServiceProvider.php')) => rename($file, determineSeparator('./src/'.$className.'ServiceProvider.php')), - str_contains($file, 'README.md') => replace_readme_paragraphs($file, $description), + str_contains((string) $file, determineSeparator('src/SkeletonServiceProvider.php')) => rename($file, determineSeparator('./src/'.$className.'ServiceProvider.php')), + str_contains((string) $file, 'README.md') => replace_readme_paragraphs($file, $description), default => [], }; } + rename(determineSeparator('config/skeleton.php'), determineSeparator('./config/'.$packageSlugWithoutPrefix.'.php')); -confirm('Execute `composer install` and run tests?') && run('composer install && composer test'); +if (confirm('Execute `composer install` and run tests?')) { + run('composer install && composer test'); +} -confirm('Let this script delete itself?', true) && unlink(__FILE__); +if (confirm('Let this script delete itself?', true)) { + unlink(__FILE__); +} writeln(' '); writeln('Moox Builder is finished. Have fun!'); diff --git a/packages/skeleton/tests/ArchTest.php b/packages/skeleton/tests/ArchTest.php index caacfeb8f..3111a3759 100644 --- a/packages/skeleton/tests/ArchTest.php +++ b/packages/skeleton/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\Skeleton') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\Skeleton\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\Skeleton'); arch()->preset()->php(); diff --git a/packages/skeleton/tests/Feature/ExampleTest.php b/packages/skeleton/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/skeleton/tests/Feature/ExampleTest.php +++ b/packages/skeleton/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/skeleton/tests/Pest.php b/packages/skeleton/tests/Pest.php index 3c46a070a..cc168cfc4 100644 --- a/packages/skeleton/tests/Pest.php +++ b/packages/skeleton/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/skeleton/tests/TestCase.php b/packages/skeleton/tests/TestCase.php index 243c3c4ce..a364245ff 100644 --- a/packages/skeleton/tests/TestCase.php +++ b/packages/skeleton/tests/TestCase.php @@ -13,7 +13,7 @@ protected function setUp(): void parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'VendorName\\Skeleton\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn (string $modelName): string => 'VendorName\\Skeleton\\Database\\Factories\\'.class_basename($modelName).'Factory' ); } @@ -24,7 +24,7 @@ protected function getPackageProviders($app) ]; } - public function getEnvironmentSetUp($app) + public function getEnvironmentSetUp($app): void { config()->set('database.default', 'testing'); diff --git a/packages/skeleton/tests/Unit/ExampleTest.php b/packages/skeleton/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/skeleton/tests/Unit/ExampleTest.php +++ b/packages/skeleton/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/slug/tests/ArchTest.php b/packages/slug/tests/ArchTest.php index 56a34ae1f..a0460dcbc 100644 --- a/packages/slug/tests/ArchTest.php +++ b/packages/slug/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\Slug') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\Slug\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\Slug'); arch()->preset()->php(); diff --git a/packages/slug/tests/Feature/ExampleTest.php b/packages/slug/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/slug/tests/Feature/ExampleTest.php +++ b/packages/slug/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/slug/tests/Pest.php b/packages/slug/tests/Pest.php index 3080fb320..25719e273 100644 --- a/packages/slug/tests/Pest.php +++ b/packages/slug/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/slug/tests/TestCase.php b/packages/slug/tests/TestCase.php index ceac9df67..45f33e34d 100644 --- a/packages/slug/tests/TestCase.php +++ b/packages/slug/tests/TestCase.php @@ -13,7 +13,7 @@ protected function setUp(): void parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'VendorName\\Slug\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn (string $modelName): string => 'VendorName\\Slug\\Database\\Factories\\'.class_basename($modelName).'Factory' ); } @@ -24,7 +24,7 @@ protected function getPackageProviders($app) ]; } - public function getEnvironmentSetUp($app) + public function getEnvironmentSetUp($app): void { config()->set('database.default', 'testing'); diff --git a/packages/slug/tests/Unit/ExampleTest.php b/packages/slug/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/slug/tests/Unit/ExampleTest.php +++ b/packages/slug/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/sync/config/sync.php b/packages/sync/config/sync.php index 64f36d15b..689ec78b0 100644 --- a/packages/sync/config/sync.php +++ b/packages/sync/config/sync.php @@ -1,5 +1,14 @@ '\Moox\Sync\Models\Sync', - 'resource' => '\Moox\Sync\Resources\SyncResource', - 'api_controller' => '\Moox\Sync\Http\Controllers\Api\SyncController', + 'model' => Sync::class, + 'resource' => SyncResource::class, + 'api_controller' => SyncController::class, ], 'Platform' => [ 'api' => [ @@ -189,9 +197,9 @@ 'destroy', ], ], - 'model' => '\Moox\Sync\Models\Platform', - 'resource' => '\Moox\Sync\Resources\PlatformResource', - 'api_controller' => '\Moox\Sync\Http\Controllers\Api\PlatformController', + 'model' => Platform::class, + 'resource' => PlatformResource::class, + 'api_controller' => PlatformController::class, ], ], @@ -293,8 +301,8 @@ */ 'models_with_syncable_relations' => [ - 'Moox\User\Models\User', - 'Moox\Press\Models\WpUser' => [ + User::class, + WpUser::class => [ 'Moox\UserSession\Models\Session', ], // Add any other models here @@ -460,7 +468,7 @@ 'file_sync_max_size_http' => 2 * 1024 * 1024, // 5 MB 'file_sync_max_size_rsync' => 50 * 1024 * 1024, // 50 MB, not implemented yet - 'file_sync_chunk_size_http' => 1 * 1024 * 1024, // 1 MB + 'file_sync_chunk_size_http' => 1024 * 1024, // 1 MB /* |-------------------------------------------------------------------------- diff --git a/packages/sync/routes/api.php b/packages/sync/routes/api.php index 9e8f620ab..c486bab06 100644 --- a/packages/sync/routes/api.php +++ b/packages/sync/routes/api.php @@ -1,6 +1,7 @@ prefix('api')->group(function () use ($entity, $config) { + Route::middleware($middleware)->prefix('api')->group(function () use ($entity, $config): void { Route::apiResource(Str::lower($entity), $config['api_controller'])->only($config['api']['active_routes']); }); } } } -Route::middleware('auth.platformtoken')->prefix('api')->group(function () { - Route::get('platform/{id}/sync', [\Moox\Sync\Http\Controllers\Api\PlatformSyncController::class, 'index']); +Route::middleware('auth.platformtoken')->prefix('api')->group(function (): void { + Route::get('platform/{id}/sync', [PlatformSyncController::class, 'index']); }); $webhookPath = config('sync.sync_webhook_url', '/sync-webhook'); diff --git a/packages/sync/src/Commands/InstallCommand.php b/packages/sync/src/Commands/InstallCommand.php index 7c637304d..1e92ed3a8 100644 --- a/packages/sync/src/Commands/InstallCommand.php +++ b/packages/sync/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Sync config already exist. The config will not be published.'); } } @@ -125,22 +126,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -181,12 +182,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/sync/src/Handlers/AbstractSyncHandler.php b/packages/sync/src/Handlers/AbstractSyncHandler.php index fcaf95710..e4b7f25f0 100644 --- a/packages/sync/src/Handlers/AbstractSyncHandler.php +++ b/packages/sync/src/Handlers/AbstractSyncHandler.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Handlers; +use Exception; use Illuminate\Support\Facades\DB; use Moox\Core\Traits\LogLevel; @@ -9,20 +10,9 @@ abstract class AbstractSyncHandler { use LogLevel; - protected $modelClass; + public function __construct(protected string $modelClass, protected array $modelData, protected string $eventType) {} - protected $modelData; - - protected $eventType; - - public function __construct(string $modelClass, array $modelData, string $eventType) - { - $this->modelClass = $modelClass; - $this->modelData = $modelData; - $this->eventType = $eventType; - } - - public function handle() + public function handle(): void { DB::beginTransaction(); @@ -40,13 +30,13 @@ public function handle() DB::commit(); $this->logInfo('Moox Sync: Sync process completed successfully'); - } catch (\Exception $e) { + } catch (Exception $exception) { DB::rollBack(); - $this->logDebug('Moox Sync: Sync failed: '.$e->getMessage(), [ + $this->logDebug('Moox Sync: Sync failed: '.$exception->getMessage(), [ 'model_class' => $this->modelClass, - 'trace' => $e->getTraceAsString(), + 'trace' => $exception->getTraceAsString(), ]); - throw $e; + throw $exception; } } diff --git a/packages/sync/src/Http/Controllers/Api/PlatformController.php b/packages/sync/src/Http/Controllers/Api/PlatformController.php index ba1f1ff0f..b35d0c247 100644 --- a/packages/sync/src/Http/Controllers/Api/PlatformController.php +++ b/packages/sync/src/Http/Controllers/Api/PlatformController.php @@ -17,21 +17,21 @@ public function index() return PlatformResource::collection($platforms); } - public function show($id) + public function show($id): PlatformResource { $platform = Platform::findOrFail($id); return new PlatformResource($platform); } - public function store(Request $request) + public function store(Request $request): PlatformResource { $platform = Platform::create($request->all()); return new PlatformResource($platform); } - public function update(Request $request, $id) + public function update(Request $request, $id): PlatformResource { $platform = Platform::findOrFail($id); $platform->update($request->all()); diff --git a/packages/sync/src/Http/Controllers/Api/PlatformSyncController.php b/packages/sync/src/Http/Controllers/Api/PlatformSyncController.php index 41bb9a31d..801239fa5 100644 --- a/packages/sync/src/Http/Controllers/Api/PlatformSyncController.php +++ b/packages/sync/src/Http/Controllers/Api/PlatformSyncController.php @@ -10,7 +10,7 @@ class PlatformSyncController extends Controller { public function index($platformId) { - $syncs = Sync::whereHas('sourcePlatform', function ($query) use ($platformId) { + $syncs = Sync::whereHas('sourcePlatform', function ($query) use ($platformId): void { $query->where('id', $platformId); })->with(['sourcePlatform', 'targetPlatform'])->get(); diff --git a/packages/sync/src/Http/Controllers/Api/SyncController.php b/packages/sync/src/Http/Controllers/Api/SyncController.php index d780dc89f..9ec0159cb 100644 --- a/packages/sync/src/Http/Controllers/Api/SyncController.php +++ b/packages/sync/src/Http/Controllers/Api/SyncController.php @@ -16,21 +16,21 @@ public function index() return SyncResource::collection($syncs); } - public function show($id) + public function show($id): SyncResource { $sync = Sync::findOrFail($id); return new SyncResource($sync); } - public function store(Request $request) + public function store(Request $request): SyncResource { $sync = Sync::create($request->all()); return new SyncResource($sync); } - public function update(Request $request, $id) + public function update(Request $request, $id): SyncResource { $sync = Sync::findOrFail($id); $sync->update($request->all()); diff --git a/packages/sync/src/Http/Controllers/FileSyncController.php b/packages/sync/src/Http/Controllers/FileSyncController.php index 7a010a79b..ba0ee3444 100644 --- a/packages/sync/src/Http/Controllers/FileSyncController.php +++ b/packages/sync/src/Http/Controllers/FileSyncController.php @@ -23,7 +23,7 @@ public function receiveChunk(Request $request) { $this->validateRequest($request); - $chunkPath = $this->saveTempChunk($request); + $this->saveTempChunk($request); return response()->json(['status' => 'success', 'message' => 'Chunk received']); } @@ -91,15 +91,15 @@ protected function validateRequest(Request $request) } } - protected function saveTempChunk(Request $request) + protected function saveTempChunk(Request $request): string { $chunkPath = $this->getTempChunkPath($request); - Storage::put($chunkPath, base64_decode($request->input('chunk'))); + Storage::put($chunkPath, base64_decode((string) $request->input('chunk'))); return $chunkPath; } - protected function reassembleFile(Request $request) + protected function reassembleFile(Request $request): string { $tempFilePath = $this->getTempFilePath($request); $totalChunks = $request->input('file_data.total_chunks'); @@ -113,10 +113,10 @@ protected function reassembleFile(Request $request) return $tempFilePath; } - protected function isFileExtensionAllowed($filePath) + protected function isFileExtensionAllowed($filePath): bool { $allowedExtensions = config('sync.file_sync_allowed_extensions', []); - $extension = pathinfo($filePath, PATHINFO_EXTENSION); + $extension = pathinfo((string) $filePath, PATHINFO_EXTENSION); return in_array(strtolower($extension), $allowedExtensions); } @@ -134,6 +134,7 @@ protected function cleanupTempFiles(Request $request) $chunkPath = $this->getTempChunkPath($request, $i); Storage::delete($chunkPath); } + Storage::delete($this->getTempFilePath($request)); } @@ -151,29 +152,29 @@ protected function getExistingFileSize(Request $request) return Storage::exists($finalPath) ? Storage::size($finalPath) : 0; } - protected function calculateExistingFileHash(Request $request) + protected function calculateExistingFileHash(Request $request): string { $finalPath = $this->getFinalFilePath($request); - return Storage::exists($finalPath) ? md5(Storage::get($finalPath)) : ''; + return Storage::exists($finalPath) ? md5((string) Storage::get($finalPath)) : ''; } - protected function getTempChunkPath(Request $request, $chunkIndex = null) + protected function getTempChunkPath(Request $request, $chunkIndex = null): string { - $chunkIndex = $chunkIndex ?? $request->input('chunk_index'); + $chunkIndex ??= $request->input('chunk_index'); - return "{$this->tempDirectory}/{$request->input('model_class')}/{$request->input('model_id')}/{$request->input('field')}/chunk_{$chunkIndex}"; + return sprintf('%s/%s/%s/%s/chunk_%s', $this->tempDirectory, $request->input('model_class'), $request->input('model_id'), $request->input('field'), $chunkIndex); } - protected function getTempFilePath(Request $request) + protected function getTempFilePath(Request $request): string { - return "{$this->tempDirectory}/{$request->input('model_class')}/{$request->input('model_id')}/{$request->input('field')}/temp_file"; + return sprintf('%s/%s/%s/%s/temp_file', $this->tempDirectory, $request->input('model_class'), $request->input('model_id'), $request->input('field')); } - protected function getFinalFilePath(Request $request) + protected function getFinalFilePath(Request $request): string { // This method should be implemented based on your application's file storage logic // For example, you might store files in a specific directory structure based on the model and field - return "uploads/{$request->input('model_class')}/{$request->input('model_id')}/{$request->input('field')}/{$request->input('file_data.name')}"; + return sprintf('uploads/%s/%s/%s/%s', $request->input('model_class'), $request->input('model_id'), $request->input('field'), $request->input('file_data.name')); } } diff --git a/packages/sync/src/Http/Controllers/SyncWebhookController.php b/packages/sync/src/Http/Controllers/SyncWebhookController.php index 37d830df6..4703a4184 100644 --- a/packages/sync/src/Http/Controllers/SyncWebhookController.php +++ b/packages/sync/src/Http/Controllers/SyncWebhookController.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Http\Controllers; +use Exception; use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Http; @@ -40,13 +41,13 @@ public function handle(Request $request) } return response()->json(['status' => 'success', 'message' => 'Sync job dispatched']); - } catch (\Exception $e) { + } catch (Exception $exception) { $this->logDebug('SyncWebhookController encountered an error', [ - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), + 'error' => $exception->getMessage(), + 'trace' => $exception->getTraceAsString(), ]); - return response()->json(['status' => 'error', 'message' => $e->getMessage()], 500); + return response()->json(['status' => 'error', 'message' => $exception->getMessage()], 500); } } @@ -89,7 +90,7 @@ protected function fileExists(string $path): bool protected function requestMissingFiles(array $data, array $missingFiles, Platform $sourcePlatform) { $responsePath = config('sync.sync_response_url', '/sync-response'); - $url = "https://{$sourcePlatform->domain}{$responsePath}"; + $url = sprintf('https://%s%s', $sourcePlatform->domain, $responsePath); Http::post($url, [ 'model_class' => $data['model_class'], @@ -128,7 +129,7 @@ protected function shouldSyncFile(array $fileData): bool return true; // For now, always sync the file } - protected function getModelId(array $modelData) + protected function getModelId(array $modelData): ?array { $localIdentifierFields = config('sync.local_identifier_fields', ['ID', 'uuid', 'ulid', 'id']); diff --git a/packages/sync/src/Http/Resources/PlatformResource.php b/packages/sync/src/Http/Resources/PlatformResource.php index 0831727ee..576f176f7 100644 --- a/packages/sync/src/Http/Resources/PlatformResource.php +++ b/packages/sync/src/Http/Resources/PlatformResource.php @@ -3,6 +3,7 @@ namespace Moox\Sync\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; +use Override; /** * @property int $id @@ -20,6 +21,7 @@ */ class PlatformResource extends JsonResource { + #[Override] public function toArray($request): array { return [ diff --git a/packages/sync/src/Http/Resources/SyncResource.php b/packages/sync/src/Http/Resources/SyncResource.php index d214e1746..6d2952c2f 100644 --- a/packages/sync/src/Http/Resources/SyncResource.php +++ b/packages/sync/src/Http/Resources/SyncResource.php @@ -3,6 +3,8 @@ namespace Moox\Sync\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; +use Illuminate\Support\Carbon; +use Override; /** * @property int $id @@ -21,10 +23,11 @@ * @property bool $has_errors * @property string $error_message * @property int $interval - * @property \Illuminate\Support\Carbon $last_sync + * @property Carbon $last_sync */ class SyncResource extends JsonResource { + #[Override] public function toArray($request) { return [ diff --git a/packages/sync/src/Jobs/FileSyncJob.php b/packages/sync/src/Jobs/FileSyncJob.php index b180e0e90..3e2bf6f62 100644 --- a/packages/sync/src/Jobs/FileSyncJob.php +++ b/packages/sync/src/Jobs/FileSyncJob.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Jobs; +use Exception; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; @@ -14,31 +15,15 @@ class FileSyncJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, LogLevel, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use LogLevel; + use Queueable; + use SerializesModels; - protected $modelClass; + public function __construct(protected $modelClass, protected $modelId, protected $field, protected $fileData, protected Platform $sourcePlatform, protected Platform $targetPlatform) {} - protected $modelId; - - protected $field; - - protected $fileData; - - protected $sourcePlatform; - - protected $targetPlatform; - - public function __construct($modelClass, $modelId, $field, $fileData, Platform $sourcePlatform, Platform $targetPlatform) - { - $this->modelClass = $modelClass; - $this->modelId = $modelId; - $this->field = $field; - $this->fileData = $fileData; - $this->sourcePlatform = $sourcePlatform; - $this->targetPlatform = $targetPlatform; - } - - public function handle() + public function handle(): void { try { if (! $this->validateFile()) { @@ -56,21 +41,21 @@ public function handle() } $this->syncFile(); - } catch (\Exception $e) { + } catch (Exception $exception) { Log::error('File sync failed', [ 'model_class' => $this->modelClass, 'model_id' => $this->modelId, 'field' => $this->field, - 'error' => $e->getMessage(), + 'error' => $exception->getMessage(), ]); - throw $e; + throw $exception; } } protected function validateFile(): bool { $allowedExtensions = config('sync.file_sync_allowed_extensions', []); - $extension = pathinfo($this->fileData['path'], PATHINFO_EXTENSION); + $extension = pathinfo((string) $this->fileData['path'], PATHINFO_EXTENSION); return in_array(strtolower($extension), $allowedExtensions); } @@ -97,7 +82,7 @@ protected function shouldSyncFile(): bool protected function syncFile() { - $chunkSize = config('sync.file_sync_chunk_size_http', 1 * 1024 * 1024); // Default to 1MB + $chunkSize = config('sync.file_sync_chunk_size_http', 1024 * 1024); // Default to 1MB $fileSize = $this->fileData['size']; $filePath = $this->fileData['path']; @@ -113,9 +98,9 @@ protected function syncFile() $this->finalizeFileSync(); } - protected function sendChunk($chunk, $chunkIndex, $totalChunks) + protected function sendChunk($chunk, string $chunkIndex, $totalChunks) { - $url = "https://{$this->targetPlatform->domain}/api/file-sync/chunk"; + $url = sprintf('https://%s/api/file-sync/chunk', $this->targetPlatform->domain); $response = Http::withHeaders([ 'X-Platform-Token' => $this->targetPlatform->api_token, @@ -125,17 +110,17 @@ protected function sendChunk($chunk, $chunkIndex, $totalChunks) 'field' => $this->field, 'chunk_index' => $chunkIndex, 'total_chunks' => $totalChunks, - 'chunk' => base64_encode($chunk), + 'chunk' => base64_encode((string) $chunk), ]); if (! $response->successful()) { - throw new \Exception("Failed to send chunk {$chunkIndex}"); + throw new Exception('Failed to send chunk '.$chunkIndex); } } protected function finalizeFileSync() { - $url = "https://{$this->targetPlatform->domain}/api/file-sync/finalize"; + $url = sprintf('https://%s/api/file-sync/finalize', $this->targetPlatform->domain); $response = Http::withHeaders([ 'X-Platform-Token' => $this->targetPlatform->api_token, @@ -147,13 +132,13 @@ protected function finalizeFileSync() ]); if (! $response->successful()) { - throw new \Exception('Failed to finalize file sync'); + throw new Exception('Failed to finalize file sync'); } } protected function checkTargetFileExists(): bool { - $url = "https://{$this->targetPlatform->domain}/api/file-sync/check"; + $url = sprintf('https://%s/api/file-sync/check', $this->targetPlatform->domain); $response = Http::withHeaders([ 'X-Platform-Token' => $this->targetPlatform->api_token, @@ -168,7 +153,7 @@ protected function checkTargetFileExists(): bool protected function getTargetFileSize(): int { - $url = "https://{$this->targetPlatform->domain}/api/file-sync/size"; + $url = sprintf('https://%s/api/file-sync/size', $this->targetPlatform->domain); $response = Http::withHeaders([ 'X-Platform-Token' => $this->targetPlatform->api_token, @@ -188,7 +173,7 @@ protected function getSourceFileHash(): string protected function getTargetFileHash(): string { - $url = "https://{$this->targetPlatform->domain}/api/file-sync/hash"; + $url = sprintf('https://%s/api/file-sync/hash', $this->targetPlatform->domain); $response = Http::withHeaders([ 'X-Platform-Token' => $this->targetPlatform->api_token, diff --git a/packages/sync/src/Jobs/PrepareSyncJob.php b/packages/sync/src/Jobs/PrepareSyncJob.php index ec0ae0688..68487b7e6 100644 --- a/packages/sync/src/Jobs/PrepareSyncJob.php +++ b/packages/sync/src/Jobs/PrepareSyncJob.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Jobs; +use Exception; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; @@ -16,40 +17,23 @@ class PrepareSyncJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, LogLevel, Queueable, SerializesModels; - - protected $identifierField; - - protected $identifierValue; - - protected $modelClass; - - protected $eventType; - - protected $platformId; - - protected $syncConfigurations; + use Dispatchable; + use InteractsWithQueue; + use LogLevel; + use Queueable; + use SerializesModels; protected $sourcePlatform; protected $modelData; - protected $fileFields; - - public function __construct($identifierField, $identifierValue, $modelClass, $eventType, $sourcePlatformId, $relevantSyncs, $fileFields = []) + public function __construct(protected $identifierField, protected $identifierValue, protected $modelClass, protected $eventType, protected $platformId, protected $syncConfigurations, protected $fileFields = []) { - $this->identifierField = $identifierField; - $this->identifierValue = $identifierValue; - $this->modelClass = $modelClass; - $this->eventType = $eventType; - $this->platformId = $sourcePlatformId; - $this->syncConfigurations = $relevantSyncs; - $this->sourcePlatform = Platform::findOrFail($sourcePlatformId); + $this->sourcePlatform = Platform::findOrFail($this->platformId); $this->modelData = $this->findModel()->toArray(); - $this->fileFields = $fileFields; } - public function handle(PlatformRelationService $platformRelationService) + public function handle(PlatformRelationService $platformRelationService): void { $sync = Sync::where('source_model', $this->modelClass) ->where('source_platform_id', $this->sourcePlatform->id) @@ -115,11 +99,11 @@ protected function sendToWebhook(Platform $platform, bool $shouldDelete, array $ 'response_status' => $response->status(), 'response_body' => $response->body(), ]); - } catch (\Exception $e) { + } catch (Exception $exception) { $this->logDebug('Moox Sync: Webhook invocation error', [ 'platform' => $platform->name, - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), + 'error' => $exception->getMessage(), + 'trace' => $exception->getTraceAsString(), ]); } } @@ -132,7 +116,7 @@ protected function transformData($model) 'identifier_value' => $this->identifierValue, ]); - $transformerClass = config("sync.transformer_bindings.{$this->modelClass}"); + $transformerClass = config('sync.transformer_bindings.'.$this->modelClass); if ($transformerClass && class_exists($transformerClass)) { $transformer = new $transformerClass($model); @@ -150,7 +134,7 @@ protected function transformData($model) protected function addFileMetadata(array $data): array { - $fileResolverClass = config("sync.file_sync_resolver.{$this->modelClass}"); + $fileResolverClass = config('sync.file_sync_resolver.'.$this->modelClass); if (! $fileResolverClass || ! class_exists($fileResolverClass)) { return $data; } @@ -166,7 +150,7 @@ protected function addFileMetadata(array $data): array } } - if (! empty($fileData)) { + if ($fileData !== []) { $data['_file_sync'] = $fileData; } @@ -219,7 +203,7 @@ protected function getFullModelData($model) 'identifier_value' => $this->identifierValue, ]); - $transformerClass = config("sync.transformer_bindings.{$this->modelClass}"); + $transformerClass = config('sync.transformer_bindings.'.$this->modelClass); if ($transformerClass && class_exists($transformerClass)) { $transformer = new $transformerClass($model); @@ -265,7 +249,7 @@ protected function invokeWebhooks(array $data) 'response_status' => $response->status(), 'response_body' => $response->body(), ]); - } catch (\Exception $e) { + } catch (Exception $e) { $this->logDebug('Moox Sync: Webhook invocation error', [ 'platform' => $targetPlatform->name, 'error' => $e->getMessage(), diff --git a/packages/sync/src/Jobs/SyncBackupJob.php b/packages/sync/src/Jobs/SyncBackupJob.php index 8fdac45af..514ec6720 100644 --- a/packages/sync/src/Jobs/SyncBackupJob.php +++ b/packages/sync/src/Jobs/SyncBackupJob.php @@ -11,9 +11,12 @@ class SyncBackupJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; - public function handle() + public function handle(): void { $syncs = Sync::where('status', true)->get(); diff --git a/packages/sync/src/Jobs/SyncJob.php b/packages/sync/src/Jobs/SyncJob.php index a4e2f5776..62c82abd2 100644 --- a/packages/sync/src/Jobs/SyncJob.php +++ b/packages/sync/src/Jobs/SyncJob.php @@ -2,6 +2,10 @@ namespace Moox\Sync\Jobs; +use Carbon\Month; +use Carbon\WeekDay; +use DateTimeInterface; +use Exception; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; @@ -15,53 +19,35 @@ class SyncJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, LogLevel, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use LogLevel; + use Queueable; + use SerializesModels; - protected $modelClass; + public function __construct(protected $modelClass, protected $modelData, protected $eventType, protected Platform $sourcePlatform, protected Platform $targetPlatform, protected bool $shouldDelete) {} - protected $modelData; - - protected $eventType; - - protected $sourcePlatform; - - protected $targetPlatform; - - protected $shouldDelete; - - public function __construct($modelClass, $modelData, $eventType, Platform $sourcePlatform, Platform $targetPlatform, bool $shouldDelete) - { - $this->modelClass = $modelClass; - $this->modelData = $modelData; - $this->eventType = $eventType; - $this->sourcePlatform = $sourcePlatform; - $this->targetPlatform = $targetPlatform; - $this->shouldDelete = $shouldDelete; - } - - public function handle() + public function handle(): void { try { if ($this->shouldDelete) { $this->deleteModel(); - } else { + } elseif ($this->modelClass === Platform::class) { // Existing sync logic - if ($this->modelClass === Platform::class) { - $this->syncPlatform(); - } else { - $this->syncModel(); - } + $this->syncPlatform(); + } else { + $this->syncModel(); } - } catch (\Exception $e) { + } catch (Exception $exception) { Log::error('Moox Sync: Error syncing model', [ 'model_class' => $this->modelClass, - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), + 'error' => $exception->getMessage(), + 'trace' => $exception->getTraceAsString(), 'source_platform' => $this->sourcePlatform->id, 'target_platform' => $this->targetPlatform->id, 'should_delete' => $this->shouldDelete, ]); - throw $e; + throw $exception; } } @@ -92,7 +78,7 @@ protected function syncPlatform() protected function syncModel() { - $handlerClass = config("sync.sync_bindings.{$this->modelClass}"); + $handlerClass = config('sync.sync_bindings.'.$this->modelClass); if ($handlerClass && class_exists($handlerClass)) { $handler = new $handlerClass($this->modelClass, $this->modelData, $this->eventType); @@ -134,7 +120,7 @@ protected function formatDatetimeFields($data) return $data; } - protected function formatDatetime($dateString) + protected function formatDatetime(DateTimeInterface|WeekDay|Month|string|int|float|null $dateString): string { return Carbon::parse($dateString)->format('Y-m-d H:i:s'); } @@ -157,6 +143,6 @@ protected function getModelId() 'model_data' => $this->modelData, ]); - throw new \Exception('No valid identifier found for the model'); + throw new Exception('No valid identifier found for the model'); } } diff --git a/packages/sync/src/Jobs/SyncPlatformJob.php b/packages/sync/src/Jobs/SyncPlatformJob.php index aea38c862..0b399134e 100644 --- a/packages/sync/src/Jobs/SyncPlatformJob.php +++ b/packages/sync/src/Jobs/SyncPlatformJob.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Jobs; +use Exception; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; @@ -13,7 +14,11 @@ class SyncPlatformJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, LogLevel, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use LogLevel; + use Queueable; + use SerializesModels; protected $currentPlatform; @@ -22,7 +27,7 @@ public function __construct() $this->currentPlatform = Platform::where('domain', request()->getHost())->first(); } - public function handle() + public function handle(): void { $this->logDebug('SyncPlatformJob handle method entered'); @@ -54,7 +59,7 @@ protected function syncPlatform(Platform $platform) ]); $this->sendWebhook($platform, $targetPlatform); - } catch (\Exception $e) { + } catch (Exception $e) { $this->logDebug('Error syncing platform', [ 'source' => $this->currentPlatform->id, 'platform' => $platform->id, diff --git a/packages/sync/src/Listener/SyncListener.php b/packages/sync/src/Listener/SyncListener.php index dfaa9fa5a..b1fe7f524 100644 --- a/packages/sync/src/Listener/SyncListener.php +++ b/packages/sync/src/Listener/SyncListener.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Listener; +use Exception; use Illuminate\Database\QueryException; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Log; @@ -17,11 +18,8 @@ class SyncListener protected $currentPlatform; - protected $syncService; - - public function __construct(SyncService $syncService) + public function __construct(protected SyncService $syncService) { - $this->syncService = $syncService; $this->setCurrentPlatform(); $this->logInfo('Moox Sync: SyncListener constructed'); } @@ -41,12 +39,12 @@ protected function setCurrentPlatform() } } catch (QueryException $e) { Log::error('Moox Sync: Database error occurred while querying for domain', ['domain' => $domain, 'error' => $e->getMessage()]); - } catch (\Exception $e) { + } catch (Exception $e) { Log::error('Moox Sync: An unexpected error occurred', ['error' => $e->getMessage()]); } } - public function registerListeners() + public function registerListeners(): void { $this->logInfo('Moox Sync: Registering listeners'); if ($this->currentPlatform) { @@ -55,29 +53,30 @@ public function registerListeners() foreach ($syncsToListen as $sync) { $this->registerModelListeners($sync->source_model); } + $this->logInfo('Moox Sync: Listeners registered', ['models' => $syncsToListen->pluck('source_model')]); } else { $this->logDebug('Moox Sync: No listeners registered - current platform not set'); } } - protected function registerModelListeners($modelClass) + protected function registerModelListeners(string $modelClass) { $this->logInfo('Moox Sync: Registering listeners for model', ['model' => $modelClass]); - Event::listen("eloquent.created: {$modelClass}", function ($model) use ($modelClass) { + Event::listen('eloquent.created: '.$modelClass, function ($model) use ($modelClass): void { $localIdentifier = $this->getLocalIdentifier($model); $this->logDebug('Moox Sync: Created event triggered', ['model' => $modelClass, 'local_identifier' => $localIdentifier]); $this->handleModelEvent($model, 'created'); }); - Event::listen("eloquent.updated: {$modelClass}", function ($model) use ($modelClass) { + Event::listen('eloquent.updated: '.$modelClass, function ($model) use ($modelClass): void { $localIdentifier = $this->getLocalIdentifier($model); $this->logDebug('Moox Sync: Updated event triggered', ['model' => $modelClass, 'local_identifier' => $localIdentifier]); $this->handleModelEvent($model, 'updated'); }); - Event::listen("eloquent.deleted: {$modelClass}", function ($model) use ($modelClass) { + Event::listen('eloquent.deleted: '.$modelClass, function ($model) use ($modelClass): void { $localIdentifier = $this->getLocalIdentifier($model); $this->logDebug('Moox Sync: Deleted event triggered', ['model' => $modelClass, 'local_identifier' => $localIdentifier]); $this->handleModelEvent($model, 'deleted'); @@ -87,7 +86,7 @@ protected function registerModelListeners($modelClass) protected function handleModelEvent($model, $eventType) { if (! $this->currentPlatform) { - $this->logDebug('Moox Sync: Model event ignored - current platform not set', ['model' => get_class($model), 'event' => $eventType]); + $this->logDebug('Moox Sync: Model event ignored - current platform not set', ['model' => $model::class, 'event' => $eventType]); return; } @@ -95,19 +94,19 @@ protected function handleModelEvent($model, $eventType) $localIdentifier = $this->getLocalIdentifier($model); if (! $localIdentifier) { - $this->logDebug('Moox Sync: Model event ignored - no local identifier found', ['model' => get_class($model), 'event' => $eventType]); + $this->logDebug('Moox Sync: Model event ignored - no local identifier found', ['model' => $model::class, 'event' => $eventType]); return; } $this->logInfo('Dispatching PrepareSyncJob', [ - 'model' => get_class($model), + 'model' => $model::class, 'local_identifier' => $localIdentifier, 'event' => $eventType, 'platform' => $this->currentPlatform->id, ]); - $transformerClass = config('sync.transformer_bindings.'.get_class($model)); + $transformerClass = config('sync.transformer_bindings.'.$model::class); $delay = 0; if ($transformerClass && class_exists($transformerClass)) { @@ -116,15 +115,13 @@ protected function handleModelEvent($model, $eventType) } $relevantSyncs = Sync::where('source_platform_id', $this->currentPlatform->id) - ->where('source_model', get_class($model)) + ->where('source_model', $model::class) ->where('status', true) ->get() - ->map(function ($sync) { - return [ - 'target_platform_id' => $sync->target_platform_id, - 'target_model' => $sync->target_model, - ]; - }); + ->map(fn ($sync): array => [ + 'target_platform_id' => $sync->target_platform_id, + 'target_model' => $sync->target_model, + ]); $fileFields = []; foreach ($model->getAttributes() as $field => $value) { @@ -140,7 +137,7 @@ protected function handleModelEvent($model, $eventType) PrepareSyncJob::dispatch( $localIdentifier['field'], $localIdentifier['value'], - get_class($model), + $model::class, $eventType, $this->currentPlatform->id, $relevantSyncs, @@ -148,7 +145,7 @@ protected function handleModelEvent($model, $eventType) )->delay(now()->addSeconds($delay)); } - protected function getLocalIdentifier($model) + protected function getLocalIdentifier($model): ?array { $localIdentifierFields = config('sync.local_identifier_fields', ['id', 'ID', 'uuid', 'ulid']); @@ -158,7 +155,7 @@ protected function getLocalIdentifier($model) } } - $this->logDebug('No local identifier found for model', ['model' => get_class($model)]); + $this->logDebug('No local identifier found for model', ['model' => $model::class]); return null; } @@ -167,12 +164,12 @@ protected function isFileField($model, $field) { $fileFieldSearch = config('sync.file_sync_fieldsearch', []); foreach ($fileFieldSearch as $search) { - if (strpos(strtolower($field), strtolower($search)) !== false) { + if (str_contains(strtolower((string) $field), strtolower((string) $search))) { return true; } } - $resolverClass = config('sync.file_sync_resolver.'.get_class($model)); + $resolverClass = config('sync.file_sync_resolver.'.$model::class); if ($resolverClass && class_exists($resolverClass)) { $resolver = new $resolverClass($model); diff --git a/packages/sync/src/Models/Sync.php b/packages/sync/src/Models/Sync.php index 671747091..b23eb62d2 100644 --- a/packages/sync/src/Models/Sync.php +++ b/packages/sync/src/Models/Sync.php @@ -10,7 +10,7 @@ class Sync extends Model /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'status', diff --git a/packages/sync/src/Resolver/AbstractFileResolver.php b/packages/sync/src/Resolver/AbstractFileResolver.php index 4489cd84c..c099147e0 100644 --- a/packages/sync/src/Resolver/AbstractFileResolver.php +++ b/packages/sync/src/Resolver/AbstractFileResolver.php @@ -8,12 +8,7 @@ abstract class AbstractFileResolver implements FileResolverInterface { - protected $model; - - public function __construct(Model $model) - { - $this->model = $model; - } + public function __construct(protected Model $model) {} public function resolve(): array { @@ -45,7 +40,7 @@ public function getFileData(string $field): ?array 'size' => Storage::size($filePath), 'last_modified' => Storage::lastModified($filePath), 'mime_type' => Storage::mimeType($filePath), - 'extension' => pathinfo($filePath, PATHINFO_EXTENSION), + 'extension' => pathinfo((string) $filePath, PATHINFO_EXTENSION), ]; } } diff --git a/packages/sync/src/Resources/PlatformResource.php b/packages/sync/src/Resources/PlatformResource.php index ea16e31c5..7cc2e3328 100644 --- a/packages/sync/src/Resources/PlatformResource.php +++ b/packages/sync/src/Resources/PlatformResource.php @@ -27,6 +27,7 @@ use Moox\Sync\Resources\PlatformResource\Pages\EditPlatform; use Moox\Sync\Resources\PlatformResource\Pages\ListPlatforms; use Moox\Sync\Resources\PlatformResource\Pages\ViewPlatform; +use Override; class PlatformResource extends Resource { @@ -38,6 +39,7 @@ class PlatformResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -60,7 +62,7 @@ public static function form(Form $form): Form ->required() ->unique(ignoreRecord: true) ->live(debounce: 500) - ->afterStateUpdated(function ($state, callable $set) { + ->afterStateUpdated(function ($state, callable $set): void { if (empty($state)) { $set('ip_address', 'The host is not resolvable'); } else { @@ -113,7 +115,7 @@ public static function form(Form $form): Form ->label(__('core::sync.generate_token')) ->icon('gmdi-generating-tokens') ->action('generateToken') - ->hidden(fn ($livewire) => $livewire instanceof ViewRecord) + ->hidden(fn ($livewire): bool => $livewire instanceof ViewRecord) ), Toggle::make('master') @@ -126,7 +128,7 @@ public static function form(Form $form): Form 'lg' => 12, ]) ->reactive() - ->afterStateUpdated(function ($state, callable $set, callable $get) { + ->afterStateUpdated(function ($state, callable $set, callable $get): void { if ($state) { $existingMaster = Platform::where('master', true) ->where('id', '!=', $get('id')) @@ -223,6 +225,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -291,6 +294,7 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return [ @@ -299,6 +303,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -309,26 +314,31 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('sync.resources.platform.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('sync.resources.platform.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('sync.resources.platform.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('sync.resources.platform.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -339,11 +349,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return config('sync.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('sync.navigation_sort') + 2; diff --git a/packages/sync/src/Resources/PlatformResource/Pages/ListPlatforms.php b/packages/sync/src/Resources/PlatformResource/Pages/ListPlatforms.php index 43d795707..7439f72c1 100644 --- a/packages/sync/src/Resources/PlatformResource/Pages/ListPlatforms.php +++ b/packages/sync/src/Resources/PlatformResource/Pages/ListPlatforms.php @@ -9,6 +9,7 @@ use Moox\Sync\Jobs\SyncPlatformJob; use Moox\Sync\Models\Platform; use Moox\Sync\Resources\PlatformResource; +use Override; class ListPlatforms extends ListRecords { @@ -16,11 +17,12 @@ class ListPlatforms extends ListRecords public static string $resource = PlatformResource::class; - public function getActions(): array + protected function getActions(): array { return []; } + #[Override] public function getTitle(): string { return __('sync::translations.platforms'); @@ -30,13 +32,11 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Platform { - return $model::create($data); - }), + ->using(fn (array $data, string $model): Platform => $model::create($data)), // TODO: make configurable, raise the job frequency then to hourly Action::make('Sync Platforms') ->label('Sync Platforms') - ->action(function () { + ->action(function (): void { SyncPlatformJob::dispatch(); }) ->requiresConfirmation() diff --git a/packages/sync/src/Resources/PlatformResource/RelationManagers/SyncsRelationManager.php b/packages/sync/src/Resources/PlatformResource/RelationManagers/SyncsRelationManager.php index 03044644c..04e7d5e46 100644 --- a/packages/sync/src/Resources/PlatformResource/RelationManagers/SyncsRelationManager.php +++ b/packages/sync/src/Resources/PlatformResource/RelationManagers/SyncsRelationManager.php @@ -14,6 +14,7 @@ use Filament\Tables\Actions\EditAction; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Override; class SyncsRelationManager extends RelationManager { @@ -21,6 +22,7 @@ class SyncsRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'syncable_type'; + #[Override] public function form(Form $form): Form { return $form->schema([ diff --git a/packages/sync/src/Resources/SyncResource.php b/packages/sync/src/Resources/SyncResource.php index 49f1dffef..6a1de4f10 100644 --- a/packages/sync/src/Resources/SyncResource.php +++ b/packages/sync/src/Resources/SyncResource.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Resources; +use Exception; use Filament\Forms\Components\Grid; use Filament\Forms\Components\Hidden; use Filament\Forms\Components\Section; @@ -27,6 +28,7 @@ use Moox\Sync\Resources\SyncResource\Pages\ListSyncs; use Moox\Sync\Resources\SyncResource\Pages\ViewSync; use Moox\Sync\Services\ModelCompatibilityChecker; +use Override; class SyncResource extends Resource { @@ -38,7 +40,7 @@ class SyncResource extends Resource protected static ?string $recordTitleAttribute = 'title'; - private static function generateTitle(callable $get) + private static function generateTitle(callable $get): string { if (! $get('source_platform_id') || ! $get('target_platform_id')) { return ''; @@ -54,7 +56,7 @@ private static function generateTitle(callable $get) return ''; } - $title = "{$sourcePlatform->domain} ({$sourceModel}) to {$targetPlatform->domain} ({$targetModel})"; + $title = sprintf('%s (%s) to %s (%s)', $sourcePlatform->domain, $sourceModel, $targetPlatform->domain, $targetModel); if ($usePlatformRelations) { $title .= ' by platform'; @@ -63,7 +65,7 @@ private static function generateTitle(callable $get) return $title; } - private static function updateTitle(callable $set, callable $get) + private static function updateTitle(callable $set, callable $get): void { $title = self::generateTitle($get); $set('title', $title); @@ -71,7 +73,7 @@ private static function updateTitle(callable $set, callable $get) private static function getApiUrl(?Platform $platform): ?string { - return $platform ? "https://{$platform->domain}/api/models" : null; + return $platform instanceof Platform ? sprintf('https://%s/api/models', $platform->domain) : null; } private static function fetchModelsFromApi(string $apiUrl, Platform $platform): array @@ -95,12 +97,12 @@ private static function fetchModelsFromApi(string $apiUrl, Platform $platform): foreach ($data['models'] as $model) { $package = str_replace('Models', ' - ', str_replace('\\', ' ', $model)); if ($package && $model) { - $options["{$package}"] = "{$model}"; + $options[$package] = $model; } } return array_filter(array_flip($options)); // Remove any null values - } catch (\Exception $e) { + } catch (Exception) { Notification::make() ->title('API Error') ->body(__('An error occurred while fetching the models from platform: ').$platform->name.' ('.$platform->domain.')') @@ -111,6 +113,7 @@ private static function fetchModelsFromApi(string $apiUrl, Platform $platform): } } + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -128,14 +131,10 @@ public static function form(Form $form): Form ->rules(['exists:platforms,id']) ->required() ->relationship('sourcePlatform', 'name') - ->options(function () { - return Platform::all()->mapWithKeys(function ($platform) { - return [$platform->id => $platform->name ?? "Platform {$platform->id}"]; - })->toArray(); - }) + ->options(fn () => Platform::all()->mapWithKeys(fn ($platform) => [$platform->id => $platform->name ?? 'Platform '.$platform->id])->toArray()) ->columnSpan(['default' => 12]) ->reactive() - ->afterStateUpdated(function ($state, callable $set, callable $get) { + ->afterStateUpdated(function ($state, callable $set, callable $get): void { $sourceModel = $get('source_model'); $targetPlatformId = $get('target_platform_id'); $targetModel = $get('target_model'); @@ -160,20 +159,18 @@ public static function form(Form $form): Form $options = $apiUrl ? self::fetchModelsFromApi($apiUrl, $sourcePlatform) : []; - return collect($options)->filter(function ($value, $key) { - return $key !== null && $value !== null; - })->toArray(); + return collect($options)->filter(fn ($value, $key): bool => $key !== null && $value !== null)->toArray(); }) ->rules(['max:255']) ->required() ->reactive() ->columnSpan(['default' => 12]) - ->hint(function (callable $get) { + ->hint(function (callable $get): ?HtmlString { $sourcePlatform = Platform::find($get('source_platform_id')); return $sourcePlatform ? new HtmlString('Test API') : null; }) - ->afterStateUpdated(function ($state, callable $set, callable $get) { + ->afterStateUpdated(function ($state, callable $set, callable $get): void { $sourcePlatformId = $get('source_platform_id'); $sourceModel = $get('source_model'); $targetPlatformId = $get('target_platform_id'); @@ -198,14 +195,10 @@ public static function form(Form $form): Form ->rules(['exists:platforms,id']) ->required() ->relationship('targetPlatform', 'name') - ->options(function () { - return Platform::all()->mapWithKeys(function ($platform) { - return [$platform->id => $platform->name ?? "Platform {$platform->id}"]; - })->toArray(); - }) + ->options(fn () => Platform::all()->mapWithKeys(fn ($platform) => [$platform->id => $platform->name ?? 'Platform '.$platform->id])->toArray()) ->columnSpan(['default' => 12]) ->reactive() - ->afterStateUpdated(function ($state, callable $set, callable $get) { + ->afterStateUpdated(function ($state, callable $set, callable $get): void { $sourcePlatformId = $get('source_platform_id'); $sourceModel = $get('source_model'); $targetModel = $get('target_model'); @@ -230,20 +223,18 @@ public static function form(Form $form): Form $options = $apiUrl ? self::fetchModelsFromApi($apiUrl, $targetPlatform) : []; - return collect($options)->filter(function ($value, $key) { - return $key !== null && $value !== null; - })->toArray(); + return collect($options)->filter(fn ($value, $key): bool => $key !== null && $value !== null)->toArray(); }) ->rules(['max:255']) ->required() ->reactive() ->columnSpan(['default' => 12]) - ->hint(function (callable $get) { + ->hint(function (callable $get): ?HtmlString { $targetPlatform = Platform::find($get('target_platform_id')); return $targetPlatform ? new HtmlString('Test API') : null; }) - ->afterStateUpdated(function ($state, callable $set, callable $get) { + ->afterStateUpdated(function ($state, callable $set, callable $get): void { $sourcePlatformId = $get('source_platform_id'); $sourceModel = $get('source_model'); $targetPlatformId = $get('target_platform_id'); @@ -275,7 +266,7 @@ public static function form(Form $form): Form Hidden::make('title') ->rules(['max:255', 'string']) ->required() - ->default(fn (callable $get) => SyncResource::generateTitle($get)) + ->default(fn (callable $get): string => SyncResource::generateTitle($get)) ->reactive(), Hidden::make('models_compatible') @@ -291,7 +282,7 @@ public static function form(Form $form): Form ]); } - private static function checkModelCompatibility(callable $set, callable $get) + private static function checkModelCompatibility(callable $set, callable $get): void { $sourceModel = $get('source_model'); $targetModel = $get('target_model'); @@ -320,6 +311,7 @@ private static function checkModelCompatibility(callable $set, callable $get) } } + #[Override] public static function table(Table $table): Table { return $table @@ -328,12 +320,12 @@ public static function table(Table $table): Table TextColumn::make('sourcePlatformAndModel') ->label(__('core::sync.source_platform_and_model')) ->toggleable() - ->getStateUsing(fn ($record) => "{$record->sourcePlatform->name} ({$record->source_model})") + ->getStateUsing(fn ($record): string => sprintf('%s (%s)', $record->sourcePlatform->name, $record->source_model)) ->limit(50), TextColumn::make('targetPlatformAndModel') ->label(__('core::sync.target_platform_and_model')) ->toggleable() - ->getStateUsing(fn ($record) => "{$record->targetPlatform->name} ({$record->target_model})") + ->getStateUsing(fn ($record): string => sprintf('%s (%s)', $record->targetPlatform->name, $record->target_model)) ->limit(50), IconColumn::make('use_platform_relations') ->label(__('core::sync.use_platform_relations')) @@ -360,6 +352,7 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getPages(): array { return [ @@ -370,26 +363,31 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('sync.resources.sync.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('sync.resources.sync.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('sync.resources.sync.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('sync.resources.sync.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; @@ -400,11 +398,13 @@ public static function getNavigationBadge(): ?string return number_format(static::getModel()::count()); } + #[Override] public static function getNavigationGroup(): ?string { return config('sync.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('sync.navigation_sort') + 1; diff --git a/packages/sync/src/Resources/SyncResource/Pages/ListSyncs.php b/packages/sync/src/Resources/SyncResource/Pages/ListSyncs.php index 7c443a0f5..b3aa4aa9b 100644 --- a/packages/sync/src/Resources/SyncResource/Pages/ListSyncs.php +++ b/packages/sync/src/Resources/SyncResource/Pages/ListSyncs.php @@ -7,6 +7,7 @@ use Moox\Core\Traits\Tabs\TabsInListPage; use Moox\Sync\Models\Sync; use Moox\Sync\Resources\SyncResource; +use Override; class ListSyncs extends ListRecords { @@ -14,11 +15,12 @@ class ListSyncs extends ListRecords public static string $resource = SyncResource::class; - public function getActions(): array + protected function getActions(): array { return []; } + #[Override] public function getTitle(): string { return __('sync::translations.title'); @@ -28,9 +30,7 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Sync { - return $model::create($data); - }), + ->using(fn (array $data, string $model): Sync => $model::create($data)), ]; } diff --git a/packages/sync/src/Services/ModelCompatibilityChecker.php b/packages/sync/src/Services/ModelCompatibilityChecker.php index 7306ea855..cdad5d58d 100644 --- a/packages/sync/src/Services/ModelCompatibilityChecker.php +++ b/packages/sync/src/Services/ModelCompatibilityChecker.php @@ -31,8 +31,8 @@ public static function checkCompatibility(string $sourceModelClass, string $targ $extraColumns = array_diff($targetColumns, $sourceColumns); return [ - 'compatible' => empty($missingColumns), - 'error' => empty($missingColumns) ? null : 'Target model is missing some columns from the source model.', + 'compatible' => $missingColumns === [], + 'error' => $missingColumns === [] ? null : 'Target model is missing some columns from the source model.', 'missingColumns' => $missingColumns, 'extraColumns' => $extraColumns, ]; diff --git a/packages/sync/src/Services/PlatformRelationService.php b/packages/sync/src/Services/PlatformRelationService.php index 441be18d4..b9e6dc420 100644 --- a/packages/sync/src/Services/PlatformRelationService.php +++ b/packages/sync/src/Services/PlatformRelationService.php @@ -3,13 +3,14 @@ namespace Moox\Sync\Services; use Illuminate\Support\Facades\DB; +use InvalidArgumentException; use Moox\Sync\Models\Platform; class PlatformRelationService { public function syncPlatformsForModel($model, array $platformIds): void { - $modelType = get_class($model); + $modelType = $model::class; $modelId = $model->getKey(); DB::table('model_platform') @@ -17,15 +18,13 @@ public function syncPlatformsForModel($model, array $platformIds): void ->where('model_id', $modelId) ->delete(); - $insertData = array_map(function ($platformId) use ($modelType, $modelId) { - return [ - 'model_type' => $modelType, - 'model_id' => $modelId, - 'platform_id' => $platformId, - 'created_at' => now(), - 'updated_at' => now(), - ]; - }, $platformIds); + $insertData = array_map(fn ($platformId): array => [ + 'model_type' => $modelType, + 'model_id' => $modelId, + 'platform_id' => $platformId, + 'created_at' => now(), + 'updated_at' => now(), + ], $platformIds); DB::table('model_platform')->insert($insertData); } @@ -33,14 +32,14 @@ public function syncPlatformsForModel($model, array $platformIds): void public function getPlatformsForModel($modelClassOrInstance, $modelId = null) { if (is_object($modelClassOrInstance)) { - $modelClass = get_class($modelClassOrInstance); + $modelClass = $modelClassOrInstance::class; $modelId = $modelClassOrInstance->getKey(); } else { $modelClass = $modelClassOrInstance; } if ($modelId === null) { - throw new \InvalidArgumentException('Model ID must be provided when passing a class name.'); + throw new InvalidArgumentException('Model ID must be provided when passing a class name.'); } $platformIds = DB::table('model_platform') @@ -51,19 +50,19 @@ public function getPlatformsForModel($modelClassOrInstance, $modelId = null) return Platform::whereIn('id', $platformIds)->get(); } - public function addPlatformToModel($model, Platform $platform) + public function addPlatformToModel($model, Platform $platform): void { DB::table('model_platform')->updateOrInsert([ - 'model_type' => get_class($model), + 'model_type' => $model::class, 'model_id' => $model->getKey(), 'platform_id' => $platform->id, ]); } - public function removePlatformFromModel($model, Platform $platform) + public function removePlatformFromModel($model, Platform $platform): void { DB::table('model_platform')->where([ - 'model_type' => get_class($model), + 'model_type' => $model::class, 'model_id' => $model->getKey(), 'platform_id' => $platform->id, ])->delete(); @@ -72,7 +71,7 @@ public function removePlatformFromModel($model, Platform $platform) public function modelHasPlatform($model, Platform $platform) { return DB::table('model_platform')->where([ - 'model_type' => get_class($model), + 'model_type' => $model::class, 'model_id' => $model->getKey(), 'platform_id' => $platform->id, ])->exists(); diff --git a/packages/sync/src/Services/SyncService.php b/packages/sync/src/Services/SyncService.php index 563dfde97..83f390fdc 100644 --- a/packages/sync/src/Services/SyncService.php +++ b/packages/sync/src/Services/SyncService.php @@ -2,6 +2,7 @@ namespace Moox\Sync\Services; +use Exception; use Illuminate\Support\Facades\Config; use Moox\Core\Traits\LogLevel; use Moox\Sync\Models\Platform; @@ -10,30 +11,23 @@ class SyncService { use LogLevel; - protected $platformRelationService; + public function __construct(protected PlatformRelationService $platformRelationService) {} - public function __construct(PlatformRelationService $platformRelationService) - { - $this->platformRelationService = $platformRelationService; - } - - public function performSync($modelClass, array $modelData, string $eventType, Platform $sourcePlatform, ?Platform $targetPlatform = null) + public function performSync($modelClass, array $modelData, string $eventType, Platform $sourcePlatform, ?Platform $targetPlatform = null): void { $this->logDebug('performSync method entered', [ 'modelClass' => $modelClass, 'eventType' => $eventType, 'sourcePlatform' => $sourcePlatform->id, - 'targetPlatform' => $targetPlatform ? $targetPlatform->id : 'all', + 'targetPlatform' => $targetPlatform instanceof Platform ? $targetPlatform->id : 'all', ]); if ($modelClass === Platform::class) { $this->syncPlatform($modelData, $eventType, $targetPlatform); + } elseif ($targetPlatform instanceof Platform) { + $this->syncToSinglePlatform($modelClass, $modelData, $eventType, $sourcePlatform, $targetPlatform); } else { - if ($targetPlatform) { - $this->syncToSinglePlatform($modelClass, $modelData, $eventType, $sourcePlatform, $targetPlatform); - } else { - $this->syncToAllPlatforms($modelClass, $modelData, $eventType, $sourcePlatform); - } + $this->syncToAllPlatforms($modelClass, $modelData, $eventType, $sourcePlatform); } $this->logDebug('performSync method finished'); @@ -41,7 +35,7 @@ public function performSync($modelClass, array $modelData, string $eventType, Pl protected function syncPlatform(array $platformData, string $eventType, ?Platform $targetPlatform = null) { - if ($targetPlatform) { + if ($targetPlatform instanceof Platform) { $this->updatePlatform($platformData, $targetPlatform); } else { $allPlatforms = Platform::where('id', '!=', $platformData['id'])->get(); @@ -117,7 +111,7 @@ protected function getModelId(array $modelData) } } - throw new \Exception('Unable to determine model identifier'); + throw new Exception('Unable to determine model identifier'); } protected function processSyncEvent($modelClass, array $modelData, string $eventType, Platform $targetPlatform, $sync) @@ -129,17 +123,11 @@ protected function processSyncEvent($modelClass, array $modelData, string $event ]); if ($this->shouldSyncModel($modelClass, $modelData, $targetPlatform, $sync)) { - switch ($eventType) { - case 'created': - case 'updated': - $this->createOrUpdateModel($modelClass, $modelData, $targetPlatform); - break; - case 'deleted': - $this->deleteModel($modelClass, $modelData, $targetPlatform); - break; - default: - $this->logDebug('Unknown event type', ['eventType' => $eventType]); - } + match ($eventType) { + 'created', 'updated' => $this->createOrUpdateModel($modelClass, $modelData, $targetPlatform), + 'deleted' => $this->deleteModel($modelClass, $modelData, $targetPlatform), + default => $this->logDebug('Unknown event type', ['eventType' => $eventType]), + }; } elseif ($sync->use_platform_relations && $eventType !== 'deleted') { // If the model should not be synced but exists on the target, delete it $this->deleteModelIfExists($modelClass, $modelData, $targetPlatform); @@ -161,7 +149,7 @@ protected function deleteModelIfExists($modelClass, array $modelData, Platform $ } } - protected function createOrUpdateModel($modelClass, array $modelData, Platform $targetPlatform) + protected function createOrUpdateModel(string $modelClass, array $modelData, Platform $targetPlatform) { $uniqueFields = config('sync.unique_identifier_fields', ['ulid', 'uuid', 'slug', 'name', 'title']); $uniqueIdentifier = null; @@ -174,7 +162,7 @@ protected function createOrUpdateModel($modelClass, array $modelData, Platform $ } if (! $uniqueIdentifier) { - throw new \Exception("No unique identifier found for model {$modelClass}"); + throw new Exception('No unique identifier found for model '.$modelClass); } $model = $modelClass::updateOrCreate( diff --git a/packages/sync/src/SyncServiceProvider.php b/packages/sync/src/SyncServiceProvider.php index 518793f57..06b4b6304 100644 --- a/packages/sync/src/SyncServiceProvider.php +++ b/packages/sync/src/SyncServiceProvider.php @@ -13,6 +13,7 @@ use Moox\Sync\Jobs\SyncBackupJob; use Moox\Sync\Jobs\SyncPlatformJob; use Moox\Sync\Listener\SyncListener; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -32,6 +33,7 @@ public function configurePackage(Package $package): void ->hasCommand(InstallCommand::class); } + #[Override] public function boot(): void { parent::boot(); @@ -56,7 +58,7 @@ protected function registerSyncPlatformJob(): void $syncPlatformJobConfig = Config::get('sync.sync_platform_job'); if ($syncPlatformJobConfig['enabled']) { - $this->app->booted(function () use ($syncPlatformJobConfig) { + $this->app->booted(function () use ($syncPlatformJobConfig): void { $this->logDebug('Moox Sync: Registering sync platform job'); $schedule = $this->app->make(Schedule::class); @@ -70,7 +72,7 @@ protected function registerSyncBackupJob(): void $syncBackupJobConfig = Config::get('sync.sync_backup_job'); if ($syncBackupJobConfig['enabled']) { - $this->app->booted(function () use ($syncBackupJobConfig) { + $this->app->booted(function () use ($syncBackupJobConfig): void { $this->logDebug('Moox Sync: Registering sync backup job'); $schedule = $this->app->make(Schedule::class); diff --git a/packages/sync/src/Transformer/AbstractTransformer.php b/packages/sync/src/Transformer/AbstractTransformer.php index b975ceeae..0d193cbf0 100644 --- a/packages/sync/src/Transformer/AbstractTransformer.php +++ b/packages/sync/src/Transformer/AbstractTransformer.php @@ -6,14 +6,11 @@ abstract class AbstractTransformer { - protected $query; - protected $model; - public function __construct(Builder $query) + public function __construct(protected Builder $query) { - $this->query = $query; - $this->model = $query->getModel(); + $this->model = $this->query->getModel(); } public function transform(): array diff --git a/packages/tag/config/tag.php b/packages/tag/config/tag.php index e8d87c09c..6774242df 100644 --- a/packages/tag/config/tag.php +++ b/packages/tag/config/tag.php @@ -1,5 +1,7 @@ \App\Models\User::class, + 'user_model' => User::class, /* |-------------------------------------------------------------------------- diff --git a/packages/tag/src/Commands/InstallCommand.php b/packages/tag/src/Commands/InstallCommand.php index 7447541a6..44f2134ba 100644 --- a/packages/tag/src/Commands/InstallCommand.php +++ b/packages/tag/src/Commands/InstallCommand.php @@ -34,7 +34,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -80,6 +80,7 @@ public function publishConfiguration(): void return; } + warning('The Tag config already exist. The config will not be published.'); } } @@ -92,6 +93,7 @@ public function publishMigrations(): void return; } + info('Publishing Tags Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'tag-migrations']); } @@ -128,22 +130,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -184,12 +186,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/tag/src/Models/Tag.php b/packages/tag/src/Models/Tag.php index 83ee6996e..be5414bdf 100644 --- a/packages/tag/src/Models/Tag.php +++ b/packages/tag/src/Models/Tag.php @@ -10,10 +10,12 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\DB; use Moox\Tag\Database\Factories\TagFactory; +use Override; class Tag extends Model { - use HasFactory, SoftDeletes; + use HasFactory; + use SoftDeletes; protected $table = 'tags'; @@ -52,9 +54,10 @@ public function detachAllTaggables(): void DB::table('taggables')->where('tag_id', $this->id)->delete(); } + #[Override] protected static function booted(): void { - static::deleting(function (Tag $tag) { + static::deleting(function (Tag $tag): void { $tag->detachAllTaggables(); }); } diff --git a/packages/tag/src/Resources/TagResource.php b/packages/tag/src/Resources/TagResource.php index 58e217177..17211bd8d 100644 --- a/packages/tag/src/Resources/TagResource.php +++ b/packages/tag/src/Resources/TagResource.php @@ -6,6 +6,7 @@ use Camya\Filament\Forms\Components\TitleWithSlugInput; use Filament\Forms\Components\Actions; +use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\ColorPicker; use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Components\FileUpload; @@ -31,6 +32,7 @@ use Moox\Tag\Resources\TagResource\Pages\EditTag; use Moox\Tag\Resources\TagResource\Pages\ListTags; use Moox\Tag\Resources\TagResource\Pages\ViewTag; +use Override; class TagResource extends Resource { @@ -40,6 +42,7 @@ class TagResource extends Resource protected static ?string $currentTab = null; + #[Override] public static function getEloquentQuery(): Builder { return parent::getEloquentQuery()->withoutGlobalScopes(); @@ -49,6 +52,7 @@ public static function getEloquentQuery(): Builder protected static ?string $authorModel = null; + #[Override] public static function form(Form $form): Form { static::initUserModel(); @@ -76,74 +80,74 @@ public static function form(Form $form): Form Section::make() ->schema([ Actions::make([ - Actions\Action::make('restore') + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof ViewTag), - Actions\Action::make('save') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof ViewTag), + Action::make('save') ->label(__('core::core.save')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire instanceof CreateTag ? $livewire->create() : $livewire->save(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateTag || $livewire instanceof EditTag), - Actions\Action::make('saveAndCreateAnother') + ->visible(fn ($livewire): bool => $livewire instanceof CreateTag || $livewire instanceof EditTag), + Action::make('saveAndCreateAnother') ->label(__('core::core.save_and_create_another')) ->color('secondary') ->button() ->extraAttributes(['class' => 'w-full']) - ->action(function ($livewire) { + ->action(function ($livewire): void { $livewire->saveAndCreateAnother(); }) - ->visible(fn ($livewire) => $livewire instanceof CreateTag), - Actions\Action::make('cancel') + ->visible(fn ($livewire): bool => $livewire instanceof CreateTag), + Action::make('cancel') ->label(__('core::core.cancel')) ->color('secondary') ->outlined() ->extraAttributes(['class' => 'w-full']) - ->url(fn () => static::getUrl('index')) - ->visible(fn ($livewire) => $livewire instanceof CreateTag), - Actions\Action::make('edit') + ->url(fn (): string => static::getUrl('index')) + ->visible(fn ($livewire): bool => $livewire instanceof CreateTag), + Action::make('edit') ->label(__('core::core.edit')) ->color('primary') ->button() ->extraAttributes(['class' => 'w-full']) - ->url(fn ($record) => static::getUrl('edit', ['record' => $record])) - ->visible(fn ($livewire, $record) => $livewire instanceof ViewTag && ! $record->trashed()), - Actions\Action::make('restore') + ->url(fn ($record): string => static::getUrl('edit', ['record' => $record])) + ->visible(fn ($livewire, $record): bool => $livewire instanceof ViewTag && ! $record->trashed()), + Action::make('restore') ->label(__('core::core.restore')) ->color('success') ->button() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->restore()) - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof EditTag), - Actions\Action::make('delete') + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof EditTag), + Action::make('delete') ->label(__('core::core.delete')) ->color('danger') ->link() ->extraAttributes(['class' => 'w-full']) ->action(fn ($record) => $record->delete()) - ->visible(fn ($livewire, $record) => $record && ! $record->trashed() && $livewire instanceof EditTag), + ->visible(fn ($livewire, $record): bool => $record && ! $record->trashed() && $livewire instanceof EditTag), ]), ColorPicker::make('color'), TextInput::make('weight'), TextInput::make('count') ->disabled() - ->visible(fn ($livewire, $record) => ($record && $livewire instanceof EditTag) || ($record && $livewire instanceof ViewTag)), + ->visible(fn ($livewire, $record): bool => ($record && $livewire instanceof EditTag) || ($record && $livewire instanceof ViewTag)), DateTimePicker::make('created_at') ->disabled() - ->visible(fn ($livewire, $record) => ($record && $livewire instanceof EditTag) || ($record && $livewire instanceof ViewTag)), + ->visible(fn ($livewire, $record): bool => ($record && $livewire instanceof EditTag) || ($record && $livewire instanceof ViewTag)), DateTimePicker::make('updated_at') ->disabled() - ->visible(fn ($livewire, $record) => ($record && $livewire instanceof EditTag) || ($record && $livewire instanceof ViewTag)), + ->visible(fn ($livewire, $record): bool => ($record && $livewire instanceof EditTag) || ($record && $livewire instanceof ViewTag)), DateTimePicker::make('deleted_at') ->disabled() - ->visible(fn ($livewire, $record) => $record && $record->trashed() && $livewire instanceof ViewTag), + ->visible(fn ($livewire, $record): bool => $record && $record->trashed() && $livewire instanceof ViewTag), ]), ]) ->columnSpan(['lg' => 1]), @@ -152,6 +156,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { static::initUserModel(); @@ -200,22 +205,15 @@ public static function table(Table $table): Table ->defaultSort('slug', 'desc') ->actions([ ViewAction::make(), - EditAction::make()->hidden(fn () => in_array(static::getCurrentTab(), ['trash', 'deleted'])), + EditAction::make()->hidden(fn (): bool => in_array(static::getCurrentTab(), ['trash', 'deleted'])), ]) ->bulkActions([ - DeleteBulkAction::make()->hidden(function () use ($currentTab) { - $isHidden = in_array($currentTab, ['trash', 'deleted']); - - return $isHidden; - }), - RestoreBulkAction::make()->visible(function () use ($currentTab) { - $isVisible = in_array($currentTab, ['trash', 'deleted']); - - return $isVisible; - }), + DeleteBulkAction::make()->hidden(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), + RestoreBulkAction::make()->visible(fn (): bool => in_array($currentTab, ['trash', 'deleted'])), ]); } + #[Override] public static function getRelations(): array { return [ @@ -223,6 +221,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -233,36 +232,43 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('tag.resources.tag.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('tag.resources.tag.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('tag.resources.tag.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('tag.resources.tag.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return config('tag.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('tag.navigation_sort') + 3; diff --git a/packages/tag/src/Resources/TagResource/Pages/CreateTag.php b/packages/tag/src/Resources/TagResource/Pages/CreateTag.php index cb03bfff5..069961c88 100644 --- a/packages/tag/src/Resources/TagResource/Pages/CreateTag.php +++ b/packages/tag/src/Resources/TagResource/Pages/CreateTag.php @@ -6,11 +6,13 @@ use Filament\Resources\Pages\CreateRecord; use Moox\Tag\Resources\TagResource; +use Override; class CreateTag extends CreateRecord { protected static string $resource = TagResource::class; + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/tag/src/Resources/TagResource/Pages/EditTag.php b/packages/tag/src/Resources/TagResource/Pages/EditTag.php index c226ffec1..cdf22850c 100644 --- a/packages/tag/src/Resources/TagResource/Pages/EditTag.php +++ b/packages/tag/src/Resources/TagResource/Pages/EditTag.php @@ -6,6 +6,7 @@ use Filament\Resources\Pages\EditRecord; use Moox\Tag\Resources\TagResource; +use Override; class EditTag extends EditRecord { @@ -17,6 +18,7 @@ protected function getHeaderActions(): array ]; } + #[Override] protected function getFormActions(): array { return []; diff --git a/packages/tag/src/Resources/TagResource/Pages/ListTags.php b/packages/tag/src/Resources/TagResource/Pages/ListTags.php index 9ff85cf4a..3ebd36885 100644 --- a/packages/tag/src/Resources/TagResource/Pages/ListTags.php +++ b/packages/tag/src/Resources/TagResource/Pages/ListTags.php @@ -11,6 +11,7 @@ use Moox\Core\Traits\Tabs\TabsInListPage; use Moox\Tag\Models\Tag; use Moox\Tag\Resources\TagResource; +use Override; class ListTags extends ListRecords { @@ -22,15 +23,13 @@ protected function getHeaderActions(): array { return [ CreateAction::make() - ->using(function (array $data, string $model): Tag { - return $model::create($data); - }) - ->hidden(fn () => $this->activeTab === 'deleted'), + ->using(fn (array $data, string $model): Tag => $model::create($data)) + ->hidden(fn (): bool => $this->activeTab === 'deleted'), Action::make('emptyTrash') ->label(__('core::core.empty_trash')) ->icon('heroicon-o-trash') ->color('danger') - ->action(function () { + ->action(function (): void { $trashedCount = Tag::onlyTrashed()->count(); Tag::onlyTrashed()->forceDelete(); Notification::make() @@ -40,10 +39,11 @@ protected function getHeaderActions(): array ->send(); }) ->requiresConfirmation() - ->visible(fn () => $this->activeTab === 'deleted' && Tag::onlyTrashed()->exists()), + ->visible(fn (): bool => $this->activeTab === 'deleted' && Tag::onlyTrashed()->exists()), ]; } + #[Override] public function getTitle(): string { return config('tag.resources.tag.plural'); diff --git a/packages/tag/src/Resources/TagResource/Pages/ViewTag.php b/packages/tag/src/Resources/TagResource/Pages/ViewTag.php index dff3f8e1f..7ff1c3ba0 100644 --- a/packages/tag/src/Resources/TagResource/Pages/ViewTag.php +++ b/packages/tag/src/Resources/TagResource/Pages/ViewTag.php @@ -9,6 +9,7 @@ use Filament\Resources\Pages\ViewRecord; use Illuminate\Database\Eloquent\Model; use Moox\Tag\Resources\TagResource; +use Override; class ViewTag extends ViewRecord { @@ -22,6 +23,7 @@ protected function getHeaderActions(): array ]; } + #[Override] public function getTitle(): string { $title = parent::getTitle(); diff --git a/packages/tag/tests/ArchTest.php b/packages/tag/tests/ArchTest.php index 1ba3680c9..abb5ea02f 100644 --- a/packages/tag/tests/ArchTest.php +++ b/packages/tag/tests/ArchTest.php @@ -1,5 +1,7 @@ expect('Moox\Tag') ->toUseStrictTypes() @@ -8,7 +10,7 @@ arch() ->expect('Moox\Tag\Models') ->toBeClasses() - ->toExtend('Illuminate\Database\Eloquent\Model') + ->toExtend(Model::class) ->toOnlyBeUsedIn('Moox\Tag'); arch()->preset()->php(); diff --git a/packages/tag/tests/Feature/ExampleTest.php b/packages/tag/tests/Feature/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/tag/tests/Feature/ExampleTest.php +++ b/packages/tag/tests/Feature/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/tag/tests/Pest.php b/packages/tag/tests/Pest.php index b144630d8..1fc33e760 100644 --- a/packages/tag/tests/Pest.php +++ b/packages/tag/tests/Pest.php @@ -15,11 +15,11 @@ */ pest()->extends(TestCase::class) - ->beforeEach(function () { + ->beforeEach(function (): void { $this->artisan('migrate'); $user = User::factory()->create(); $this->actingAs($user); - })->afterEach(function () { + })->afterEach(function (): void { $this->artisan('db:wipe'); $this->artisan('optimize:clear'); })->in('Feature'); diff --git a/packages/tag/tests/Unit/ExampleTest.php b/packages/tag/tests/Unit/ExampleTest.php index 61cd84c32..f3aef8edd 100644 --- a/packages/tag/tests/Unit/ExampleTest.php +++ b/packages/tag/tests/Unit/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/packages/tag/workbench/app/Models/.gitkeep b/packages/tag/workbench/app/Models/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/tag/workbench/app/Models/User.php b/packages/tag/workbench/app/Models/User.php deleted file mode 100644 index f241576b9..000000000 --- a/packages/tag/workbench/app/Models/User.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - protected $fillable = [ - 'name', - 'email', - 'password', - ]; - - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ - protected $hidden = [ - 'password', - 'remember_token', - ]; - - /** - * The attributes that should be cast. - * - * @var array - */ - protected $casts = [ - 'email_verified_at' => 'datetime', - 'password' => 'hashed', - ]; - - /** - * Determine if the user can access the Filament panel. - */ - public function canAccessPanel(Panel $panel): bool - { - return true; - } - - /** - * This method determines if the user can access the Filament panel. - * It always returns true, indicating that all users have access to the panel. - */ - protected static function newFactory() - { - return \Workbench\Database\Factories\UserFactory::new(); - } -} diff --git a/packages/tag/workbench/app/Providers/AdminPanelProvider.php b/packages/tag/workbench/app/Providers/AdminPanelProvider.php deleted file mode 100644 index 2d3ebd050..000000000 --- a/packages/tag/workbench/app/Providers/AdminPanelProvider.php +++ /dev/null @@ -1,63 +0,0 @@ -default() - ->id('admin') - ->path('admin') - ->passwordReset() - ->login() - ->colors([ - 'primary' => Color::Amber, - ]) - ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources') - ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages') - ->pages([ - Pages\Dashboard::class, - ]) - ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets') - ->widgets([ - Widgets\AccountWidget::class, - Widgets\FilamentInfoWidget::class, - ]) - ->middleware([ - EncryptCookies::class, - AddQueuedCookiesToResponse::class, - StartSession::class, - AuthenticateSession::class, - ShareErrorsFromSession::class, - VerifyCsrfToken::class, - SubstituteBindings::class, - DisableBladeIconComponents::class, - DispatchServingFilamentEvent::class, - ]) - ->authMiddleware([ - Authenticate::class, - ]) - ->spa() - ->plugins([ - \Moox\Tag\TagPlugin::make(), - ]); - } -} diff --git a/packages/tag/workbench/app/Providers/WorkbenchServiceProvider.php b/packages/tag/workbench/app/Providers/WorkbenchServiceProvider.php deleted file mode 100644 index e8cec9c2a..000000000 --- a/packages/tag/workbench/app/Providers/WorkbenchServiceProvider.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -class UserFactory extends Factory -{ - /** - * The current password being used by the factory. - */ - protected static ?string $password; - - /** - * The name of the factory's corresponding model. - * - * @var class-string - */ - protected $model = User::class; - - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - 'name' => fake()->name(), - 'email' => fake()->unique()->safeEmail(), - 'email_verified_at' => now(), - 'password' => static::$password ??= Hash::make('password'), - 'remember_token' => Str::random(10), - ]; - } - - /** - * Indicate that the model's email address should be unverified. - */ - public function unverified(): static - { - return $this->state(fn (array $attributes) => [ - 'email_verified_at' => null, - ]); - } -} diff --git a/packages/tag/workbench/database/migrations/.gitkeep b/packages/tag/workbench/database/migrations/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/tag/workbench/database/seeders/DatabaseSeeder.php b/packages/tag/workbench/database/seeders/DatabaseSeeder.php deleted file mode 100644 index ce9bd1597..000000000 --- a/packages/tag/workbench/database/seeders/DatabaseSeeder.php +++ /dev/null @@ -1,23 +0,0 @@ -create(); - - UserFactory::new()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', - ]); - } -} diff --git a/packages/tag/workbench/resources/views/.gitkeep b/packages/tag/workbench/resources/views/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/tag/workbench/routes/web.php b/packages/tag/workbench/routes/web.php deleted file mode 100644 index 86a06c53e..000000000 --- a/packages/tag/workbench/routes/web.php +++ /dev/null @@ -1,7 +0,0 @@ - [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, ], /* diff --git a/packages/trainings/src/Commands/InstallCommand.php b/packages/trainings/src/Commands/InstallCommand.php index 09d86846c..67ba7847a 100644 --- a/packages/trainings/src/Commands/InstallCommand.php +++ b/packages/trainings/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The Training config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing Trainings Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'trainings-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/trainings/src/Filters/DateRangeFilter.php b/packages/trainings/src/Filters/DateRangeFilter.php index e0d4f7334..a7473da6b 100644 --- a/packages/trainings/src/Filters/DateRangeFilter.php +++ b/packages/trainings/src/Filters/DateRangeFilter.php @@ -5,24 +5,26 @@ use Filament\Forms\Components\DatePicker; use Filament\Tables\Filters\Filter; use Illuminate\Database\Eloquent\Builder; +use Override; class DateRangeFilter extends Filter { + #[Override] public static function make(?string $name = null): static { return parent::make($name) ->form([ - DatePicker::make("{$name}_from"), - DatePicker::make("{$name}_until"), + DatePicker::make($name.'_from'), + DatePicker::make($name.'_until'), ]) ->query(function (Builder $query, array $data) use (&$name): Builder { return $query ->when( - $data["{$name}_from"], + $data[$name.'_from'], fn (Builder $query, $date): Builder => $query->whereDate($name, '>=', $date), ) ->when( - $data["{$name}_until"], + $data[$name.'_until'], fn (Builder $query, $date): Builder => $query->whereDate($name, '<=', $date), ); }); diff --git a/packages/trainings/src/Jobs/SendInvitationRequests.php b/packages/trainings/src/Jobs/SendInvitationRequests.php index bf219a3c2..320d96574 100644 --- a/packages/trainings/src/Jobs/SendInvitationRequests.php +++ b/packages/trainings/src/Jobs/SendInvitationRequests.php @@ -17,41 +17,47 @@ class SendInvitationRequests implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public function __construct() - { - $this->tries = 3; - $this->timeout = 300; - $this->maxExceptions = 1; - $this->backoff = 350; - } - - public function handle() + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 3; + + /** + * @var int + */ + public $timeout = 300; + + /** + * @var int + */ + public $maxExceptions = 1; + + /** + * @var int + */ + public $backoff = 350; + + public function handle(): void { $this->setProgress(1); $invitationRequests = Training::where('due_at', '<', now()) ->get() - ->map(function ($training) { - return TrainingInvitation::create([ - 'training_id' => $training->id, - 'title' => $training->title, - 'slug' => Str::slug($training->title), - 'content' => $training->description, - 'status' => 'new', - // TODO: what about this user_id? I forgot ... - // 'user_id' => $training->users->first()->id, - ]); - }); + ->map(fn ($training) => TrainingInvitation::create([ + 'training_id' => $training->id, + 'title' => $training->title, + 'slug' => Str::slug($training->title), + 'content' => $training->description, + 'status' => 'new', + // TODO: what about this user_id? I forgot ... + // 'user_id' => $training->users->first()->id, + ])); $this->setProgress(10); diff --git a/packages/trainings/src/Jobs/SendInvitations.php b/packages/trainings/src/Jobs/SendInvitations.php index 6a8cef474..1182886ee 100644 --- a/packages/trainings/src/Jobs/SendInvitations.php +++ b/packages/trainings/src/Jobs/SendInvitations.php @@ -15,28 +15,35 @@ class SendInvitations implements ShouldQueue { - use Dispatchable, InteractsWithQueue, JobProgress, Queueable, SerializesModels; - - public $tries; - - public $timeout; - - public $maxExceptions; - - public $backoff; - - public $invitationId; - - public function __construct($invitationId) - { - $this->tries = 3; - $this->timeout = 300; - $this->maxExceptions = 1; - $this->backoff = 350; - $this->invitationId = $invitationId; - } - - public function handle() + use Dispatchable; + use InteractsWithQueue; + use JobProgress; + use Queueable; + use SerializesModels; + + /** + * @var int + */ + public $tries = 3; + + /** + * @var int + */ + public $timeout = 300; + + /** + * @var int + */ + public $maxExceptions = 1; + + /** + * @var int + */ + public $backoff = 350; + + public function __construct(public $invitationId) {} + + public function handle(): void { $this->setProgress(1); @@ -48,7 +55,7 @@ public function handle() $invitation->trainingDates() ->whereNull('sent_at') ->get() - ->each(function ($trainingDate) { + ->each(function ($trainingDate): void { $trainingDates[] = $trainingDate; $trainingDate->update(['sent_at' => now()]); }); diff --git a/packages/trainings/src/Mail/Invitation.php b/packages/trainings/src/Mail/Invitation.php index e0384259c..f0b869bae 100644 --- a/packages/trainings/src/Mail/Invitation.php +++ b/packages/trainings/src/Mail/Invitation.php @@ -10,14 +10,10 @@ class Invitation extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; - public $trainingDates; - - public function __construct($trainingDates) - { - $this->trainingDates = $trainingDates; - } + public function __construct(public $trainingDates) {} public function envelope(): Envelope { diff --git a/packages/trainings/src/Mail/InvitationRequest.php b/packages/trainings/src/Mail/InvitationRequest.php index 88407442e..6c4c79a01 100644 --- a/packages/trainings/src/Mail/InvitationRequest.php +++ b/packages/trainings/src/Mail/InvitationRequest.php @@ -10,14 +10,10 @@ class InvitationRequest extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; - public $invitationRequest; - - public function __construct($invitationRequest) - { - $this->invitationRequest = $invitationRequest; - } + public function __construct(public $invitationRequest) {} public function envelope(): Envelope { diff --git a/packages/trainings/src/Resources/TrainingDateResource.php b/packages/trainings/src/Resources/TrainingDateResource.php index 3d59d1b3b..eddc65988 100644 --- a/packages/trainings/src/Resources/TrainingDateResource.php +++ b/packages/trainings/src/Resources/TrainingDateResource.php @@ -9,16 +9,20 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; -use Filament\Tables; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Training\Filters\DateRangeFilter; use Moox\Training\Models\TrainingDate; -use Moox\Training\Resources\TrainingDateResource\Pages; +use Moox\Training\Resources\TrainingDateResource\Pages\CreateTrainingDate; +use Moox\Training\Resources\TrainingDateResource\Pages\EditTrainingDate; +use Moox\Training\Resources\TrainingDateResource\Pages\ListTrainingDates; +use Moox\Training\Resources\TrainingDateResource\Pages\ViewTrainingDate; +use Override; class TrainingDateResource extends Resource { @@ -32,6 +36,7 @@ class TrainingDateResource extends Resource protected static ?string $recordTitleAttribute = 'link'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -142,38 +147,39 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('trainingInvitation.title') + TextColumn::make('trainingInvitation.title') ->toggleable() ->limit(50), - Tables\Columns\TextColumn::make('begin') + TextColumn::make('begin') ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('end') + TextColumn::make('end') ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('type') + TextColumn::make('type') ->toggleable() ->searchable(), - Tables\Columns\TextColumn::make('link') + TextColumn::make('link') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('location') + TextColumn::make('location') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('min_participants') + TextColumn::make('min_participants') ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('max_participants') + TextColumn::make('max_participants') ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('sent_at') + TextColumn::make('sent_at') ->toggleable() ->dateTime(), ]) @@ -190,21 +196,24 @@ public static function table(Table $table): Table ->bulkActions([DeleteBulkAction::make()]); } + #[Override] public static function getRelations(): array { return []; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListTrainingDates::route('/'), - 'create' => Pages\CreateTrainingDate::route('/create'), - 'view' => Pages\ViewTrainingDate::route('/{record}'), - 'edit' => Pages\EditTrainingDate::route('/{record}/edit'), + 'index' => ListTrainingDates::route('/'), + 'create' => CreateTrainingDate::route('/create'), + 'view' => ViewTrainingDate::route('/{record}'), + 'edit' => EditTrainingDate::route('/{record}/edit'), ]; } + #[Override] public static function getNavigationSort(): ?int { return config('trainings.navigation_sort') + 2; diff --git a/packages/trainings/src/Resources/TrainingInvitationResource.php b/packages/trainings/src/Resources/TrainingInvitationResource.php index 524dd8ff6..705947f63 100644 --- a/packages/trainings/src/Resources/TrainingInvitationResource.php +++ b/packages/trainings/src/Resources/TrainingInvitationResource.php @@ -10,15 +10,22 @@ use Filament\Forms\Form; use Filament\Notifications\Notification; use Filament\Resources\Resource; -use Filament\Tables; +use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Illuminate\Database\QueryException; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Training\Filters\DateRangeFilter; use Moox\Training\Models\TrainingInvitation; -use Moox\Training\Resources\TrainingInvitationResource\Pages; +use Moox\Training\Resources\TrainingInvitationResource\Pages\CreateTrainingInvitation; +use Moox\Training\Resources\TrainingInvitationResource\Pages\EditTrainingInvitation; +use Moox\Training\Resources\TrainingInvitationResource\Pages\ListTrainingInvitations; +use Moox\Training\Resources\TrainingInvitationResource\Pages\PrepareTrainingInvitation; +use Moox\Training\Resources\TrainingInvitationResource\Pages\ViewTrainingInvitation; +use Moox\Training\Resources\TrainingInvitationResource\RelationManagers\TrainingDatesRelationManager; +use Override; class TrainingInvitationResource extends Resource { @@ -32,6 +39,7 @@ class TrainingInvitationResource extends Resource protected static ?string $recordTitleAttribute = 'title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -83,27 +91,28 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('training.title') + TextColumn::make('training.title') ->toggleable() ->limit(50), - Tables\Columns\TextColumn::make('title') + TextColumn::make('title') ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('content') + TextColumn::make('content') ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('status') + TextColumn::make('status') ->toggleable() ->searchable() ->limit(50), @@ -119,8 +128,8 @@ public static function table(Table $table): Table ]) ->actions([EditAction::make()]) ->bulkActions([ - Tables\Actions\DeleteBulkAction::make() - ->action(function ($records, Tables\Actions\DeleteBulkAction $action) { + DeleteBulkAction::make() + ->action(function ($records, DeleteBulkAction $action): void { foreach ($records as $record) { try { $record->delete(); @@ -145,24 +154,27 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ - TrainingInvitationResource\RelationManagers\TrainingDatesRelationManager::class, + TrainingDatesRelationManager::class, ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListTrainingInvitations::route('/'), - 'create' => Pages\CreateTrainingInvitation::route('/create'), - 'view' => Pages\ViewTrainingInvitation::route('/{record}'), - 'edit' => Pages\EditTrainingInvitation::route('/{record}/edit'), - 'prepare' => Pages\PrepareTrainingInvitation::route('/{record}/prepare'), + 'index' => ListTrainingInvitations::route('/'), + 'create' => CreateTrainingInvitation::route('/create'), + 'view' => ViewTrainingInvitation::route('/{record}'), + 'edit' => EditTrainingInvitation::route('/{record}/edit'), + 'prepare' => PrepareTrainingInvitation::route('/{record}/prepare'), ]; } + #[Override] public static function getNavigationSort(): ?int { return config('trainings.navigation_sort') + 1; diff --git a/packages/trainings/src/Resources/TrainingInvitationResource/Pages/EditTrainingInvitation.php b/packages/trainings/src/Resources/TrainingInvitationResource/Pages/EditTrainingInvitation.php index 5ed2e8c79..17dfd4a03 100644 --- a/packages/trainings/src/Resources/TrainingInvitationResource/Pages/EditTrainingInvitation.php +++ b/packages/trainings/src/Resources/TrainingInvitationResource/Pages/EditTrainingInvitation.php @@ -21,7 +21,7 @@ protected function getHeaderActions(): array if (config('trainings.send_invitations_action') !== false) { $actions[] = Action::make('sendInvitations') ->label('Send Invitations') - ->action(function () { + ->action(function (): void { SendInvitations::dispatch($this->record->getKey()); }) ->requiresConfirmation() @@ -29,7 +29,7 @@ protected function getHeaderActions(): array } $actions[] = DeleteAction::make() - ->action(function ($record) { + ->action(function ($record): void { try { $record->delete(); Notification::make() @@ -37,15 +37,15 @@ protected function getHeaderActions(): array ->body('The training was deleted successfully.') ->success() ->send(); - } catch (QueryException $exception) { - if ($exception->getCode() === '23000') { + } catch (QueryException $queryException) { + if ($queryException->getCode() === '23000') { Notification::make() ->title('Cannot Delete Training') ->body('The training has associated invitations and cannot be deleted.') ->danger() ->send(); } else { - throw $exception; + throw $queryException; } } }); diff --git a/packages/trainings/src/Resources/TrainingInvitationResource/Pages/ListTrainingInvitations.php b/packages/trainings/src/Resources/TrainingInvitationResource/Pages/ListTrainingInvitations.php index bb63ff03d..37ae40aa0 100644 --- a/packages/trainings/src/Resources/TrainingInvitationResource/Pages/ListTrainingInvitations.php +++ b/packages/trainings/src/Resources/TrainingInvitationResource/Pages/ListTrainingInvitations.php @@ -23,7 +23,7 @@ protected function getHeaderActions(): array return [ Action::make('collectInvitations') ->label('Collect Invitations') - ->action(function () { + ->action(function (): void { SendInvitationRequests::dispatch(); }) ->requiresConfirmation() diff --git a/packages/trainings/src/Resources/TrainingInvitationResource/Pages/PrepareTrainingInvitation.php b/packages/trainings/src/Resources/TrainingInvitationResource/Pages/PrepareTrainingInvitation.php index 70b070350..dbb2d20b1 100644 --- a/packages/trainings/src/Resources/TrainingInvitationResource/Pages/PrepareTrainingInvitation.php +++ b/packages/trainings/src/Resources/TrainingInvitationResource/Pages/PrepareTrainingInvitation.php @@ -7,6 +7,7 @@ use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; use Moox\Training\Resources\TrainingInvitationResource; +use Override; class PrepareTrainingInvitation extends EditRecord { @@ -17,13 +18,14 @@ protected function getHeaderActions(): array return [ Action::make('sendInvitations') ->label('Send Invitations') - ->action(function () { + ->action(function (): void { // Send invitation job }), DeleteAction::make(), ]; } + #[Override] public function form(Form $form): Form { return parent::form($form); diff --git a/packages/trainings/src/Resources/TrainingInvitationResource/RelationManagers/TrainingDatesRelationManager.php b/packages/trainings/src/Resources/TrainingInvitationResource/RelationManagers/TrainingDatesRelationManager.php index 815d37243..58bf795f3 100644 --- a/packages/trainings/src/Resources/TrainingInvitationResource/RelationManagers/TrainingDatesRelationManager.php +++ b/packages/trainings/src/Resources/TrainingInvitationResource/RelationManagers/TrainingDatesRelationManager.php @@ -18,6 +18,7 @@ use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; +use Override; class TrainingDatesRelationManager extends RelationManager { @@ -25,6 +26,7 @@ class TrainingDatesRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'link'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -137,31 +139,29 @@ public function table(Table $table): Table DatePicker::make('created_from'), DatePicker::make('created_until'), ]) - ->query(function (Builder $query, array $data): Builder { - return $query - ->when( - $data['created_from'], - fn ( - Builder $query, - $date - ): Builder => $query->whereDate( - 'created_at', - '>=', - $date - ) + ->query(fn (Builder $query, array $data): Builder => $query + ->when( + $data['created_from'], + fn ( + Builder $query, + $date + ): Builder => $query->whereDate( + 'created_at', + '>=', + $date ) - ->when( - $data['created_until'], - fn ( - Builder $query, - $date - ): Builder => $query->whereDate( - 'created_at', - '<=', - $date - ) - ); - }), + ) + ->when( + $data['created_until'], + fn ( + Builder $query, + $date + ): Builder => $query->whereDate( + 'created_at', + '<=', + $date + ) + )), SelectFilter::make('training_invitation_id') ->multiple() diff --git a/packages/trainings/src/Resources/TrainingResource.php b/packages/trainings/src/Resources/TrainingResource.php index 38cd5e49c..a373b1949 100644 --- a/packages/trainings/src/Resources/TrainingResource.php +++ b/packages/trainings/src/Resources/TrainingResource.php @@ -11,16 +11,22 @@ use Filament\Forms\Form; use Filament\Notifications\Notification; use Filament\Resources\Resource; -use Filament\Tables; +use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Illuminate\Database\QueryException; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Training\Filters\DateRangeFilter; use Moox\Training\Models\Training; -use Moox\Training\Resources\TrainingResource\Pages; +use Moox\Training\Resources\TrainingResource\Pages\CreateTraining; +use Moox\Training\Resources\TrainingResource\Pages\EditTraining; +use Moox\Training\Resources\TrainingResource\Pages\ListTrainings; +use Moox\Training\Resources\TrainingResource\Pages\ViewTraining; +use Moox\Training\Resources\TrainingResource\RelationManagers\TrainingInvitationsRelationManager; +use Override; class TrainingResource extends Resource { @@ -34,6 +40,7 @@ class TrainingResource extends Resource protected static ?string $recordTitleAttribute = 'title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -169,48 +176,49 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('title') + TextColumn::make('title') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('description') + TextColumn::make('description') ->toggleable() ->searchable() ->limit(50), - Tables\Columns\TextColumn::make('duration') + TextColumn::make('duration') ->toggleable() ->searchable(true, null, true), - Tables\Columns\TextColumn::make('link') + TextColumn::make('link') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('due_at') + TextColumn::make('due_at') ->toggleable() ->dateTime(), - Tables\Columns\TextColumn::make('cycle') + TextColumn::make('cycle') ->toggleable() ->searchable(), - Tables\Columns\TextColumn::make('source_id') + TextColumn::make('source_id') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('trainingType.title') + TextColumn::make('trainingType.title') ->toggleable() ->limit(50), - Tables\Columns\TextColumn::make('trainingable_id') + TextColumn::make('trainingable_id') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('trainingable_type') + TextColumn::make('trainingable_type') ->toggleable() ->searchable(true, null, true) ->limit(50), @@ -226,8 +234,8 @@ public static function table(Table $table): Table ]) ->actions([ViewAction::make(), EditAction::make()]) ->bulkActions([ - Tables\Actions\DeleteBulkAction::make() - ->action(function ($records, Tables\Actions\DeleteBulkAction $action) { + DeleteBulkAction::make() + ->action(function ($records, DeleteBulkAction $action): void { foreach ($records as $record) { try { $record->delete(); @@ -252,23 +260,26 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ - TrainingResource\RelationManagers\TrainingInvitationsRelationManager::class, + TrainingInvitationsRelationManager::class, ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListTrainings::route('/'), - 'create' => Pages\CreateTraining::route('/create'), - 'view' => Pages\ViewTraining::route('/{record}'), - 'edit' => Pages\EditTraining::route('/{record}/edit'), + 'index' => ListTrainings::route('/'), + 'create' => CreateTraining::route('/create'), + 'view' => ViewTraining::route('/{record}'), + 'edit' => EditTraining::route('/{record}/edit'), ]; } + #[Override] public static function getNavigationSort(): ?int { return config('trainings.navigation_sort'); diff --git a/packages/trainings/src/Resources/TrainingResource/Pages/EditTraining.php b/packages/trainings/src/Resources/TrainingResource/Pages/EditTraining.php index a41851580..87cb2e1de 100644 --- a/packages/trainings/src/Resources/TrainingResource/Pages/EditTraining.php +++ b/packages/trainings/src/Resources/TrainingResource/Pages/EditTraining.php @@ -15,7 +15,7 @@ class EditTraining extends EditRecord protected function getHeaderActions(): array { return [DeleteAction::make() - ->action(function ($record, DeleteAction $action) { + ->action(function ($record, DeleteAction $action): void { try { $record->delete(); Notification::make() @@ -23,15 +23,15 @@ protected function getHeaderActions(): array ->body('The training was deleted successfully.') ->success() ->send(); - } catch (QueryException $exception) { - if ($exception->getCode() === '23000') { + } catch (QueryException $queryException) { + if ($queryException->getCode() === '23000') { Notification::make() ->title('Cannot Delete Training') ->body('The training has associated invitations and cannot be deleted.') ->danger() ->send(); } else { - throw $exception; + throw $queryException; } } }), diff --git a/packages/trainings/src/Resources/TrainingResource/Pages/ViewTraining.php b/packages/trainings/src/Resources/TrainingResource/Pages/ViewTraining.php index 5b26b07d1..15ccba3b2 100644 --- a/packages/trainings/src/Resources/TrainingResource/Pages/ViewTraining.php +++ b/packages/trainings/src/Resources/TrainingResource/Pages/ViewTraining.php @@ -18,7 +18,7 @@ protected function getHeaderActions(): array return [ EditAction::make(), DeleteAction::make() - ->action(function ($record, DeleteAction $action) { + ->action(function ($record, DeleteAction $action): void { try { $record->delete(); Notification::make() @@ -26,15 +26,15 @@ protected function getHeaderActions(): array ->body('The training was deleted successfully.') ->success() ->send(); - } catch (QueryException $exception) { - if ($exception->getCode() === '23000') { + } catch (QueryException $queryException) { + if ($queryException->getCode() === '23000') { Notification::make() ->title('Cannot Delete Training') ->body('The training has associated invitations and cannot be deleted.') ->danger() ->send(); } else { - throw $exception; + throw $queryException; } } }), diff --git a/packages/trainings/src/Resources/TrainingResource/RelationManagers/TrainingInvitationsRelationManager.php b/packages/trainings/src/Resources/TrainingResource/RelationManagers/TrainingInvitationsRelationManager.php index ec7c9d2f0..d5a1f9474 100644 --- a/packages/trainings/src/Resources/TrainingResource/RelationManagers/TrainingInvitationsRelationManager.php +++ b/packages/trainings/src/Resources/TrainingResource/RelationManagers/TrainingInvitationsRelationManager.php @@ -2,21 +2,23 @@ namespace Moox\Training\Resources\TrainingResource\RelationManagers; -use Filament\Forms; +use Filament\Forms\Components\DatePicker; use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Components\Grid; use Filament\Forms\Components\RichEditor; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\CreateAction; use Filament\Tables\Actions\DeleteAction; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Filters\Filter; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; +use Override; class TrainingInvitationsRelationManager extends RelationManager { @@ -24,6 +26,7 @@ class TrainingInvitationsRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -71,43 +74,41 @@ public function table(Table $table): Table { return $table ->columns([ - Tables\Columns\TextColumn::make('training.title')->limit(50), - Tables\Columns\TextColumn::make('title')->limit(50), - Tables\Columns\TextColumn::make('slug')->limit(50), - Tables\Columns\TextColumn::make('content')->limit(50), - Tables\Columns\TextColumn::make('sent_at')->dateTime(), + TextColumn::make('training.title')->limit(50), + TextColumn::make('title')->limit(50), + TextColumn::make('slug')->limit(50), + TextColumn::make('content')->limit(50), + TextColumn::make('sent_at')->dateTime(), ]) ->filters([ - Tables\Filters\Filter::make('created_at') + Filter::make('created_at') ->form([ - Forms\Components\DatePicker::make('created_from'), - Forms\Components\DatePicker::make('created_until'), + DatePicker::make('created_from'), + DatePicker::make('created_until'), ]) - ->query(function (Builder $query, array $data): Builder { - return $query - ->when( - $data['created_from'], - fn ( - Builder $query, - $date - ): Builder => $query->whereDate( - 'created_at', - '>=', - $date - ) + ->query(fn (Builder $query, array $data): Builder => $query + ->when( + $data['created_from'], + fn ( + Builder $query, + $date + ): Builder => $query->whereDate( + 'created_at', + '>=', + $date ) - ->when( - $data['created_until'], - fn ( - Builder $query, - $date - ): Builder => $query->whereDate( - 'created_at', - '<=', - $date - ) - ); - }), + ) + ->when( + $data['created_until'], + fn ( + Builder $query, + $date + ): Builder => $query->whereDate( + 'created_at', + '<=', + $date + ) + )), SelectFilter::make('training_id') ->multiple() diff --git a/packages/trainings/src/Resources/TrainingTypeResource.php b/packages/trainings/src/Resources/TrainingTypeResource.php index 24ed32b6c..5c860b2c0 100644 --- a/packages/trainings/src/Resources/TrainingTypeResource.php +++ b/packages/trainings/src/Resources/TrainingTypeResource.php @@ -9,15 +9,21 @@ use Filament\Forms\Form; use Filament\Notifications\Notification; use Filament\Resources\Resource; -use Filament\Tables; +use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Illuminate\Database\QueryException; use Moox\Core\Traits\Tabs\TabsInResource; use Moox\Training\Filters\DateRangeFilter; use Moox\Training\Models\TrainingType; -use Moox\Training\Resources\TrainingTypeResource\Pages; +use Moox\Training\Resources\TrainingTypeResource\Pages\CreateTrainingType; +use Moox\Training\Resources\TrainingTypeResource\Pages\EditTrainingType; +use Moox\Training\Resources\TrainingTypeResource\Pages\ListTrainingTypes; +use Moox\Training\Resources\TrainingTypeResource\Pages\ViewTrainingType; +use Moox\Training\Resources\TrainingTypeResource\RelationManagers\TrainingsRelationManager; +use Override; class TrainingTypeResource extends Resource { @@ -31,6 +37,7 @@ class TrainingTypeResource extends Resource protected static ?string $recordTitleAttribute = 'title'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -70,20 +77,21 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->poll('60s') ->columns([ - Tables\Columns\TextColumn::make('title') + TextColumn::make('title') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('slug') + TextColumn::make('slug') ->toggleable() ->searchable(true, null, true) ->limit(50), - Tables\Columns\TextColumn::make('description') + TextColumn::make('description') ->toggleable() ->searchable() ->limit(50), @@ -91,8 +99,8 @@ public static function table(Table $table): Table ->filters([DateRangeFilter::make('created_at')]) ->actions([ViewAction::make(), EditAction::make()]) ->bulkActions([ - Tables\Actions\DeleteBulkAction::make() - ->action(function ($records, Tables\Actions\DeleteBulkAction $action) { + DeleteBulkAction::make() + ->action(function ($records, DeleteBulkAction $action): void { foreach ($records as $record) { try { $record->delete(); @@ -117,23 +125,26 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ - TrainingTypeResource\RelationManagers\TrainingsRelationManager::class, + TrainingsRelationManager::class, ]; } + #[Override] public static function getPages(): array { return [ - 'index' => Pages\ListTrainingTypes::route('/'), - 'create' => Pages\CreateTrainingType::route('/create'), - 'view' => Pages\ViewTrainingType::route('/{record}'), - 'edit' => Pages\EditTrainingType::route('/{record}/edit'), + 'index' => ListTrainingTypes::route('/'), + 'create' => CreateTrainingType::route('/create'), + 'view' => ViewTrainingType::route('/{record}'), + 'edit' => EditTrainingType::route('/{record}/edit'), ]; } + #[Override] public static function getNavigationSort(): ?int { return config('trainings.navigation_sort') + 3; diff --git a/packages/trainings/src/Resources/TrainingTypeResource/Pages/EditTrainingType.php b/packages/trainings/src/Resources/TrainingTypeResource/Pages/EditTrainingType.php index 645db9836..35001f56c 100644 --- a/packages/trainings/src/Resources/TrainingTypeResource/Pages/EditTrainingType.php +++ b/packages/trainings/src/Resources/TrainingTypeResource/Pages/EditTrainingType.php @@ -15,7 +15,7 @@ class EditTrainingType extends EditRecord protected function getHeaderActions(): array { return [DeleteAction::make() - ->action(function ($record, DeleteAction $action) { + ->action(function ($record, DeleteAction $action): void { try { $record->delete(); Notification::make() @@ -23,15 +23,15 @@ protected function getHeaderActions(): array ->body('The type was deleted successfully.') ->success() ->send(); - } catch (QueryException $exception) { - if ($exception->getCode() === '23000') { + } catch (QueryException $queryException) { + if ($queryException->getCode() === '23000') { Notification::make() ->title('Cannot Delete Training Type') ->body('One or more type have associated trainings and cannot be deleted.') ->danger() ->send(); } else { - throw $exception; + throw $queryException; } } }), diff --git a/packages/trainings/src/Resources/TrainingTypeResource/Pages/ViewTrainingType.php b/packages/trainings/src/Resources/TrainingTypeResource/Pages/ViewTrainingType.php index e94b5ea97..cc6d0ca39 100644 --- a/packages/trainings/src/Resources/TrainingTypeResource/Pages/ViewTrainingType.php +++ b/packages/trainings/src/Resources/TrainingTypeResource/Pages/ViewTrainingType.php @@ -18,7 +18,7 @@ protected function getHeaderActions(): array return [ EditAction::make(), DeleteAction::make() - ->action(function ($record, DeleteAction $action) { + ->action(function ($record, DeleteAction $action): void { try { $record->delete(); Notification::make() @@ -26,15 +26,15 @@ protected function getHeaderActions(): array ->body('The type was deleted successfully.') ->success() ->send(); - } catch (QueryException $exception) { - if ($exception->getCode() === '23000') { + } catch (QueryException $queryException) { + if ($queryException->getCode() === '23000') { Notification::make() ->title('Cannot Delete Training Type') ->body('The type has associated trainings and cannot be deleted.') ->danger() ->send(); } else { - throw $exception; + throw $queryException; } } }), diff --git a/packages/trainings/src/Resources/TrainingTypeResource/RelationManagers/TrainingsRelationManager.php b/packages/trainings/src/Resources/TrainingTypeResource/RelationManagers/TrainingsRelationManager.php index 42998c798..f7b77ce9b 100644 --- a/packages/trainings/src/Resources/TrainingTypeResource/RelationManagers/TrainingsRelationManager.php +++ b/packages/trainings/src/Resources/TrainingTypeResource/RelationManagers/TrainingsRelationManager.php @@ -2,7 +2,7 @@ namespace Moox\Training\Resources\TrainingTypeResource\RelationManagers; -use Filament\Forms; +use Filament\Forms\Components\DatePicker; use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Components\Grid; use Filament\Forms\Components\RichEditor; @@ -10,14 +10,16 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; use Filament\Tables\Actions\CreateAction; use Filament\Tables\Actions\DeleteAction; use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Filters\Filter; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; +use Override; class TrainingsRelationManager extends RelationManager { @@ -25,6 +27,7 @@ class TrainingsRelationManager extends RelationManager protected static ?string $recordTitleAttribute = 'title'; + #[Override] public function form(Form $form): Form { return $form->schema([ @@ -141,51 +144,49 @@ public function table(Table $table): Table { return $table ->columns([ - Tables\Columns\TextColumn::make('title')->limit(50), - Tables\Columns\TextColumn::make('slug')->limit(50), - Tables\Columns\TextColumn::make('description')->limit(50), - Tables\Columns\TextColumn::make('duration'), - Tables\Columns\TextColumn::make('link')->limit(50), - Tables\Columns\TextColumn::make('due_at')->dateTime(), - Tables\Columns\TextColumn::make('cycle'), - Tables\Columns\TextColumn::make('source_id')->limit(50), - Tables\Columns\TextColumn::make('trainingType.title')->limit( + TextColumn::make('title')->limit(50), + TextColumn::make('slug')->limit(50), + TextColumn::make('description')->limit(50), + TextColumn::make('duration'), + TextColumn::make('link')->limit(50), + TextColumn::make('due_at')->dateTime(), + TextColumn::make('cycle'), + TextColumn::make('source_id')->limit(50), + TextColumn::make('trainingType.title')->limit( 50 ), - Tables\Columns\TextColumn::make('trainingable_id')->limit(50), - Tables\Columns\TextColumn::make('trainingable_type')->limit(50), + TextColumn::make('trainingable_id')->limit(50), + TextColumn::make('trainingable_type')->limit(50), ]) ->filters([ - Tables\Filters\Filter::make('created_at') + Filter::make('created_at') ->form([ - Forms\Components\DatePicker::make('created_from'), - Forms\Components\DatePicker::make('created_until'), + DatePicker::make('created_from'), + DatePicker::make('created_until'), ]) - ->query(function (Builder $query, array $data): Builder { - return $query - ->when( - $data['created_from'], - fn ( - Builder $query, - $date - ): Builder => $query->whereDate( - 'created_at', - '>=', - $date - ) + ->query(fn (Builder $query, array $data): Builder => $query + ->when( + $data['created_from'], + fn ( + Builder $query, + $date + ): Builder => $query->whereDate( + 'created_at', + '>=', + $date ) - ->when( - $data['created_until'], - fn ( - Builder $query, - $date - ): Builder => $query->whereDate( - 'created_at', - '<=', - $date - ) - ); - }), + ) + ->when( + $data['created_until'], + fn ( + Builder $query, + $date + ): Builder => $query->whereDate( + 'created_at', + '<=', + $date + ) + )), SelectFilter::make('training_type_id') ->multiple() diff --git a/packages/user-device/config/user-device.php b/packages/user-device/config/user-device.php index db64b3796..f721f1aa4 100644 --- a/packages/user-device/config/user-device.php +++ b/packages/user-device/config/user-device.php @@ -1,5 +1,7 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, 'Moox Users' => \Moox\User\Models\User::class, ], diff --git a/packages/user-device/src/Commands/InstallCommand.php b/packages/user-device/src/Commands/InstallCommand.php index 9d342f6d5..76d3131c9 100644 --- a/packages/user-device/src/Commands/InstallCommand.php +++ b/packages/user-device/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The UserDevice config already exist. The config will not be published.'); } } @@ -90,6 +91,7 @@ public function publishMigrations(): void return; } + info('Publishing UserDevices Migrations...'); $this->callSilent('vendor:publish', ['--tag' => 'user-device-migrations']); } @@ -126,22 +128,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -182,12 +184,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/user-device/src/Models/UserDevice.php b/packages/user-device/src/Models/UserDevice.php index aa60fb198..7e36d7b10 100644 --- a/packages/user-device/src/Models/UserDevice.php +++ b/packages/user-device/src/Models/UserDevice.php @@ -2,9 +2,11 @@ namespace Moox\UserDevice\Models; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Support\Str; +use Override; class UserDevice extends Model { @@ -18,7 +20,7 @@ class UserDevice extends Model /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'title', @@ -50,17 +52,18 @@ class UserDevice extends Model /** * The "booting" method of the model. */ + #[Override] protected static function boot() { parent::boot(); - UserDevice::creating(function ($item) { + UserDevice::creating(function ($item): void { $baseSlug = Str::slug($item->title); $slug = $baseSlug; $counter = 1; while (UserDevice::where('slug', $slug)->exists()) { - $slug = "{$baseSlug}-{$counter}"; + $slug = sprintf('%s-%d', $baseSlug, $counter); $counter++; } @@ -79,8 +82,8 @@ public function user(): MorphTo /** * Scope a query to only include active devices. * - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder + * @param Builder $query + * @return Builder */ public function scopeActive($query) { @@ -90,8 +93,8 @@ public function scopeActive($query) /** * Scope a query to only include whitelisted devices. * - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder + * @param Builder $query + * @return Builder */ public function scopeWhitelisted($query) { diff --git a/packages/user-device/src/Notifications/NewDeviceNotification.php b/packages/user-device/src/Notifications/NewDeviceNotification.php index b1823a0e7..fa93fa370 100644 --- a/packages/user-device/src/Notifications/NewDeviceNotification.php +++ b/packages/user-device/src/Notifications/NewDeviceNotification.php @@ -11,25 +11,19 @@ class NewDeviceNotification extends Notification implements ShouldQueue { use Queueable; - protected $deviceDetails; - /** * Create a new notification instance. * * @return void */ - public function __construct($deviceDetails) - { - $this->deviceDetails = $deviceDetails; - } + public function __construct(protected $deviceDetails) {} /** * Get the notification's delivery channels. * * @param mixed $notifiable - * @return array */ - public function via($notifiable) + public function via($notifiable): array { return ['mail']; } @@ -38,7 +32,7 @@ public function via($notifiable) * Get the mail representation of the notification. * * @param mixed $notifiable - * @return \Illuminate\Notifications\Messages\MailMessage + * @return MailMessage */ public function toMail($notifiable) { @@ -56,9 +50,8 @@ public function toMail($notifiable) * Get the array representation of the notification. * * @param mixed $notifiable - * @return array */ - public function toArray($notifiable) + public function toArray($notifiable): array { return [ 'deviceDetails' => $this->deviceDetails, diff --git a/packages/user-device/src/Resources/UserDeviceResource.php b/packages/user-device/src/Resources/UserDeviceResource.php index 6955dfe1e..3eb3f703d 100644 --- a/packages/user-device/src/Resources/UserDeviceResource.php +++ b/packages/user-device/src/Resources/UserDeviceResource.php @@ -21,15 +21,18 @@ use Moox\UserDevice\Resources\UserDeviceResource\Pages\ListPage; use Moox\UserDevice\Resources\UserDeviceResource\Pages\ViewPage; use Moox\UserDevice\Resources\UserDeviceResource\Widgets\UserDeviceWidgets; +use Override; class UserDeviceResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = UserDevice::class; protected static ?string $navigationIcon = 'gmdi-devices-o'; + #[Override] public static function form(Form $form): Form { return $form @@ -75,30 +78,24 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table ->columns([ IconColumn::make('platform') ->label(__('core::sync.platform')) - ->icon(function ($record) { - switch ($record->platform) { - case 'Mobile': - return 'heroicon-o-device-phone-mobile'; - case 'Desktop': - return 'heroicon-o-computer-desktop'; - default: - return 'heroicon-o-computer-desktop'; - } + ->icon(fn ($record): string => match ($record->platform) { + 'Mobile' => 'heroicon-o-device-phone-mobile', + 'Desktop' => 'heroicon-o-computer-desktop', + default => 'heroicon-o-computer-desktop', }), TextColumn::make('title') ->label(__('core::core.title')) ->sortable(), TextColumn::make('user_id') ->label(__('core::user.user_id')) - ->getStateUsing(function ($record) { - return optional($record->user)->name ?? 'unknown'; - }) + ->getStateUsing(fn ($record) => optional($record->user)->name ?? 'unknown') ->sortable(), // TODO: Not implemented yet, must be editable then @@ -127,6 +124,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -134,6 +132,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -142,6 +141,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -150,36 +150,43 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return config('user-device.resources.devices.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('user-device.resources.devices.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('user-device.resources.devices.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('user-device.resources.devices.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return config('user-device.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('user-device.navigation_sort') + 2; diff --git a/packages/user-device/src/Resources/UserDeviceResource/Pages/ListPage.php b/packages/user-device/src/Resources/UserDeviceResource/Pages/ListPage.php index 52e2c5e2d..02c455a14 100644 --- a/packages/user-device/src/Resources/UserDeviceResource/Pages/ListPage.php +++ b/packages/user-device/src/Resources/UserDeviceResource/Pages/ListPage.php @@ -7,6 +7,7 @@ use Moox\UserDevice\Models\UserDevice; use Moox\UserDevice\Resources\UserDeviceResource; use Moox\UserDevice\Resources\UserDeviceResource\Widgets\UserDeviceWidgets; +use Override; class ListPage extends ListRecords { @@ -14,12 +15,13 @@ class ListPage extends ListRecords public static string $resource = UserDeviceResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ // TODO: Widgets @@ -27,6 +29,7 @@ public function getHeaderWidgets(): array ]; } + #[Override] public function getTitle(): string { return __('core::device.title'); diff --git a/packages/user-device/src/Resources/UserDeviceResource/Widgets/UserDeviceWidgets.php b/packages/user-device/src/Resources/UserDeviceResource/Widgets/UserDeviceWidgets.php index 4098e6fd4..e4e7f0c90 100644 --- a/packages/user-device/src/Resources/UserDeviceResource/Widgets/UserDeviceWidgets.php +++ b/packages/user-device/src/Resources/UserDeviceResource/Widgets/UserDeviceWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\UserDevice\Models\UserDevice; +use Override; class UserDeviceWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/user-device/src/Services/LocationService.php b/packages/user-device/src/Services/LocationService.php index dc1d0e67a..d8297a295 100644 --- a/packages/user-device/src/Services/LocationService.php +++ b/packages/user-device/src/Services/LocationService.php @@ -2,11 +2,12 @@ namespace Moox\UserDevice\Services; +use Exception; use GeoIp2\Database\Reader; class LocationService { - protected $reader; + protected Reader $reader; public function __construct() { @@ -14,7 +15,7 @@ public function __construct() $this->reader = new Reader($mmdbPath); } - public function getLocation($ipAddress) + public function getLocation(string $ipAddress): ?array { try { $record = $this->reader->city($ipAddress); @@ -27,7 +28,7 @@ public function getLocation($ipAddress) 'lat' => $record->location->latitude, 'lon' => $record->location->longitude, ]; - } catch (\Exception $e) { + } catch (Exception) { // Handle errors or unknown IPs gracefully return null; } diff --git a/packages/user-device/src/Services/UserDeviceTracker.php b/packages/user-device/src/Services/UserDeviceTracker.php index 2a8abcde6..841d7168c 100644 --- a/packages/user-device/src/Services/UserDeviceTracker.php +++ b/packages/user-device/src/Services/UserDeviceTracker.php @@ -12,14 +12,9 @@ class UserDeviceTracker { - protected $locationService; + public function __construct(protected LocationService $locationService) {} - public function __construct(LocationService $locationService) - { - $this->locationService = $locationService; - } - - public function addUserDevice(Request $request, $user, Agent $agent) + public function addUserDevice(Request $request, $user, Agent $agent): void { $ipAddress = $request->ip(); $userAgent = $request->userAgent(); @@ -35,7 +30,7 @@ public function addUserDevice(Request $request, $user, Agent $agent) $device = UserDevice::updateOrCreate([ 'user_id' => $user_id, - 'user_type' => get_class($user), + 'user_type' => $user::class, 'ip_address' => $ipAddress, 'user_agent' => $userAgent, ], [ diff --git a/packages/user-device/src/UserDeviceServiceProvider.php b/packages/user-device/src/UserDeviceServiceProvider.php index f0253a32a..f57c5164a 100644 --- a/packages/user-device/src/UserDeviceServiceProvider.php +++ b/packages/user-device/src/UserDeviceServiceProvider.php @@ -7,6 +7,7 @@ use Moox\UserDevice\Commands\InstallCommand; use Moox\UserDevice\Services\LocationService; use Moox\UserDevice\Services\UserDeviceTracker; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -23,16 +24,13 @@ public function configurePackage(Package $package): void ->hasCommand(InstallCommand::class); } - public function register() + #[Override] + public function register(): void { parent::register(); - $this->app->singleton(LocationService::class, function ($app) { - return new LocationService; - }); + $this->app->singleton(LocationService::class, fn ($app): LocationService => new LocationService); - $this->app->singleton(UserDeviceTracker::class, function ($app) { - return new UserDeviceTracker($app->make(LocationService::class)); - }); + $this->app->singleton(UserDeviceTracker::class, fn ($app): UserDeviceTracker => new UserDeviceTracker($app->make(LocationService::class))); } } diff --git a/packages/user-session/config/user-session.php b/packages/user-session/config/user-session.php index 7222f09c6..f1add3026 100644 --- a/packages/user-session/config/user-session.php +++ b/packages/user-session/config/user-session.php @@ -1,5 +1,8 @@ [ - 'App Users' => \App\Models\User::class, + 'App Users' => User::class, 'Moox Users' => \Moox\User\Models\User::class, ], - 'device_model' => \Moox\UserDevice\Models\UserDevice::class, + 'device_model' => UserDevice::class, /* | Session expiry for different scopes, diff --git a/packages/user-session/src/Commands/InstallCommand.php b/packages/user-session/src/Commands/InstallCommand.php index a27db8ea6..9eee7b599 100644 --- a/packages/user-session/src/Commands/InstallCommand.php +++ b/packages/user-session/src/Commands/InstallCommand.php @@ -32,7 +32,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +78,7 @@ public function publishConfiguration(): void return; } + warning('The UserSession config already exist. The config will not be published.'); } } @@ -130,22 +131,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -186,12 +187,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/user-session/src/Resources/UserSessionResource.php b/packages/user-session/src/Resources/UserSessionResource.php index c806c7ca7..cb4b94d43 100644 --- a/packages/user-session/src/Resources/UserSessionResource.php +++ b/packages/user-session/src/Resources/UserSessionResource.php @@ -2,6 +2,7 @@ namespace Moox\UserSession\Resources; +use Exception; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; @@ -19,10 +20,12 @@ use Moox\UserSession\Models\UserSession; use Moox\UserSession\Resources\UserSessionResource\Pages\ListPage; use Moox\UserSession\Resources\UserSessionResource\Widgets\UserSessionWidgets; +use Override; class UserSessionResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = UserSession::class; @@ -30,6 +33,7 @@ class UserSessionResource extends Resource protected static ?string $recordTitleAttribute = 'id'; + #[Override] public static function form(Form $form): Form { return $form @@ -51,6 +55,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -66,7 +71,7 @@ public static function table(Table $table): Table return $record->user->name; } - return "ID {$record->user_id} (no user type)"; + return sprintf('ID %s (no user type)', $record->user_id); }) ->sortable(), @@ -95,15 +100,15 @@ public static function table(Table $table): Table ViewAction::make(), DeleteAction::make() ->label(__('core::core.drop')) - ->action(function ($record) { + ->action(function ($record): void { try { $record->delete(); Notification::make() ->title('Deleted successfully') ->success() ->send(); - } catch (\Exception $e) { - Log::error('Failed to delete record: '.$e->getMessage()); + } catch (Exception $exception) { + Log::error('Failed to delete record: '.$exception->getMessage()); Notification::make() ->title('Error on deleting') ->success() @@ -116,6 +121,7 @@ public static function table(Table $table): Table ]); } + #[Override] public static function getRelations(): array { return [ @@ -123,6 +129,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -132,6 +139,7 @@ public static function getPages(): array ]; } + #[Override] public static function getWidgets(): array { return [ @@ -140,36 +148,43 @@ public static function getWidgets(): array ]; } + #[Override] public static function getModelLabel(): string { return config('user-session.resources.session.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('user-session.resources.session.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('user-session.resources.session.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('user-session.resources.session.single'); } + #[Override] public static function shouldRegisterNavigation(): bool { return true; } + #[Override] public static function getNavigationGroup(): ?string { return config('user-session.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('user-session.navigation_sort') + 3; diff --git a/packages/user-session/src/Resources/UserSessionResource/Pages/ListPage.php b/packages/user-session/src/Resources/UserSessionResource/Pages/ListPage.php index 18cc145d7..cf3b6151c 100644 --- a/packages/user-session/src/Resources/UserSessionResource/Pages/ListPage.php +++ b/packages/user-session/src/Resources/UserSessionResource/Pages/ListPage.php @@ -7,6 +7,7 @@ use Moox\UserSession\Models\UserSession; use Moox\UserSession\Resources\UserSessionResource; use Moox\UserSession\Resources\UserSessionResource\Widgets\UserSessionWidgets; +use Override; class ListPage extends ListRecords { @@ -14,12 +15,13 @@ class ListPage extends ListRecords public static string $resource = UserSessionResource::class; - public function getActions(): array + protected function getActions(): array { return []; } - public function getHeaderWidgets(): array + #[Override] + protected function getHeaderWidgets(): array { return [ // TODO: Widgets @@ -27,6 +29,7 @@ public function getHeaderWidgets(): array ]; } + #[Override] public function getTitle(): string { return __('core::session.title'); diff --git a/packages/user-session/src/Resources/UserSessionResource/Widgets/UserSessionWidgets.php b/packages/user-session/src/Resources/UserSessionResource/Widgets/UserSessionWidgets.php index c1a2b576a..9e0ca38be 100644 --- a/packages/user-session/src/Resources/UserSessionResource/Widgets/UserSessionWidgets.php +++ b/packages/user-session/src/Resources/UserSessionResource/Widgets/UserSessionWidgets.php @@ -6,9 +6,11 @@ use Filament\Widgets\StatsOverviewWidget\Stat; use Illuminate\Support\Facades\DB; use Moox\UserSession\Models\UserSession; +use Override; class UserSessionWidgets extends BaseWidget { + #[Override] protected function getCards(): array { $aggregationColumns = [ diff --git a/packages/user-session/src/Services/SessionRelationService.php b/packages/user-session/src/Services/SessionRelationService.php index 0fe84112d..7b1ffd4fd 100644 --- a/packages/user-session/src/Services/SessionRelationService.php +++ b/packages/user-session/src/Services/SessionRelationService.php @@ -2,6 +2,8 @@ namespace Moox\UserSession\Services; +use Exception; +use Log; use Moox\UserSession\Models\UserSession; class SessionRelationService @@ -10,7 +12,7 @@ public function associateUserSession($user): void { try { $sessionId = session()->getId(); - $userType = get_class($user); + $userType = $user::class; $userSession = UserSession::find($sessionId); @@ -21,10 +23,10 @@ public function associateUserSession($user): void 'last_activity' => now()->getTimestamp(), ]); } else { - \Log::warning('Session not found for ID:', ['session_id' => $sessionId]); + Log::warning('Session not found for ID:', ['session_id' => $sessionId]); } - } catch (\Exception $e) { - \Log::error('Failed to associate user session:', ['error' => $e->getMessage()]); + } catch (Exception $exception) { + Log::error('Failed to associate user session:', ['error' => $exception->getMessage()]); } } } diff --git a/packages/user-session/src/UserSessionServiceProvider.php b/packages/user-session/src/UserSessionServiceProvider.php index f281ff1f9..fb4ce0bfe 100644 --- a/packages/user-session/src/UserSessionServiceProvider.php +++ b/packages/user-session/src/UserSessionServiceProvider.php @@ -6,6 +6,7 @@ use Moox\UserSession\Commands\InstallCommand; use Moox\UserSession\Services\SessionRelationService; +use Override; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -21,16 +22,16 @@ public function configurePackage(Package $package): void ->hasCommand(InstallCommand::class); } - public function register() + #[Override] + public function register(): void { parent::register(); - $this->app->singleton(SessionRelationService::class, function ($app) { - return new SessionRelationService; - }); + $this->app->singleton(SessionRelationService::class, fn ($app): SessionRelationService => new SessionRelationService); } - public function boot() + #[Override] + public function boot(): void { parent::boot(); diff --git a/packages/user/config/user.php b/packages/user/config/user.php index b44e314fa..446d33bc7 100644 --- a/packages/user/config/user.php +++ b/packages/user/config/user.php @@ -1,5 +1,7 @@ [ 'validation' => [ - 'rules' => Illuminate\Validation\Rules\Password::min(20) + 'rules' => Password::min(20) ->max(64) ->mixedCase() ->numbers() diff --git a/packages/user/src/Commands/InstallCommand.php b/packages/user/src/Commands/InstallCommand.php index 33af82f24..01289a703 100644 --- a/packages/user/src/Commands/InstallCommand.php +++ b/packages/user/src/Commands/InstallCommand.php @@ -2,6 +2,7 @@ namespace Moox\User\Commands; +use BezhanSalleh\FilamentShield\FilamentShieldServiceProvider; use Illuminate\Console\Command; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Schema; @@ -32,7 +33,7 @@ class InstallCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->art(); $this->welcome(); @@ -78,6 +79,7 @@ public function publishConfiguration(): void return; } + warning('The User config already exist. The config will not be published.'); } } @@ -110,7 +112,7 @@ public function customizeFilament(): void if (! File::exists($translationPath)) { $this->call('vendor:publish', [ - '--provider' => 'BezhanSalleh\FilamentShield\FilamentShieldServiceProvider', + '--provider' => FilamentShieldServiceProvider::class, '--tag' => 'translations', ]); @@ -130,7 +132,7 @@ public function customizeFilament(): void $outputPath = $file->getPathname(); $content = "info("Updated {$file->getFilename()} in {$localePath}"); + $this->info(sprintf('Updated %s in %s', $file->getFilename(), $localePath)); } } } @@ -161,22 +163,22 @@ public function registerPlugins(string $providerPath): void foreach ($pluginsToAdd as $plugin) { $searchPlugin = '/'.$plugin.'/'; if (preg_match($searchPlugin, $content)) { - warning("$plugin already registered."); + warning($plugin.' already registered.'); } else { $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; } } - if ($newPlugins) { + if ($newPlugins !== '' && $newPlugins !== '0') { if (preg_match($pattern, $content)) { info('Plugins section found. Adding new plugins...'); - $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $replacement = "->plugins([$1\n{$newPlugins}\n ]);"; $newContent = preg_replace($pattern, $replacement, $content); } else { info('Plugins section created. Adding new plugins...'); - $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $pluginsSection = " ->plugins([\n{$newPlugins}\n ]);"; $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; $replacement = "$1\n".$pluginsSection; $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); @@ -217,12 +219,14 @@ public function getPanelProviderPath(): string|array foreach ($providers as $provider) { $providerNames[] = $provider->getBasename(); } + $providerPath = multiselect( label: 'Which Panel should it be registered', options: [...$providerNames], default: [$providerNames[0]], ); } + if (count($providers) == 1) { $providerPath .= '/'.$providers[0]->getBasename(); } diff --git a/packages/user/src/Models/User.php b/packages/user/src/Models/User.php index 679bbd54c..aeacde838 100644 --- a/packages/user/src/Models/User.php +++ b/packages/user/src/Models/User.php @@ -15,7 +15,11 @@ class User extends Authenticatable implements FilamentUser, HasAvatar { - use HasFactory, HasRoles, Notifiable, SoftDeletes, TwoFactorAuthenticatable; + use HasFactory; + use HasRoles; + use Notifiable; + use SoftDeletes; + use TwoFactorAuthenticatable; protected $fillable = [ 'name', diff --git a/packages/user/src/Resources/UserResource.php b/packages/user/src/Resources/UserResource.php index bbe963e5e..7370adda7 100644 --- a/packages/user/src/Resources/UserResource.php +++ b/packages/user/src/Resources/UserResource.php @@ -31,10 +31,12 @@ use Moox\User\Resources\UserResource\Pages\EditUser; use Moox\User\Resources\UserResource\Pages\ListUsers; use Moox\User\Resources\UserResource\Pages\ViewUser; +use Override; class UserResource extends Resource { - use BaseInResource, TabsInResource; + use BaseInResource; + use TabsInResource; protected static ?string $model = User::class; @@ -42,6 +44,7 @@ class UserResource extends Resource protected static ?string $recordTitleAttribute = 'name'; + #[Override] public static function form(Form $form): Form { return $form->schema([ @@ -167,7 +170,7 @@ public static function form(Form $form): Form ->unique( 'users', 'email', - fn (?Model $record) => $record + fn (?Model $record): ?Model => $record ) ->email() ->columnSpan([ @@ -265,6 +268,7 @@ public static function form(Form $form): Form ]); } + #[Override] public static function table(Table $table): Table { return $table @@ -278,9 +282,7 @@ public static function table(Table $table): Table ->size(50), TextColumn::make('name') ->label(__('core::user.name')) - ->formatStateUsing(function ($state, User $user) { - return $user->first_name.' '.$user->last_name; - }) + ->formatStateUsing(fn ($state, User $user): string => $user->first_name.' '.$user->last_name) ->toggleable() ->sortable() ->searchable() @@ -301,8 +303,8 @@ public static function table(Table $table): Table $record->email_verified_at) ? 'heroicon-o-x-circle' : 'heroicon-o-check-circle' ) ->colors([ - 'success' => fn ($record) => $record->email_verified_at !== null, - 'danger' => fn ($record) => $record->email_verified_at === null, + 'success' => fn ($record): bool => $record->email_verified_at !== null, + 'danger' => fn ($record): bool => $record->email_verified_at === null, ]), IconColumn::make('roles.name') ->label(__('core::user.roles')) @@ -331,6 +333,7 @@ public static function table(Table $table): Table ])); } + #[Override] public static function getRelations(): array { return [ @@ -341,6 +344,7 @@ public static function getRelations(): array ]; } + #[Override] public static function getPages(): array { return [ @@ -351,31 +355,37 @@ public static function getPages(): array ]; } + #[Override] public static function getModelLabel(): string { return config('user.resources.user.single'); } + #[Override] public static function getPluralModelLabel(): string { return config('user.resources.user.plural'); } + #[Override] public static function getNavigationLabel(): string { return config('user.resources.user.plural'); } + #[Override] public static function getBreadcrumb(): string { return config('user.resources.user.single'); } + #[Override] public static function getNavigationGroup(): ?string { return config('user.navigation_group'); } + #[Override] public static function getNavigationSort(): ?int { return config('user.navigation_sort') + 1; diff --git a/packages/user/src/Resources/UserResource/Pages/EditUser.php b/packages/user/src/Resources/UserResource/Pages/EditUser.php index f12b1f24d..45edd5e5a 100644 --- a/packages/user/src/Resources/UserResource/Pages/EditUser.php +++ b/packages/user/src/Resources/UserResource/Pages/EditUser.php @@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Hash; use Moox\User\Models\User; use Moox\User\Resources\UserResource; +use Override; use STS\FilamentImpersonate\Pages\Actions\Impersonate; class EditUser extends EditRecord @@ -20,6 +21,7 @@ protected function getHeaderActions(): array return [DeleteAction::make(), Impersonate::make()->record($this->getRecord())]; } + #[Override] protected function mutateFormDataBeforeSave(array $data): array { if (filled($data['new_password'])) { @@ -40,6 +42,7 @@ public function afterSave() return redirect('moox/users'); } + #[Override] protected function getSavedNotification(): ?Notification { return Notification::make() diff --git a/packages/user/src/Services/Login.php b/packages/user/src/Services/Login.php index 0046b3bb1..100424da6 100644 --- a/packages/user/src/Services/Login.php +++ b/packages/user/src/Services/Login.php @@ -23,13 +23,17 @@ use Illuminate\Support\HtmlString; use Illuminate\Validation\ValidationException; use Jenssegers\Agent\Agent; +use Moox\UserDevice\Services\UserDeviceTracker; +use Moox\UserSession\Services\SessionRelationService; +use Override; /** * @property Form $form */ class Login extends SimplePage { - use InteractsWithFormActions, WithRateLimiting; + use InteractsWithFormActions; + use WithRateLimiting; protected $userDeviceTracker; @@ -47,12 +51,12 @@ class Login extends SimplePage public function __construct() { - if (class_exists(\Moox\UserDevice\Services\UserDeviceTracker::class)) { - $this->userDeviceTracker = app(\Moox\UserDevice\Services\UserDeviceTracker::class); + if (class_exists(UserDeviceTracker::class)) { + $this->userDeviceTracker = app(UserDeviceTracker::class); } - if (class_exists(\Moox\UserSession\Services\SessionRelationService::class)) { - $this->sessionRelationService = app(\Moox\UserSession\Services\SessionRelationService::class); + if (class_exists(SessionRelationService::class)) { + $this->sessionRelationService = app(SessionRelationService::class); } } @@ -113,10 +117,10 @@ public function authenticate(): Redirector|RedirectResponse|LoginResponse|null $data = $this->form->getState(); $credentials = $this->getCredentialsFromFormData($data); $credentialKey = array_key_first($credentials); - $guardProvider = config("auth.guards.$guardName.provider"); - $userModel = config("auth.providers.$guardProvider.model"); - $userModelUsername = config("user.auth.$guardName.username"); - $userModelEmail = config("user.auth.$guardName.email"); + $guardProvider = config(sprintf('auth.guards.%s.provider', $guardName)); + $userModel = config(sprintf('auth.providers.%s.model', $guardProvider)); + $userModelUsername = config(sprintf('user.auth.%s.username', $guardName)); + $userModelEmail = config(sprintf('user.auth.%s.email', $guardName)); $query = $userModel::query(); if (! empty($userModelUsername) && $credentialKey === 'name') { @@ -210,11 +214,13 @@ public function registerAction(): Action ->url(filament()->getRegistrationUrl()); } + #[Override] public function getTitle(): string|Htmlable { return __('filament-panels::pages/auth/login.title'); } + #[Override] public function getHeading(): string|Htmlable { return __('filament-panels::pages/auth/login.heading'); @@ -252,6 +258,7 @@ private function isWhitelisted(): bool if (is_array($ipWhiteList) && in_array($ipAddress, $ipWhiteList)) { return true; } + if ($ipWhiteList === $ipAddress) { return true; } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 0942025c3..60acf5ad5 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -16,3 +16,5 @@ parameters: - 'packages/sync' - 'packages/*/tests/*' tmpDir: build/phpstan + ignoreErrors: + - "#Called 'env' outside of the config directory which returns null when the config is cached, use 'config'#" diff --git a/public/build/assets/app-DwIXNj71.css b/public/build/assets/app-DwIXNj71.css new file mode 100644 index 000000000..665aa06e2 --- /dev/null +++ b/public/build/assets/app-DwIXNj71.css @@ -0,0 +1 @@ +*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:sans,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[type=text],input:where(:not([type])),[type=email],[type=url],[type=password],[type=number],[type=date],[type=datetime-local],[type=month],[type=search],[type=tel],[type=time],[type=week],[multiple],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow: 0 0 #0000}[type=text]:focus,input:where(:not([type])):focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=month]:focus,[type=search]:focus,[type=tel]:focus,[type=time]:focus,[type=week]:focus,[multiple]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:initial;background-position:initial;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow: 0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}@media (forced-colors: active){[type=checkbox]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}@media (forced-colors: active){[type=radio]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}@media (forced-colors: active){[type=checkbox]:indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);text-decoration:underline;font-weight:500}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:disc;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{font-weight:400;color:var(--tw-prose-counters)}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.25em}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:500;font-style:italic;color:var(--tw-prose-quotes);border-left-width:.25rem;border-left-color:var(--tw-prose-quote-borders);quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:900;color:inherit}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:800;color:inherit}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){display:block;margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:500;font-family:inherit;color:var(--tw-prose-kbd);box-shadow:0 0 0 1px rgb(var(--tw-prose-kbd-shadows) / 10%),0 3px rgb(var(--tw-prose-kbd-shadows) / 10%);font-size:.875em;border-radius:.3125rem;padding:.1875em .375em}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-weight:600;font-size:.875em}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:"`"}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);overflow-x:auto;font-weight:400;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:none}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose{--tw-prose-body: #374151;--tw-prose-headings: #111827;--tw-prose-lead: #4b5563;--tw-prose-links: #111827;--tw-prose-bold: #111827;--tw-prose-counters: #6b7280;--tw-prose-bullets: #d1d5db;--tw-prose-hr: #e5e7eb;--tw-prose-quotes: #111827;--tw-prose-quote-borders: #e5e7eb;--tw-prose-captions: #6b7280;--tw-prose-kbd: #111827;--tw-prose-kbd-shadows: 17 24 39;--tw-prose-code: #111827;--tw-prose-pre-code: #e5e7eb;--tw-prose-pre-bg: #1f2937;--tw-prose-th-borders: #d1d5db;--tw-prose-td-borders: #e5e7eb;--tw-prose-invert-body: #d1d5db;--tw-prose-invert-headings: #fff;--tw-prose-invert-lead: #9ca3af;--tw-prose-invert-links: #fff;--tw-prose-invert-bold: #fff;--tw-prose-invert-counters: #9ca3af;--tw-prose-invert-bullets: #4b5563;--tw-prose-invert-hr: #374151;--tw-prose-invert-quotes: #f3f4f6;--tw-prose-invert-quote-borders: #374151;--tw-prose-invert-captions: #9ca3af;--tw-prose-invert-kbd: #fff;--tw-prose-invert-kbd-shadows: 255 255 255;--tw-prose-invert-code: #fff;--tw-prose-invert-pre-code: #d1d5db;--tw-prose-invert-pre-bg: rgb(0 0 0 / 50%);--tw-prose-invert-th-borders: #4b5563;--tw-prose-invert-td-borders: #374151;font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>*:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>*:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>*:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>*:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-left:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding:.5714286em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-4{top:1rem;right:1rem;bottom:1rem;left:1rem}.inset-y-0{top:0;bottom:0}.-bottom-1\/2{bottom:-50%}.-top-1\/2{top:-50%}.bottom-0{bottom:0}.bottom-1\/2{bottom:50%}.end-0{inset-inline-end:0px}.end-4{inset-inline-end:1rem}.end-6{inset-inline-end:1.5rem}.start-0{inset-inline-start:0px}.start-full{inset-inline-start:100%}.top-0{top:0}.top-1{top:.25rem}.top-1\/2{top:50%}.top-4{top:1rem}.top-6{top:1.5rem}.z-0{z-index:0}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[1\]{z-index:1}.col-\[--col-span-default\]{grid-column:var(--col-span-default)}.col-start-\[--col-start-default\]{grid-column-start:var(--col-start-default)}.row-start-2{grid-row-start:2}.-m-0{margin:-0px}.-m-0\.5{margin:-.125rem}.-m-1{margin:-.25rem}.-m-1\.5{margin:-.375rem}.-m-2{margin:-.5rem}.-m-2\.5{margin:-.625rem}.-m-3{margin:-.75rem}.-m-3\.5{margin:-.875rem}.m-10{margin:2.5rem}.m-12{margin:3rem}.m-5{margin:1.25rem}.m-8{margin:2rem}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.-mx-4{margin-left:-1rem;margin-right:-1rem}.-my-1{margin-top:-.25rem;margin-bottom:-.25rem}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.mx-auto{margin-left:auto;margin-right:auto}.my-16{margin-top:4rem;margin-bottom:4rem}.my-auto{margin-top:auto;margin-bottom:auto}.-me-2{margin-inline-end:-.5rem}.-ml-px{margin-left:-1px}.-ms-1{margin-inline-start:-.25rem}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.me-4{margin-inline-end:1rem}.me-6{margin-inline-end:1.5rem}.ml-3{margin-left:.75rem}.ms-6{margin-inline-start:1.5rem}.ms-auto{margin-inline-start:auto}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-6{margin-top:1.5rem}.mt-auto{margin-top:auto}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.inline-grid{display:inline-grid}.contents{display:contents}.hidden{display:none}.h-0{height:0px}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-16{height:4rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[100dvh\],.h-dvh{height:100dvh}.h-full{height:100%}.h-screen{height:100vh}.min-h-full{min-height:100%}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[--sidebar-width\]{width:var(--sidebar-width)}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-px{width:1px}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[theme\(spacing\.4\)\]{min-width:1rem}.min-w-\[theme\(spacing\.5\)\]{min-width:1.25rem}.min-w-\[theme\(spacing\.6\)\]{min-width:1.5rem}.\!max-w-2xl{max-width:42rem!important}.\!max-w-3xl{max-width:48rem!important}.\!max-w-4xl{max-width:56rem!important}.\!max-w-5xl{max-width:64rem!important}.\!max-w-6xl{max-width:72rem!important}.\!max-w-7xl{max-width:80rem!important}.\!max-w-\[14rem\]{max-width:14rem!important}.\!max-w-lg{max-width:32rem!important}.\!max-w-md{max-width:28rem!important}.\!max-w-sm{max-width:24rem!important}.\!max-w-xl{max-width:36rem!important}.\!max-w-xs{max-width:20rem!important}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-max{max-width:-moz-max-content;max-width:max-content}.max-w-md{max-width:28rem}.max-w-min{max-width:-moz-min-content;max-width:min-content}.max-w-prose{max-width:65ch}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.max-w-screen-md{max-width:768px}.max-w-screen-sm{max-width:640px}.max-w-screen-xl{max-width:1280px}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-1\/4{--tw-translate-x: -25%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-3\/4{--tw-translate-y: -75%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-rotate-180{--tw-rotate: -180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x: 1;--tw-scale-y: 1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-95{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.columns-\[--cols-default\]{-moz-columns:var(--cols-default);columns:var(--cols-default)}.auto-cols-fr{grid-auto-columns:minmax(0,1fr)}.grid-flow-col{grid-auto-flow:column}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-\[--cols-default\]{grid-template-columns:var(--cols-default)}.grid-cols-\[repeat\(auto-fit\,minmax\(0\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.grid-rows-\[1fr_auto_1fr\]{grid-template-rows:1fr auto 1fr}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-items-center{justify-items:center}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-1{-moz-column-gap:.25rem;column-gap:.25rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-x-5{-moz-column-gap:1.25rem;column-gap:1.25rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-y-1{row-gap:.25rem}.gap-y-2{row-gap:.5rem}.gap-y-4{row-gap:1rem}.gap-y-6{row-gap:1.5rem}.gap-y-7{row-gap:1.75rem}.gap-y-8{row-gap:2rem}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity))}.self-start{align-self:flex-start}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-x-clip{overflow-x:clip}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.rounded-l-md{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.rounded-r-md{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-e{border-inline-end-width:1px}.border-s{border-inline-start-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-\[\#002945\]{--tw-border-opacity: 1;border-color:rgb(0 41 69 / var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity))}.bg-\[\#001829\]{--tw-bg-opacity: 1;background-color:rgb(0 24 41 / var(--tw-bg-opacity))}.bg-\[\#002945\]{--tw-bg-opacity: 1;background-color:rgb(0 41 69 / var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.bg-gray-950\/50{background-color:#03071280}.bg-sky-900{--tw-bg-opacity: 1;background-color:rgb(12 74 110 / var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-white\/0{background-color:#fff0}.bg-cover{background-size:cover}.bg-center{background-position:center}.bg-right-top{background-position:right top}.bg-no-repeat{background-repeat:no-repeat}.object-cover{-o-object-fit:cover;object-fit:cover}.object-center{-o-object-position:center;object-position:center}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-6{padding-bottom:1.5rem}.pe-0{padding-inline-end:0px}.pe-1{padding-inline-end:.25rem}.pe-2{padding-inline-end:.5rem}.pe-3{padding-inline-end:.75rem}.pe-4{padding-inline-end:1rem}.pe-6{padding-inline-end:1.5rem}.ps-0{padding-inline-start:0px}.ps-1{padding-inline-start:.25rem}.ps-2{padding-inline-start:.5rem}.ps-3{padding-inline-start:.75rem}.ps-\[5\.25rem\]{padding-inline-start:5.25rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-center{text-align:center}.text-start{text-align:start}.font-sans{font-family:sans,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-extralight{font-weight:200}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.font-thin{font-weight:100}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.tracking-tight{letter-spacing:-.025em}.tracking-tighter{letter-spacing:-.05em}.text-\[\#0e9bdc\]{--tw-text-opacity: 1;color:rgb(14 155 220 / var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.text-gray-700\/50{color:#37415180}.text-gray-950{--tw-text-opacity: 1;color:rgb(3 7 18 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-70{opacity:.7}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-inset{--tw-ring-inset: inset}.ring-gray-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity))}.ring-gray-600\/10{--tw-ring-color: rgb(75 85 99 / .1)}.ring-gray-950\/10{--tw-ring-color: rgb(3 7 18 / .1)}.ring-gray-950\/5{--tw-ring-color: rgb(3 7 18 / .05)}.drop-shadow{--tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / .1)) drop-shadow(0 1px 1px rgb(0 0 0 / .06));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.delay-100{transition-delay:.1s}.duration-150{transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.tooltip{visibility:hidden;position:absolute}.has-tooltip:hover .tooltip{visibility:visible;z-index:50}.mt-105{margin-top:10.5rem}[x-cloak]{display:none!important}h1{font-size:1.875rem;line-height:2.25rem;font-family:Exo,sans-serif}:is(.dark .dark\:prose-invert){--tw-prose-body: var(--tw-prose-invert-body);--tw-prose-headings: var(--tw-prose-invert-headings);--tw-prose-lead: var(--tw-prose-invert-lead);--tw-prose-links: var(--tw-prose-invert-links);--tw-prose-bold: var(--tw-prose-invert-bold);--tw-prose-counters: var(--tw-prose-invert-counters);--tw-prose-bullets: var(--tw-prose-invert-bullets);--tw-prose-hr: var(--tw-prose-invert-hr);--tw-prose-quotes: var(--tw-prose-invert-quotes);--tw-prose-quote-borders: var(--tw-prose-invert-quote-borders);--tw-prose-captions: var(--tw-prose-invert-captions);--tw-prose-kbd: var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows: var(--tw-prose-invert-kbd-shadows);--tw-prose-code: var(--tw-prose-invert-code);--tw-prose-pre-code: var(--tw-prose-invert-pre-code);--tw-prose-pre-bg: var(--tw-prose-invert-pre-bg);--tw-prose-th-borders: var(--tw-prose-invert-th-borders);--tw-prose-td-borders: var(--tw-prose-invert-td-borders)}.placeholder\:text-gray-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.placeholder\:text-gray-400::placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.checked\:ring-0:checked{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.hover\:bg-gray-400\/10:hover{background-color:#9ca3af1a}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.hover\:text-\[\#69bce2\]:hover{--tw-text-opacity: 1;color:rgb(105 188 226 / var(--tw-text-opacity))}.hover\:text-gray-400:hover{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.hover\:text-gray-500:hover{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.hover\:text-gray-700\/75:hover{color:#374151bf}.focus\:z-10:focus{z-index:10}.focus\:border-blue-300:focus{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-offset-0:focus{--tw-ring-offset-width: 0px}.focus-visible\:bg-gray-100:focus-visible{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.focus-visible\:bg-gray-50:focus-visible{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.focus-visible\:text-gray-500:focus-visible{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.focus-visible\:text-gray-700\/75:focus-visible{color:#374151bf}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-gray-400\/40:focus-visible{--tw-ring-color: rgb(156 163 175 / .4)}.active\:bg-gray-100:active{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.active\:text-gray-500:active{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.active\:text-gray-700:active{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.enabled\:cursor-wait:enabled{cursor:wait}.enabled\:opacity-70:enabled{opacity:.7}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:bg-gray-50:disabled{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.disabled\:text-gray-50:disabled{--tw-text-opacity: 1;color:rgb(249 250 251 / var(--tw-text-opacity))}.disabled\:text-gray-500:disabled{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.disabled\:opacity-70:disabled{opacity:.7}.disabled\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled{-webkit-text-fill-color:#6b7280}.disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled::-moz-placeholder{-webkit-text-fill-color:#9ca3af}.disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled::placeholder{-webkit-text-fill-color:#9ca3af}.disabled\:checked\:bg-gray-400:checked:disabled{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity))}.disabled\:checked\:text-gray-400:checked:disabled{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.group\/link:hover .group-hover\/link\:underline{text-decoration-line:underline}.group\/link:focus-visible .group-focus-visible\/link\:underline{text-decoration-line:underline}:is(.dark .dark\:flex){display:flex}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-white\/5)>:not([hidden])~:not([hidden]){border-color:#ffffff0d}:is(.dark .dark\:border-gray-600){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity))}:is(.dark .dark\:border-white\/10){border-color:#ffffff1a}:is(.dark .dark\:bg-gray-400\/10){background-color:#9ca3af1a}:is(.dark .dark\:bg-gray-500){--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-500\/20){background-color:#6b728033}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-950){--tw-bg-opacity: 1;background-color:rgb(3 7 18 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-950\/75){background-color:#030712bf}:is(.dark .dark\:bg-transparent){background-color:transparent}:is(.dark .dark\:bg-white\/5){background-color:#ffffff0d}:is(.dark .dark\:text-gray-200){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300\/50){color:#d1d5db80}:is(.dark .dark\:text-gray-400){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}:is(.dark .dark\:text-gray-600){--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}:is(.dark .dark\:ring-gray-400\/20){--tw-ring-color: rgb(156 163 175 / .2)}:is(.dark .dark\:ring-gray-700){--tw-ring-opacity: 1;--tw-ring-color: rgb(55 65 81 / var(--tw-ring-opacity))}:is(.dark .dark\:ring-white\/10){--tw-ring-color: rgb(255 255 255 / .1)}:is(.dark .dark\:ring-white\/20){--tw-ring-color: rgb(255 255 255 / .2)}:is(.dark .dark\:placeholder\:text-gray-500)::-moz-placeholder{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}:is(.dark .dark\:placeholder\:text-gray-500)::placeholder{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}:is(.dark .dark\:hover\:bg-white\/10:hover){background-color:#ffffff1a}:is(.dark .dark\:hover\:bg-white\/5:hover){background-color:#ffffff0d}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300\/75:hover){color:#d1d5dbbf}:is(.dark .dark\:hover\:text-gray-400:hover){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-700:focus){--tw-border-opacity: 1;border-color:rgb(29 78 216 / var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-blue-800:focus){--tw-border-opacity: 1;border-color:rgb(30 64 175 / var(--tw-border-opacity))}:is(.dark .dark\:focus-visible\:bg-white\/5:focus-visible){background-color:#ffffff0d}:is(.dark .dark\:focus-visible\:text-gray-300\/75:focus-visible){color:#d1d5dbbf}:is(.dark .dark\:focus-visible\:text-gray-400:focus-visible){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}:is(.dark .dark\:active\:bg-gray-700:active){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity))}:is(.dark .dark\:active\:text-gray-300:active){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}:is(.dark .dark\:disabled\:bg-transparent:disabled){background-color:transparent}:is(.dark .dark\:disabled\:text-gray-400:disabled){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}:is(.dark .dark\:disabled\:ring-white\/10:disabled){--tw-ring-color: rgb(255 255 255 / .1)}:is(.dark .dark\:disabled\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled){-webkit-text-fill-color:#9ca3af}:is(.dark .dark\:disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled)::-moz-placeholder{-webkit-text-fill-color:#6b7280}:is(.dark .dark\:disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled)::placeholder{-webkit-text-fill-color:#6b7280}:is(.dark .dark\:disabled\:checked\:bg-gray-600:checked:disabled){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity))}@media (min-width: 640px){.sm\:relative{position:relative}.sm\:col-\[--col-span-sm\]{grid-column:var(--col-span-sm)}.sm\:col-span-2{grid-column:span 2 / span 2}.sm\:col-start-\[--col-start-sm\]{grid-column-start:var(--col-start-sm)}.sm\:mt-7{margin-top:1.75rem}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:grid{display:grid}.sm\:inline-grid{display:inline-grid}.sm\:hidden{display:none}.sm\:max-w-2xl{max-width:42rem}.sm\:flex-1{flex:1 1 0%}.sm\:columns-\[--cols-sm\]{-moz-columns:var(--cols-sm);columns:var(--cols-sm)}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-\[--cols-sm\]{grid-template-columns:var(--cols-sm)}.sm\:grid-cols-\[repeat\(auto-fit\,minmax\(0\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:grid-rows-\[1fr_auto_3fr\]{grid-template-rows:1fr auto 3fr}.sm\:flex-row{flex-direction:row}.sm\:items-start{align-items:flex-start}.sm\:items-end{align-items:flex-end}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.sm\:rounded-lg{border-radius:.5rem}.sm\:rounded-xl{border-radius:.75rem}.sm\:px-12{padding-left:3rem;padding-right:3rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:pt-1{padding-top:.25rem}.sm\:pt-1\.5{padding-top:.375rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:leading-6{line-height:1.5rem}}@media (min-width: 768px){.md\:bottom-4{bottom:1rem}.md\:order-first{order:-9999}.md\:col-\[--col-span-md\]{grid-column:var(--col-span-md)}.md\:col-span-2{grid-column:span 2 / span 2}.md\:col-start-\[--col-start-md\]{grid-column-start:var(--col-start-md)}.md\:inline-grid{display:inline-grid}.md\:hidden{display:none}.md\:columns-\[--cols-md\]{-moz-columns:var(--cols-md);columns:var(--cols-md)}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[--cols-md\]{grid-template-columns:var(--cols-md)}.md\:flex-row{flex-direction:row}.md\:items-start{align-items:flex-start}.md\:rounded-xl{border-radius:.75rem}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:pe-6{padding-inline-end:1.5rem}}@media (min-width: 1024px){.lg\:sticky{position:sticky}.lg\:z-0{z-index:0}.lg\:col-\[--col-span-lg\]{grid-column:var(--col-span-lg)}.lg\:col-start-\[--col-start-lg\]{grid-column-start:var(--col-start-lg)}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:inline-grid{display:inline-grid}.lg\:hidden{display:none}.lg\:-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.lg\:translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.lg\:columns-\[--cols-lg\]{-moz-columns:var(--cols-lg);columns:var(--cols-lg)}.lg\:grid-cols-\[--cols-lg\]{grid-template-columns:var(--cols-lg)}.lg\:bg-transparent{background-color:transparent}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:pe-8{padding-inline-end:2rem}.lg\:shadow-none{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.lg\:shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.lg\:ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.lg\:transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.lg\:transition-none{transition-property:none}.lg\:delay-100{transition-delay:.1s}:is(.dark .dark\:lg\:bg-transparent){background-color:transparent}}@media (min-width: 1280px){.xl\:col-\[--col-span-xl\]{grid-column:var(--col-span-xl)}.xl\:col-start-\[--col-start-xl\]{grid-column-start:var(--col-start-xl)}.xl\:inline-grid{display:inline-grid}.xl\:hidden{display:none}.xl\:columns-\[--cols-xl\]{-moz-columns:var(--cols-xl);columns:var(--cols-xl)}.xl\:grid-cols-\[--cols-xl\]{grid-template-columns:var(--cols-xl)}}@media (min-width: 1536px){.\32xl\:col-\[--col-span-2xl\]{grid-column:var(--col-span-2xl)}.\32xl\:col-start-\[--col-start-2xl\]{grid-column-start:var(--col-start-2xl)}.\32xl\:inline-grid{display:inline-grid}.\32xl\:hidden{display:none}.\32xl\:columns-\[--cols-2xl\]{-moz-columns:var(--cols-2xl);columns:var(--cols-2xl)}.\32xl\:grid-cols-\[--cols-2xl\]{grid-template-columns:var(--cols-2xl)}}.rtl\:-translate-x-0:where([dir=rtl],[dir=rtl] *){--tw-translate-x: -0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rtl\:-translate-x-full:where([dir=rtl],[dir=rtl] *){--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rtl\:translate-x-1\/2:where([dir=rtl],[dir=rtl] *){--tw-translate-x: 50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rtl\:translate-x-1\/4:where([dir=rtl],[dir=rtl] *){--tw-translate-x: 25%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rtl\:translate-x-full:where([dir=rtl],[dir=rtl] *){--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rtl\:flex-row-reverse:where([dir=rtl],[dir=rtl] *){flex-direction:row-reverse}@media (min-width: 1024px){.rtl\:lg\:-translate-x-0:where([dir=rtl],[dir=rtl] *){--tw-translate-x: -0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rtl\:lg\:translate-x-full:where([dir=rtl],[dir=rtl] *){--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}}.\[\&\:\:-ms-reveal\]\:hidden::-ms-reveal{display:none}.\[\&\:not\(\:has\(\.fi-ac-action\:focus\)\)\]\:focus-within\:ring-2:focus-within:not(:has(.fi-ac-action:focus)){--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.\[\&\:not\(\:nth-child\(1_of_\.fi-btn\)\)\]\:shadow-\[-1px_0_0_0_theme\(colors\.gray\.200\)\]:not(:nth-child(1 of.fi-btn)){--tw-shadow: -1px 0 0 0 #e5e7eb;--tw-shadow-colored: -1px 0 0 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}:is(.dark .dark\:\[\&\:not\(\:nth-child\(1_of_\.fi-btn\)\)\]\:shadow-\[-1px_0_0_0_theme\(colors\.white\/20\%\)\]:not(:nth-child(1 of.fi-btn))){--tw-shadow: -1px 0 0 0 rgb(255 255 255 / 20%);--tw-shadow-colored: -1px 0 0 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.\[\&\:not\(\:nth-last-child\(1_of_\.fi-btn\)\)\]\:me-px:not(:nth-last-child(1 of.fi-btn)){margin-inline-end:1px}.\[\&\:nth-child\(1_of_\.fi-btn\)\]\:rounded-s-lg:nth-child(1 of.fi-btn){border-start-start-radius:.5rem;border-end-start-radius:.5rem}.\[\&\:nth-last-child\(1_of_\.fi-btn\)\]\:rounded-e-lg:nth-last-child(1 of.fi-btn){border-start-end-radius:.5rem;border-end-end-radius:.5rem}:checked+*>.\[\:checked\+\*\>\&\]\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}input:checked+.\[input\:checked\+\&\]\:bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity))}input:checked+.\[input\:checked\+\&\]\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}input:checked+.\[input\:checked\+\&\]\:ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}input:checked+.\[input\:checked\+\&\]\:hover\:bg-gray-300:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity))}:is(.dark input:checked+.dark\:\[input\:checked\+\&\]\:bg-gray-600){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity))}:is(.dark input:checked+.dark\:\[input\:checked\+\&\]\:hover\:bg-gray-500:hover){--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity))}input:focus-visible+.\[input\:focus-visible\+\&\]\:z-10{z-index:10}input:focus-visible+.\[input\:focus-visible\+\&\]\:ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}input:focus-visible+.\[input\:focus-visible\+\&\]\:ring-gray-950\/10{--tw-ring-color: rgb(3 7 18 / .1)}:is(.dark input:focus-visible+.dark\:\[input\:focus-visible\+\&\]\:ring-white\/20){--tw-ring-color: rgb(255 255 255 / .2)} diff --git a/public/build/manifest.json b/public/build/manifest.json index b4f17ec13..05042abca 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -1,6 +1,6 @@ { "resources/css/app.css": { - "file": "assets/app-D7iVuhjt.css", + "file": "assets/app-DwIXNj71.css", "src": "resources/css/app.css", "isEntry": true }, diff --git a/public/js/filament/forms/components/key-value.js b/public/js/filament/forms/components/key-value.js index 9c847c018..47b51b1b1 100644 --- a/public/js/filament/forms/components/key-value.js +++ b/public/js/filament/forms/components/key-value.js @@ -1 +1 @@ -function r({state:o}){return{state:o,rows:[],shouldUpdateRows:!0,init:function(){this.updateRows(),this.rows.length<=0?this.rows.push({key:"",value:""}):this.updateState(),this.$watch("state",(t,e)=>{let s=i=>i===null?0:Array.isArray(i)?i.length:typeof i!="object"?0:Object.keys(i).length;s(t)===0&&s(e)===0||this.updateRows()})},addRow:function(){this.rows.push({key:"",value:""}),this.updateState()},deleteRow:function(t){this.rows.splice(t,1),this.rows.length<=0&&this.addRow(),this.updateState()},reorderRows:function(t){let e=Alpine.raw(this.rows);this.rows=[];let s=e.splice(t.oldIndex,1)[0];e.splice(t.newIndex,0,s),this.$nextTick(()=>{this.rows=e,this.updateState()})},updateRows:function(){if(!this.shouldUpdateRows){this.shouldUpdateRows=!0;return}let t=[];for(let[e,s]of Object.entries(this.state??{}))t.push({key:e,value:s});this.rows=t},updateState:function(){let t={};this.rows.forEach(e=>{e.key===""||e.key===null||(t[e.key]=e.value)}),this.shouldUpdateRows=!1,this.state=t}}}export{r as default}; +function r({state:i}){return{state:i,rows:[],shouldUpdateRows:!0,init:function(){this.updateRows(),this.rows.length<=0?this.rows.push({key:"",value:""}):this.updateState(),this.$watch("state",(t,e)=>{let s=o=>o===null?0:Array.isArray(o)?o.length:typeof o!="object"?0:Object.keys(o).length;s(t)===0&&s(e)===0||(this.shouldUpdateRows=!0,this.updateRows())})},addRow:function(){this.rows.push({key:"",value:""}),this.updateState()},deleteRow:function(t){this.rows.splice(t,1),this.rows.length<=0&&this.addRow(),this.updateState()},reorderRows:function(t){let e=Alpine.raw(this.rows);this.rows=[];let s=e.splice(t.oldIndex,1)[0];e.splice(t.newIndex,0,s),this.$nextTick(()=>{this.rows=e,this.updateState()})},updateRows:function(){if(!this.shouldUpdateRows){this.shouldUpdateRows=!0;return}let t=[];for(let[e,s]of Object.entries(this.state??{}))t.push({key:e,value:s});this.rows=t},updateState:function(){let t={};this.rows.forEach(e=>{e.key===""||e.key===null||(t[e.key]=e.value)}),this.shouldUpdateRows=!1,this.state=t}}}export{r as default}; diff --git a/rector.php b/rector.php new file mode 100644 index 000000000..b41108a60 --- /dev/null +++ b/rector.php @@ -0,0 +1,40 @@ +paths([ + __DIR__.'/app', + __DIR__.'/config', + __DIR__.'/packages', + ]); + + $rectorConfig->skip([]); + + $rectorConfig->sets([ + LevelSetList::UP_TO_PHP_82, + SetList::TYPE_DECLARATION, + SetList::CODING_STYLE, + SetList::CODE_QUALITY, + SetList::DEAD_CODE, + ]); + + $rectorConfig->rule(TypedPropertyFromStrictConstructorRector::class); + $rectorConfig->rule(StrictArrayParamDimFetchRector::class); + $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); + $rectorConfig->rule(AddVoidReturnTypeWhereNoReturnRector::class); + $rectorConfig->rule(ReturnTypeFromStrictTypedCallRector::class); + $rectorConfig->rule(AddReturnTypeDeclarationRector::class); + + $rectorConfig->importNames(); +};