diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d89c2a24..daedef83 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -42,3 +42,6 @@ jobs: - name: Run test suite run: php artisan test + + - name: Run Phpstan + run: ./vendor/bin/phpstan analyze --no-progress diff --git a/app/Actions/FirewallRule/CreateRule.php b/app/Actions/FirewallRule/CreateRule.php index b06de8ae..dd2517ea 100755 --- a/app/Actions/FirewallRule/CreateRule.php +++ b/app/Actions/FirewallRule/CreateRule.php @@ -21,7 +21,6 @@ public function create(Server $server, array $input): FirewallRule 'mask' => $input['mask'] ?? null, ]); - /** @var Firewall $firewallHandler */ $firewallHandler = $server->firewall()->handler(); $firewallHandler->addRule( $rule->type, diff --git a/app/Actions/NotificationChannels/AddChannel.php b/app/Actions/NotificationChannels/AddChannel.php index 0104cfb0..48853f6b 100644 --- a/app/Actions/NotificationChannels/AddChannel.php +++ b/app/Actions/NotificationChannels/AddChannel.php @@ -59,7 +59,7 @@ public static function rules(array $input): array 'label' => 'required', ]; - return array_merge($rules, static::providerRules($input)); + return array_merge($rules, self::providerRules($input)); } private static function providerRules(array $input): array diff --git a/app/Actions/ServerProvider/CreateServerProvider.php b/app/Actions/ServerProvider/CreateServerProvider.php index 6b80cef0..67ce83e2 100644 --- a/app/Actions/ServerProvider/CreateServerProvider.php +++ b/app/Actions/ServerProvider/CreateServerProvider.php @@ -17,7 +17,7 @@ class CreateServerProvider */ public function create(User $user, Project $project, array $input): ServerProvider { - $provider = static::getProvider($input['provider']); + $provider = self::getProvider($input['provider']); try { $provider->connect($input); @@ -60,7 +60,7 @@ public static function rules(array $input): array ], ]; - return array_merge($rules, static::providerRules($input)); + return array_merge($rules, self::providerRules($input)); } private static function providerRules(array $input): array @@ -69,6 +69,6 @@ private static function providerRules(array $input): array return []; } - return static::getProvider($input['provider'])->credentialValidationRules($input); + return self::getProvider($input['provider'])->credentialValidationRules($input); } } diff --git a/app/Actions/SourceControl/ConnectSourceControl.php b/app/Actions/SourceControl/ConnectSourceControl.php index 826d291b..7b8db820 100644 --- a/app/Actions/SourceControl/ConnectSourceControl.php +++ b/app/Actions/SourceControl/ConnectSourceControl.php @@ -46,7 +46,7 @@ public static function rules(array $input): array ], ]; - return array_merge($rules, static::providerRules($input)); + return array_merge($rules, self::providerRules($input)); } /** diff --git a/app/Actions/SourceControl/EditSourceControl.php b/app/Actions/SourceControl/EditSourceControl.php index 9bde5141..00308e3c 100644 --- a/app/Actions/SourceControl/EditSourceControl.php +++ b/app/Actions/SourceControl/EditSourceControl.php @@ -35,7 +35,7 @@ public static function rules(SourceControl $sourceControl, array $input): array ], ]; - return array_merge($rules, static::providerRules($sourceControl, $input)); + return array_merge($rules, self::providerRules($sourceControl, $input)); } /** diff --git a/app/Facades/FTP.php b/app/Facades/FTP.php index 509af002..a3b519e3 100644 --- a/app/Facades/FTP.php +++ b/app/Facades/FTP.php @@ -7,12 +7,12 @@ use Illuminate\Support\Facades\Facade; /** - * @method static bool|Connection connect(string $host, string $port, bool $ssl = false) - * @method static bool login(string $username, string $password, bool|Connection $connection) - * @method static void close(bool|Connection $connection) - * @method static bool passive(bool|Connection $connection, bool $passive) - * @method static bool delete(bool|Connection $connection, string $path) - * @method static void assertConnected(string $host) + * @ method static bool|Connection connect(string $host, string $port, bool $ssl = false) + * @ method static bool login(string $username, string $password, bool|Connection $connection) + * @ method static void close(bool|Connection $connection) + * @ method static bool passive(bool|Connection $connection, bool $passive) + * @ method static bool delete(bool|Connection $connection, string $path) + * @ method static void assertConnected(string $host) */ class FTP extends Facade { diff --git a/app/Facades/SSH.php b/app/Facades/SSH.php index 5cbb0a60..2fd725d4 100644 --- a/app/Facades/SSH.php +++ b/app/Facades/SSH.php @@ -10,15 +10,15 @@ /** * Class SSH * - * @method static init(Server $server, string $asUser = null) - * @method static setLog(?ServerLog $log) - * @method static connect() - * @method static string exec(string $command, string $log = '', int $siteId = null, ?bool $stream = false, callable $streamCallback = null) - * @method static string assertExecuted(array|string $commands) - * @method static string assertExecutedContains(string $command) - * @method static string assertFileUploaded(string $toPath, ?string $content = null) - * @method static string getUploadedLocalPath() - * @method static disconnect() + * @ method static \App\Helpers\SSH init(Server $server, string $asUser = null) + * @ method static \App\Helpers\SSH setLog(?ServerLog $log) + * @ method static void connect() + * @ method static string exec(string $command, string $log = '', int $siteId = null, ?bool $stream = false, callable $streamCallback = null) + * @ method static string assertExecuted(array|string $commands) + * @ method static string assertExecutedContains(string $command) + * @ method static string assertFileUploaded(string $toPath, ?string $content = null) + * @ method static string getUploadedLocalPath() + * @ method static void disconnect() */ class SSH extends FacadeAlias { diff --git a/app/Models/Backup.php b/app/Models/Backup.php index 529f394f..cb362c60 100644 --- a/app/Models/Backup.php +++ b/app/Models/Backup.php @@ -8,19 +8,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; -/** - * @property string $type - * @property int $server_id - * @property int $storage_id - * @property int $database_id - * @property string $interval - * @property int $keep_backups - * @property string $status - * @property Server $server - * @property StorageProvider $storage - * @property Database $database - * @property BackupFile[] $files - */ class Backup extends AbstractModel { use HasFactory; @@ -58,26 +45,41 @@ public static function boot(): void BackupStatus::FAILED => 'danger', ]; + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); } + /** + * @return BelongsTo + */ public function storage(): BelongsTo { return $this->belongsTo(StorageProvider::class, 'storage_id'); } + /** + * @return BelongsTo + */ public function database(): BelongsTo { return $this->belongsTo(Database::class)->withTrashed(); } + /** + * @return HasMany + */ public function files(): HasMany { return $this->hasMany(BackupFile::class, 'backup_id'); } + /** + * @return HasOne + */ public function lastFile(): HasOne { return $this->hasOne(BackupFile::class, 'backup_id')->latest(); diff --git a/app/Models/BackupFile.php b/app/Models/BackupFile.php index b8c60dbc..f74d4d0a 100644 --- a/app/Models/BackupFile.php +++ b/app/Models/BackupFile.php @@ -7,15 +7,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $backup_id - * @property string $name - * @property int $size - * @property string $status - * @property string $restored_to - * @property Carbon $restored_at - * @property Backup $backup - */ class BackupFile extends AbstractModel { use HasFactory; @@ -39,7 +30,7 @@ protected static function booted(): void static::created(function (BackupFile $backupFile) { $keep = $backupFile->backup->keep_backups; if ($backupFile->backup->files()->count() > $keep) { - /* @var BackupFile $lastFileToKeep */ + /** @var BackupFile $lastFileToKeep */ $lastFileToKeep = $backupFile->backup->files()->orderByDesc('id')->skip($keep)->first(); if ($lastFileToKeep) { $files = $backupFile->backup->files() @@ -71,6 +62,9 @@ protected static function booted(): void BackupFileStatus::RESTORE_FAILED => 'danger', ]; + /** + * @return BelongsTo + */ public function backup(): BelongsTo { return $this->belongsTo(Backup::class); diff --git a/app/Models/CronJob.php b/app/Models/CronJob.php index c076a3dd..7a284834 100755 --- a/app/Models/CronJob.php +++ b/app/Models/CronJob.php @@ -6,16 +6,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $server_id - * @property string $command - * @property string $user - * @property string $frequency - * @property bool $hidden - * @property string $status - * @property string $crontab - * @property Server $server - */ class CronJob extends AbstractModel { use HasFactory; @@ -43,6 +33,9 @@ class CronJob extends AbstractModel CronjobStatus::DISABLED => 'gray', ]; + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); diff --git a/app/Models/Database.php b/app/Models/Database.php index 72ebac1b..cf50878a 100755 --- a/app/Models/Database.php +++ b/app/Models/Database.php @@ -9,14 +9,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; -/** - * @property int $server_id - * @property string $name - * @property string $status - * @property Server $server - * @property Backup[] $backups - * @property Carbon $deleted_at - */ class Database extends AbstractModel { use HasFactory; @@ -55,11 +47,17 @@ public static function boot(): void DatabaseStatus::FAILED => 'danger', ]; + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); } + /** + * @return HasMany + */ public function backups(): HasMany { return $this->hasMany(Backup::class)->where('type', 'database'); diff --git a/app/Models/DatabaseUser.php b/app/Models/DatabaseUser.php index 652e4f10..34a4c002 100755 --- a/app/Models/DatabaseUser.php +++ b/app/Models/DatabaseUser.php @@ -6,15 +6,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $server_id - * @property string $username - * @property string $password - * @property array $databases - * @property string $host - * @property string $status - * @property Server $server - */ class DatabaseUser extends AbstractModel { use HasFactory; @@ -38,6 +29,9 @@ class DatabaseUser extends AbstractModel 'password', ]; + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); diff --git a/app/Models/Deployment.php b/app/Models/Deployment.php index 41d6493c..6776396e 100755 --- a/app/Models/Deployment.php +++ b/app/Models/Deployment.php @@ -6,18 +6,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $site_id - * @property int $deployment_script_id - * @property int $log_id - * @property string $commit_id - * @property string $commit_id_short - * @property array $commit_data - * @property string $status - * @property Site $site - * @property DeploymentScript $deploymentScript - * @property ServerLog $log - */ class Deployment extends AbstractModel { use HasFactory; @@ -44,16 +32,25 @@ class Deployment extends AbstractModel DeploymentStatus::FAILED => 'danger', ]; + /** + * @return BelongsTo + */ public function site(): BelongsTo { return $this->belongsTo(Site::class); } + /** + * @return BelongsTo + */ public function deploymentScript(): BelongsTo { return $this->belongsTo(DeploymentScript::class); } + /** + * @return BelongsTo + */ public function log(): BelongsTo { return $this->belongsTo(ServerLog::class, 'log_id'); diff --git a/app/Models/DeploymentScript.php b/app/Models/DeploymentScript.php index 4dd0a026..feb125f6 100644 --- a/app/Models/DeploymentScript.php +++ b/app/Models/DeploymentScript.php @@ -5,12 +5,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $site_id - * @property string $name - * @property string $content - * @property Site $site - */ class DeploymentScript extends AbstractModel { use HasFactory; @@ -25,6 +19,9 @@ class DeploymentScript extends AbstractModel 'site_id' => 'integer', ]; + /** + * @return BelongsTo + */ public function site(): BelongsTo { return $this->belongsTo(Site::class); diff --git a/app/Models/FirewallRule.php b/app/Models/FirewallRule.php index aec1fe8f..0500809a 100755 --- a/app/Models/FirewallRule.php +++ b/app/Models/FirewallRule.php @@ -5,17 +5,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $server_id - * @property string $type - * @property string $protocol - * @property int $port - * @property string $source - * @property ?string $mask - * @property string $note - * @property string $status - * @property Server $server - */ class FirewallRule extends AbstractModel { use HasFactory; @@ -36,6 +25,9 @@ class FirewallRule extends AbstractModel 'port' => 'integer', ]; + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); diff --git a/app/Models/GitHook.php b/app/Models/GitHook.php index fd54f561..0165160c 100755 --- a/app/Models/GitHook.php +++ b/app/Models/GitHook.php @@ -6,17 +6,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $site_id - * @property int $source_control_id - * @property string $secret - * @property array $events - * @property array $actions - * @property string $hook_id - * @property array $hook_response - * @property Site $site - * @property SourceControl $sourceControl - */ class GitHook extends AbstractModel { use HasFactory; @@ -39,11 +28,17 @@ class GitHook extends AbstractModel 'hook_response' => 'json', ]; + /** + * @return BelongsTo + */ public function site(): BelongsTo { return $this->belongsTo(Site::class); } + /** + * @return BelongsTo + */ public function sourceControl(): BelongsTo { return $this->belongsTo(SourceControl::class); diff --git a/app/Models/Metric.php b/app/Models/Metric.php index 7802b053..febba572 100644 --- a/app/Models/Metric.php +++ b/app/Models/Metric.php @@ -7,26 +7,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $id - * @property int $server_id - * @property float $load - * @property float $memory_total - * @property float $memory_used - * @property float $memory_free - * @property float $disk_total - * @property float $disk_used - * @property float $disk_free - * @property-read float|int $memory_total_in_bytes - * @property-read float|int $memory_used_in_bytes - * @property-read float|int $memory_free_in_bytes - * @property-read float|int $disk_total_in_bytes - * @property-read float|int $disk_used_in_bytes - * @property-read float|int $disk_free_in_bytes - * @property Server $server - * @property Carbon $created_at - * @property Carbon $updated_at - */ class Metric extends Model { use HasFactory; @@ -53,6 +33,9 @@ class Metric extends Model 'disk_free' => 'float', ]; + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); diff --git a/app/Models/NotificationChannel.php b/app/Models/NotificationChannel.php index 73054023..4ade0dad 100644 --- a/app/Models/NotificationChannel.php +++ b/app/Models/NotificationChannel.php @@ -8,14 +8,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Notifications\Notifiable; -/** - * @property int $id - * @property string provider - * @property array data - * @property string label - * @property bool connected - * @property int $project_id - */ class NotificationChannel extends AbstractModel { use HasFactory; @@ -52,6 +44,9 @@ public static function notifyAll(NotificationInterface $notification): void } } + /** + * @return BelongsTo + */ public function project(): BelongsTo { return $this->belongsTo(Project::class); diff --git a/app/Models/PersonalAccessToken.php b/app/Models/PersonalAccessToken.php index b6981ad3..a3bdd642 100644 --- a/app/Models/PersonalAccessToken.php +++ b/app/Models/PersonalAccessToken.php @@ -6,17 +6,6 @@ use Carbon\Carbon; use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken; -/** - * @property int $id - * @property string $tokenable_type - * @property int $tokenable_id - * @property string $name - * @property string $token - * @property array $abilities - * @property Carbon $last_used_at - * @property Carbon $created_at - * @property Carbon $updated_at - */ class PersonalAccessToken extends SanctumPersonalAccessToken { use HasTimezoneTimestamps; diff --git a/app/Models/Project.php b/app/Models/Project.php index 0c477081..effaeac5 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -11,18 +11,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; -/** - * @property int $id - * @property int $user_id - * @property string $name - * @property Carbon $created_at - * @property Carbon $updated_at - * @property User $user - * @property Collection $servers - * @property Collection $users - * @property Collection $notificationChannels - * @property Collection $sourceControls - */ class Project extends Model { use HasFactory; @@ -44,31 +32,49 @@ public static function boot(): void }); } + /** + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); } + /** + * @return HasMany + */ public function servers(): HasMany { return $this->hasMany(Server::class); } + /** + * @return HasMany + */ public function notificationChannels(): HasMany { return $this->hasMany(NotificationChannel::class); } + /** + * @return BelongsToMany + */ public function users(): BelongsToMany { return $this->belongsToMany(User::class, 'user_project')->withTimestamps(); } + /** + * @return HasMany + */ public function sourceControls(): HasMany { return $this->hasMany(SourceControl::class); } + /** + * @return HasMany + */ public function tags(): HasMany { return $this->hasMany(Tag::class); diff --git a/app/Models/Queue.php b/app/Models/Queue.php index 5779fab3..7c708937 100644 --- a/app/Models/Queue.php +++ b/app/Models/Queue.php @@ -6,20 +6,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $server_id - * @property int $site_id - * @property string $command - * @property string $user - * @property bool $auto_start - * @property bool $auto_restart - * @property int $numprocs - * @property int $redirect_stderr - * @property string $stdout_logfile - * @property string $status - * @property Server $server - * @property Site $site - */ class Queue extends AbstractModel { use HasFactory; @@ -77,11 +63,17 @@ public function getServerIdAttribute(int $value): int return $value; } + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); } + /** + * @return BelongsTo + */ public function site(): BelongsTo { return $this->belongsTo(Site::class); diff --git a/app/Models/Script.php b/app/Models/Script.php index e5306378..1527e2df 100644 --- a/app/Models/Script.php +++ b/app/Models/Script.php @@ -10,19 +10,6 @@ use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Support\Collection; -/** - * @property int $id - * @property int $user_id - * @property string $name - * @property string $content - * @property Carbon $created_at - * @property Carbon $updated_at - * @property Collection $executions - * @property ?ScriptExecution $lastExecution - * @property User $user - * @property int $project_id - * @property ?Project $project - */ class Script extends AbstractModel { use HasFactory; @@ -48,11 +35,17 @@ public static function boot(): void }); } + /** + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); } + /** + * @return BelongsTo + */ public function project(): BelongsTo { return $this->belongsTo(Project::class); @@ -69,11 +62,17 @@ public function getVariables(): array return array_unique($variables); } + /** + * @return HasMany + */ public function executions(): HasMany { return $this->hasMany(ScriptExecution::class); } + /** + * @return HasOne + */ public function lastExecution(): HasOne { return $this->hasOne(ScriptExecution::class)->latest(); diff --git a/app/Models/ScriptExecution.php b/app/Models/ScriptExecution.php index 6b8c1e9a..a321521c 100644 --- a/app/Models/ScriptExecution.php +++ b/app/Models/ScriptExecution.php @@ -7,20 +7,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; -/** - * @property int $id - * @property int $script_id - * @property int $server_log_id - * @property ?int $server_id - * @property string $user - * @property array $variables - * @property string $status - * @property Carbon $created_at - * @property Carbon $updated_at - * @property Script $script - * @property ?ServerLog $serverLog - * @property ?Server $server - */ class ScriptExecution extends AbstractModel { use HasFactory; @@ -47,6 +33,9 @@ class ScriptExecution extends AbstractModel ScriptExecutionStatus::FAILED => 'danger', ]; + /** + * @return BelongsTo + */ public function script(): BelongsTo { return $this->belongsTo(Script::class); @@ -64,11 +53,17 @@ public function getContent(): string return $content; } + /** + * @return BelongsTo + */ public function serverLog(): BelongsTo { return $this->belongsTo(ServerLog::class); } + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); diff --git a/app/Models/Server.php b/app/Models/Server.php index 622a75c0..f4c5060e 100755 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -9,6 +9,10 @@ use App\ServerTypes\ServerType; use App\SSH\Cron\Cron; use App\SSH\OS\OS; +use App\SSH\Services\Database\Database as DatabaseService; +use App\SSH\Services\Firewall\Firewall as FirewallService; +use App\SSH\Services\PHP\PHP as PHPService; +use App\SSH\Services\ProcessManager\ProcessManager as ProcessManagerService; use App\SSH\Systemd\Systemd; use App\Support\Testing\SSHFake; use Carbon\Carbon; @@ -23,47 +27,6 @@ use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; -/** - * @property int $project_id - * @property int $user_id - * @property string $name - * @property string $ssh_user - * @property string $ip - * @property string $local_ip - * @property int $port - * @property string $os - * @property string $type - * @property array $type_data - * @property string $provider - * @property int $provider_id - * @property array $provider_data - * @property array $authentication - * @property string $public_key - * @property string $status - * @property bool $auto_update - * @property int $available_updates - * @property int $security_updates - * @property int $progress - * @property string $progress_step - * @property Project $project - * @property User $creator - * @property ServerProvider $serverProvider - * @property ServerLog[] $logs - * @property Site[] $sites - * @property Service[] $services - * @property Database[] $databases - * @property DatabaseUser[] $databaseUsers - * @property FirewallRule[] $firewallRules - * @property CronJob[] $cronJobs - * @property Queue[] $queues - * @property Backup[] $backups - * @property Queue[] $daemons - * @property SshKey[] $sshKeys - * @property Tag[] $tags - * @property string $hostname - * @property int $updates - * @property Carbon $last_update_check - */ class Server extends AbstractModel { use HasFactory; @@ -172,76 +135,121 @@ public function isInstallationFailed(): bool return $this->status === ServerStatus::INSTALLATION_FAILED; } + /** + * @return BelongsTo + */ public function project(): BelongsTo { return $this->belongsTo(Project::class, 'project_id'); } + /** + * @return BelongsTo + */ public function creator(): BelongsTo { return $this->belongsTo(User::class, 'user_id'); } + /** + * @return BelongsTo + */ public function serverProvider(): BelongsTo { return $this->belongsTo(ServerProvider::class, 'provider_id'); } + /** + * @return HasMany + */ public function logs(): HasMany { return $this->hasMany(ServerLog::class); } + /** + * @return HasMany + */ public function sites(): HasMany { return $this->hasMany(Site::class); } + /** + * @return HasMany + */ public function services(): HasMany { return $this->hasMany(Service::class); } + /** + * @return HasMany + */ public function databases(): HasMany { return $this->hasMany(Database::class); } + /** + * @return HasMany + */ public function databaseUsers(): HasMany { return $this->hasMany(DatabaseUser::class); } + /** + * @return HasMany + */ public function firewallRules(): HasMany { return $this->hasMany(FirewallRule::class); } + /** + * @return HasMany + */ public function cronJobs(): HasMany { return $this->hasMany(CronJob::class); } + /** + * @return HasMany + */ public function queues(): HasMany { return $this->hasMany(Queue::class); } + /** + * @return HasMany + */ public function backups(): HasMany { return $this->hasMany(Backup::class); } + /** + * @return HasMany + */ public function daemons(): HasMany { return $this->queues()->whereNull('site_id'); } + /** + * @return HasMany + */ public function metrics(): HasMany { return $this->hasMany(Metric::class); } + /** + * @return BelongsToMany + */ public function sshKeys(): BelongsToMany { return $this->belongsToMany(SshKey::class, 'server_ssh_keys') @@ -249,6 +257,9 @@ public function sshKeys(): BelongsToMany ->withTimestamps(); } + /** + * @return MorphToMany + */ public function tags(): MorphToMany { return $this->morphToMany(Tag::class, 'taggable'); @@ -265,7 +276,7 @@ public function getSshUser(): string public function service($type, $version = null): ?Service { - /* @var Service $service */ + /** @var Service $service */ $service = $this->services() ->where(function ($query) use ($type, $version) { $query->where('type', $type); @@ -280,7 +291,7 @@ public function service($type, $version = null): ?Service public function defaultService($type): ?Service { - /* @var Service $service */ + /** @var ?Service $service */ $service = $this->services() ->where('type', $type) ->where('is_default', 1) @@ -288,7 +299,7 @@ public function defaultService($type): ?Service // If no default service found, get the first service with status ready or stopped if (! $service) { - /** @var Service $service */ + /** @ var ?Service $service */ $service = $this->services() ->where('type', $type) ->whereIn('status', [ServiceStatus::READY, ServiceStatus::STOPPED]) @@ -352,6 +363,9 @@ public function webserver(?string $version = null): ?Service return $this->service('webserver', $version); } + /** + * @return Service + */ public function database(?string $version = null): ?Service { if (! $version) { @@ -361,6 +375,9 @@ public function database(?string $version = null): ?Service return $this->service('database', $version); } + /** + * @return Service + */ public function firewall(?string $version = null): ?Service { if (! $version) { @@ -370,6 +387,9 @@ public function firewall(?string $version = null): ?Service return $this->service('firewall', $version); } + /** + * @return Service + */ public function processManager(?string $version = null): ?Service { if (! $version) { diff --git a/app/Models/ServerLog.php b/app/Models/ServerLog.php index e308ee48..873a58b3 100755 --- a/app/Models/ServerLog.php +++ b/app/Models/ServerLog.php @@ -12,17 +12,7 @@ use Symfony\Component\HttpFoundation\StreamedResponse; use Throwable; -/** - * @property int $server_id - * @property ?int $site_id - * @property string $type - * @property string $name - * @property string $disk - * @property Server $server - * @property ?Site $site - * @property bool $is_remote - */ -class ServerLog extends AbstractModel +final class ServerLog extends AbstractModel { use HasFactory; @@ -63,11 +53,17 @@ public function getRouteKey(): string return 'log'; } + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); } + /** + * @return BelongsTo + */ public function site(): BelongsTo { return $this->belongsTo(Site::class); @@ -140,7 +136,7 @@ public function getContent($lines = null): ?string return "Log file doesn't exist!"; } - public static function log(Server $server, string $type, string $content, ?Site $site = null): static + public static function log(Server $server, string $type, string $content, ?Site $site = null): ServerLog { $log = new static([ 'server_id' => $server->id, diff --git a/app/Models/ServerProvider.php b/app/Models/ServerProvider.php index 585448df..88313198 100644 --- a/app/Models/ServerProvider.php +++ b/app/Models/ServerProvider.php @@ -8,17 +8,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Facades\Cache; -/** - * @property int $user_id - * @property string $profile - * @property string $provider - * @property array $credentials - * @property bool $connected - * @property User $user - * @property ?int $project_id - * @property Server[] $servers - * @property Project $project - */ class ServerProvider extends AbstractModel { use HasFactory; @@ -39,6 +28,9 @@ class ServerProvider extends AbstractModel 'project_id' => 'integer', ]; + /** + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); @@ -49,6 +41,9 @@ public function getCredentials(): array return $this->credentials; } + /** + * @return HasMany + */ public function servers(): HasMany { return $this->hasMany(Server::class, 'provider_id'); @@ -61,6 +56,9 @@ public function provider(): \App\ServerProviders\ServerProvider return new $providerClass($this); } + /** + * @return BelongsTo + */ public function project(): BelongsTo { return $this->belongsTo(Project::class); diff --git a/app/Models/Service.php b/app/Models/Service.php index a705f49d..2e6b5fe9 100755 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -9,22 +9,13 @@ use App\SSH\Services\PHP\PHP as PHPAlias; use App\SSH\Services\ProcessManager\ProcessManager; use App\SSH\Services\ServiceInterface; -use App\SSH\Services\WebServer\WebServer as WebServerAlias; +use App\SSH\Services\Webserver\Webserver as WebServerAlias; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Str; /** - * @property int $server_id - * @property string $type - * @property array $type_data - * @property string $name - * @property string $version - * @property string $unit - * @property string $logs - * @property string $status - * @property bool $is_default - * @property Server $server + * @template TService of ServiceInterface = ServiceInterface */ class Service extends AbstractModel { @@ -74,6 +65,9 @@ public static function boot(): void ServiceStatus::DISABLED => 'gray', ]; + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); @@ -81,6 +75,7 @@ public function server(): BelongsTo /** * @return ProcessManager|DatabaseAlias|PHPAlias|WebServerAlias + * @phpstan-return TService */ public function handler(): ServiceInterface { diff --git a/app/Models/Site.php b/app/Models/Site.php index 0852df85..89ebbd08 100755 --- a/app/Models/Site.php +++ b/app/Models/Site.php @@ -17,33 +17,6 @@ use Illuminate\Support\Str; /** - * @property int $server_id - * @property string $type - * @property array $type_data - * @property string $domain - * @property array $aliases - * @property string $web_directory - * @property string $path - * @property string $php_version - * @property string $source_control - * @property int $source_control_id - * @property string $repository - * @property string $ssh_key - * @property string $branch - * @property string $status - * @property int $port - * @property int $progress - * @property Server $server - * @property ServerLog[] $logs - * @property Deployment[] $deployments - * @property ?GitHook $gitHook - * @property DeploymentScript $deploymentScript - * @property Queue[] $queues - * @property Ssl[] $ssls - * @property ?Ssl $activeSsl - * @property string $ssh_key_name - * @property ?SourceControl $sourceControl - * * @TODO: Add nodejs_version column */ class Site extends AbstractModel @@ -120,46 +93,73 @@ public function isInstallationFailed(): bool return $this->status === SiteStatus::INSTALLATION_FAILED; } + /** + * @return BelongsTo + */ public function server(): BelongsTo { return $this->belongsTo(Server::class); } + /** + * @return HasMany + */ public function logs(): HasMany { return $this->hasMany(ServerLog::class); } + /** + * @return HasMany + */ public function deployments(): HasMany { return $this->hasMany(Deployment::class); } + /** + * @return HasOne + */ public function gitHook(): HasOne { return $this->hasOne(GitHook::class); } + /** + * @return HasOne + */ public function deploymentScript(): HasOne { return $this->hasOne(DeploymentScript::class); } + /** + * @return HasMany + */ public function queues(): HasMany { return $this->hasMany(Queue::class); } + /** + * @return HasMany + */ public function ssls(): HasMany { return $this->hasMany(Ssl::class); } + /** + * @return MorphToMany + */ public function tags(): MorphToMany { return $this->morphToMany(Tag::class, 'taggable'); } + /** + * @return BelongsTo + */ public function sourceControl(): BelongsTo { return $this->belongsTo(SourceControl::class)->withTrashed(); @@ -204,6 +204,9 @@ public function changePHPVersion($version): void $this->save(); } + /** + * @return HasOne + */ public function activeSsl(): HasOne { return $this->hasOne(Ssl::class) diff --git a/app/Models/SourceControl.php b/app/Models/SourceControl.php index c064457e..5bdbf694 100755 --- a/app/Models/SourceControl.php +++ b/app/Models/SourceControl.php @@ -9,14 +9,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; -/** - * @property string $provider - * @property array $provider_data - * @property ?string $profile - * @property ?string $url - * @property string $access_token - * @property ?int $project_id - */ class SourceControl extends AbstractModel { use HasFactory; @@ -49,11 +41,17 @@ public function getRepo(?string $repo = null): ?array return $this->provider()->getRepo($repo); } + /** + * @return HasMany + */ public function sites(): HasMany { return $this->hasMany(Site::class); } + /** + * @return BelongsTo + */ public function project(): BelongsTo { return $this->belongsTo(Project::class); diff --git a/app/Models/SshKey.php b/app/Models/SshKey.php index cf420844..d9086236 100644 --- a/app/Models/SshKey.php +++ b/app/Models/SshKey.php @@ -7,13 +7,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\SoftDeletes; -/** - * @property int $user_id - * @property string $name - * @property string $public_key - * @property User $user - * @property Server[] $servers - */ class SshKey extends AbstractModel { use HasFactory; @@ -30,11 +23,17 @@ class SshKey extends AbstractModel 'public_key' => 'encrypted', ]; + /** + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); } + /** + * @return BelongsToMany + */ public function servers(): BelongsToMany { return $this->belongsToMany(Server::class, 'server_ssh_keys') diff --git a/app/Models/Ssl.php b/app/Models/Ssl.php index cb160170..fbbe0a7f 100644 --- a/app/Models/Ssl.php +++ b/app/Models/Ssl.php @@ -8,20 +8,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Str; -/** - * @property int $site_id - * @property string $type - * @property string $certificate - * @property string $pk - * @property string $ca - * @property Carbon $expires_at - * @property string $status - * @property Site $site - * @property string $ca_path - * @property ?array $domains - * @property int $log_id - * @property ?ServerLog $log - */ class Ssl extends AbstractModel { use HasFactory; @@ -55,6 +41,9 @@ class Ssl extends AbstractModel SslStatus::FAILED => 'danger', ]; + /** + * @return BelongsTo + */ public function site(): BelongsTo { return $this->belongsTo(Site::class); @@ -139,6 +128,9 @@ public function getDomains(): array return $this->domains; } + /** + * @return BelongsTo + */ public function log(): BelongsTo { return $this->belongsTo(ServerLog::class); diff --git a/app/Models/StorageProvider.php b/app/Models/StorageProvider.php index 0ad869ad..d9a9c3bc 100644 --- a/app/Models/StorageProvider.php +++ b/app/Models/StorageProvider.php @@ -7,14 +7,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; -/** - * @property int $user_id - * @property string $profile - * @property string $provider - * @property array $credentials - * @property User $user - * @property int $project_id - */ class StorageProvider extends AbstractModel { use HasFactory; @@ -33,6 +25,9 @@ class StorageProvider extends AbstractModel 'project_id' => 'integer', ]; + /** + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); @@ -45,11 +40,17 @@ public function provider(): \App\StorageProviders\StorageProvider return new $providerClass($this); } + /** + * @return HasMany + */ public function backups(): HasMany { return $this->hasMany(Backup::class, 'storage_id'); } + /** + * @return BelongsTo + */ public function project(): BelongsTo { return $this->belongsTo(Project::class); diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 2a0ce619..7a909c44 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -8,14 +8,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphToMany; -/** - * @property int $id - * @property int $project_id - * @property string $name - * @property string $color - * @property Carbon $created_at - * @property Carbon $updated_at - */ class Tag extends AbstractModel { use HasFactory; @@ -30,16 +22,25 @@ class Tag extends AbstractModel 'project_id' => 'int', ]; + /** + * @return BelongsTo + */ public function project(): BelongsTo { return $this->belongsTo(Project::class); } + /** + * @return MorphToMany + */ public function servers(): MorphToMany { return $this->morphedByMany(Server::class, 'taggable'); } + /** + * @return MorphToMany + */ public function sites(): MorphToMany { return $this->morphedByMany(Site::class, 'taggable'); diff --git a/app/Models/User.php b/app/Models/User.php index 796ad89a..0009044b 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -18,30 +18,6 @@ use Laravel\Fortify\TwoFactorAuthenticatable; use Laravel\Sanctum\HasApiTokens; -/** - * @property int $id - * @property string $name - * @property string $email - * @property string $password - * @property string $profile_photo_path - * @property string $two_factor_recovery_codes - * @property string $two_factor_secret - * @property SshKey[] $sshKeys - * @property SourceControl[] $sourceControls - * @property ServerProvider[] $serverProviders - * @property Script[] $scripts - * @property StorageProvider[] $storageProviders - * @property StorageProvider[] $connectedStorageProviders - * @property Collection $tokens - * @property string $profile_photo_url - * @property string $timezone - * @property int $current_project_id - * @property Project $currentProject - * @property Collection $projects - * @property string $role - * @property Carbon $created_at - * @property Carbon $updated_at - */ class User extends Authenticatable implements FilamentUser { use HasApiTokens; @@ -69,36 +45,57 @@ class User extends Authenticatable implements FilamentUser protected $appends = [ ]; + /** + * @return HasMany + */ public function servers(): HasMany { return $this->hasMany(Server::class); } + /** + * @return HasMany + */ public function sshKeys(): HasMany { return $this->hasMany(SshKey::class); } + /** + * @return HasMany + */ public function sourceControls(): HasMany { return $this->hasMany(SourceControl::class); } + /** + * @return HasMany + */ public function serverProviders(): HasMany { return $this->hasMany(ServerProvider::class); } + /** + * @return HasOne + */ public function sourceControl(string $provider): HasOne { return $this->hasOne(SourceControl::class)->where('provider', $provider); } + /** + * @return HasMany + */ public function storageProviders(): HasMany { return $this->hasMany(StorageProvider::class); } + /** + * @return HasOne + */ public function storageProvider(string $provider): HasOne { return $this->hasOne(StorageProvider::class)->where('provider', $provider); @@ -113,15 +110,21 @@ public function allProjects(): Builder|BelongsToMany return $this->projects(); } + /** + * @return BelongsToMany + */ public function projects(): BelongsToMany { return $this->belongsToMany(Project::class, 'user_project') ->withTimestamps(); } + /** + * @return HasOne + */ public function currentProject(): HasOne { - return $this->HasOne(Project::class, 'id', 'current_project_id'); + return $this->hasOne(Project::class, 'id', 'current_project_id'); } public function createDefaultProject(): Project @@ -147,6 +150,9 @@ public function isAdmin(): bool return $this->role === UserRole::ADMIN; } + /** + * @return HasMany + */ public function scripts(): HasMany { return $this->hasMany(Script::class); diff --git a/app/SSH/Services/Database/Database.php b/app/SSH/Services/Database/Database.php index a5ab82c1..db453488 100755 --- a/app/SSH/Services/Database/Database.php +++ b/app/SSH/Services/Database/Database.php @@ -3,8 +3,9 @@ namespace App\SSH\Services\Database; use App\Models\BackupFile; +use App\SSH\Services\ServiceInterface; -interface Database +interface Database extends ServiceInterface { public function create(string $name): void; diff --git a/app/SSH/Services/Firewall/Firewall.php b/app/SSH/Services/Firewall/Firewall.php index e71cdfef..0bf64262 100755 --- a/app/SSH/Services/Firewall/Firewall.php +++ b/app/SSH/Services/Firewall/Firewall.php @@ -2,7 +2,9 @@ namespace App\SSH\Services\Firewall; -interface Firewall +use App\SSH\Services\ServiceInterface; + +interface Firewall extends ServiceInterface { public function addRule(string $type, string $protocol, int $port, string $source, ?string $mask): void; diff --git a/app/SSH/Services/ProcessManager/ProcessManager.php b/app/SSH/Services/ProcessManager/ProcessManager.php index 70bf32cf..587b742a 100755 --- a/app/SSH/Services/ProcessManager/ProcessManager.php +++ b/app/SSH/Services/ProcessManager/ProcessManager.php @@ -2,7 +2,9 @@ namespace App\SSH\Services\ProcessManager; -interface ProcessManager +use App\SSH\Services\ServiceInterface; + +interface ProcessManager extends ServiceInterface { public function create( int $id, diff --git a/app/SSH/Services/Webserver/Webserver.php b/app/SSH/Services/Webserver/Webserver.php index 4137d325..9bbc7031 100755 --- a/app/SSH/Services/Webserver/Webserver.php +++ b/app/SSH/Services/Webserver/Webserver.php @@ -4,8 +4,9 @@ use App\Models\Site; use App\Models\Ssl; +use App\SSH\Services\ServiceInterface; -interface Webserver +interface Webserver extends ServiceInterface { public function createVHost(Site $site): void; diff --git a/app/SiteTypes/Wordpress.php b/app/SiteTypes/Wordpress.php index 83365ee2..ff74beea 100755 --- a/app/SiteTypes/Wordpress.php +++ b/app/SiteTypes/Wordpress.php @@ -8,7 +8,9 @@ use App\Enums\SiteFeature; use App\Models\Database; use App\Models\DatabaseUser; +use App\SSH\Services\Webserver\Webserver; use Closure; +use Illuminate\Database\Query\Builder; use Illuminate\Validation\Rule; class Wordpress extends AbstractSiteType @@ -41,7 +43,7 @@ public function createRules(array $input): array ], 'database' => [ 'required', - Rule::unique('databases', 'name')->where(function ($query) { + Rule::unique('databases', 'name')->where(function (Builder $query) { return $query->where('server_id', $this->site->server_id); }), function (string $attribute, mixed $value, Closure $fail) { @@ -52,7 +54,7 @@ function (string $attribute, mixed $value, Closure $fail) { ], 'database_user' => [ 'required', - Rule::unique('database_users', 'username')->where(function ($query) { + Rule::unique('database_users', 'username')->where(function (Builder $query) { return $query->where('server_id', $this->site->server_id); }), ], diff --git a/app/Traits/HasProjectThroughServer.php b/app/Traits/HasProjectThroughServer.php index 904368db..2f3487df 100644 --- a/app/Traits/HasProjectThroughServer.php +++ b/app/Traits/HasProjectThroughServer.php @@ -8,6 +8,9 @@ trait HasProjectThroughServer { + /** + * @return HasOneThrough + */ public function project(): HasOneThrough { return $this->hasOneThrough( diff --git a/app/Web/Pages/Login.php b/app/Web/Pages/Login.php index cb05dfaf..ea5de21a 100644 --- a/app/Web/Pages/Login.php +++ b/app/Web/Pages/Login.php @@ -141,7 +141,7 @@ private function initTwoFactor(): void PanelsRenderHook::AUTH_LOGIN_FORM_BEFORE, fn (): string => Blade::render( <<{$this->logoutAction()->render()} + {$this->logoutAction()->render()->render()} BLADE ), ); diff --git a/app/Web/Pages/Servers/SSHKeys/Index.php b/app/Web/Pages/Servers/SSHKeys/Index.php index 1477bded..2419fc4b 100644 --- a/app/Web/Pages/Servers/SSHKeys/Index.php +++ b/app/Web/Pages/Servers/SSHKeys/Index.php @@ -11,6 +11,7 @@ use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; +use Filament\Forms\Get; use Filament\Notifications\Notification; use Filament\Support\Enums\MaxWidth; @@ -51,15 +52,15 @@ protected function getHeaderActions(): array Select::make('key_id') ->label('Key') ->options(auth()->user()->sshKeys()->pluck('name', 'id')->toArray()) - ->visible(fn ($get) => $get('type') === 'existing') + ->visible(fn (Get $get) => $get('type') === 'existing') ->rules(DeployKeyToServer::rules(auth()->user(), $this->server)['key_id']), TextInput::make('name') ->label('Name') - ->visible(fn ($get) => $get('type') === 'new') + ->visible(fn (Get $get) => $get('type') === 'new') ->rules(CreateSshKey::rules()['name']), Textarea::make('public_key') ->label('Public Key') - ->visible(fn ($get) => $get('type') === 'new') + ->visible(fn (Get $get) => $get('type') === 'new') ->rules(CreateSshKey::rules()['public_key']), ]) ->modalSubmitActionLabel('Deploy') diff --git a/app/Web/Pages/Servers/Services/Index.php b/app/Web/Pages/Servers/Services/Index.php index 4a6d9b75..0ca03039 100644 --- a/app/Web/Pages/Servers/Services/Index.php +++ b/app/Web/Pages/Servers/Services/Index.php @@ -8,6 +8,7 @@ use Exception; use Filament\Actions\Action; use Filament\Forms\Components\Select; +use Filament\Forms\Get; use Filament\Notifications\Notification; use Filament\Support\Enums\MaxWidth; @@ -50,9 +51,9 @@ protected function getHeaderActions(): array ->searchable() ->options($availableServices) ->reactive() - ->rules(fn ($get) => Install::rules($get())['name']), + ->rules(fn (Get $get) => Install::rules($get())['name']), Select::make('version') - ->options(function (callable $get) { + ->options(function (Get $get) { if (! $get('name')) { return []; } @@ -60,7 +61,7 @@ protected function getHeaderActions(): array return collect(config("core.service_versions.{$get('name')}")) ->mapWithKeys(fn ($version) => [$version => $version]); }) - ->rules(fn ($get) => Install::rules($get())['version']) + ->rules(fn (Get $get) => Install::rules($get())['version']) ->reactive(), ]) ->action(function (array $data) { diff --git a/app/Web/Pages/Servers/Sites/Widgets/SitesList.php b/app/Web/Pages/Servers/Sites/Widgets/SitesList.php index 7b694615..ca8d0792 100644 --- a/app/Web/Pages/Servers/Sites/Widgets/SitesList.php +++ b/app/Web/Pages/Servers/Sites/Widgets/SitesList.php @@ -36,7 +36,7 @@ protected function getTableColumns(): array ->label('Tags') ->badge() ->icon('heroicon-o-tag') - ->formatStateUsing(fn ($state) => $state->name) + ->formatStateUsing(fn ($state) => $state->name) // ? What is $state ? Site doesn't have color, Tag does, but how is it a Tag? ->color(fn ($state) => $state->color) ->searchable() ->sortable(), diff --git a/app/Web/Pages/Servers/Widgets/ServerDetails.php b/app/Web/Pages/Servers/Widgets/ServerDetails.php index 45b292f3..a0df105e 100644 --- a/app/Web/Pages/Servers/Widgets/ServerDetails.php +++ b/app/Web/Pages/Servers/Widgets/ServerDetails.php @@ -45,7 +45,7 @@ public function infolist(Infolist $infolist): Infolist ->hintIconTooltip('Server unique identifier to use in the API'), TextEntry::make('created_at') ->label('Created At') - ->formatStateUsing(fn ($record) => $record->created_at_by_timezone) + ->formatStateUsing(fn (Server $record) => $record->created_at_by_timezone) ->inlineLabel(), TextEntry::make('last_updated_check') ->label('Last Updated Check') diff --git a/app/Web/Pages/Servers/Widgets/ServersList.php b/app/Web/Pages/Servers/Widgets/ServersList.php index 36fb85a5..425bdff6 100644 --- a/app/Web/Pages/Servers/Widgets/ServersList.php +++ b/app/Web/Pages/Servers/Widgets/ServersList.php @@ -3,6 +3,7 @@ namespace App\Web\Pages\Servers\Widgets; use App\Models\Server; +use App\Models\Tag; use App\Web\Pages\Servers\Settings; use App\Web\Pages\Servers\View; use Filament\Tables\Actions\Action; @@ -33,7 +34,7 @@ protected function getTableColumns(): array ->label('Tags') ->badge() ->icon('heroicon-o-tag') - ->formatStateUsing(fn ($state) => $state->name) + ->formatStateUsing(fn ($state) => $state->name) // ? What is $state ? Server doesn't have color, Tag does, but how is it a Tag? ->color(fn ($state) => $state->color) ->searchable() ->sortable(), @@ -45,7 +46,7 @@ protected function getTableColumns(): array ->sortable(), TextColumn::make('created_at') ->label('Created At') - ->formatStateUsing(fn ($record) => $record->created_at_by_timezone) + ->formatStateUsing(fn (Server $record) => $record->created_at_by_timezone) ->searchable() ->sortable(), ]; diff --git a/app/Web/Pages/Settings/Profile/Widgets/BrowserSession.php b/app/Web/Pages/Settings/Profile/Widgets/BrowserSession.php index 88bb3859..6fb4bc06 100644 --- a/app/Web/Pages/Settings/Profile/Widgets/BrowserSession.php +++ b/app/Web/Pages/Settings/Profile/Widgets/BrowserSession.php @@ -18,6 +18,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; +use stdClass; class BrowserSession extends Widget implements HasForms, HasInfolists { @@ -92,6 +93,9 @@ private function getDynamicSchema(): array return $sections; } + /** + * @return list + */ private function getSessions(): array { if (config(key: 'session.driver') !== 'database') { @@ -103,7 +107,7 @@ private function getSessions(): array ->where(column: 'user_id', operator: Auth::user()->getAuthIdentifier()) ->latest(column: 'last_activity') ->get() - )->map(callback: function ($session): object { + )->map(callback: function (stdClass $session): stdClass { $agent = $this->createAgent($session); return (object) [ @@ -121,7 +125,7 @@ private function getSessions(): array })->toArray(); } - private function createAgent(mixed $session) + private function createAgent(stdClass $session): Agent { return tap( value: new Agent, diff --git a/app/Web/Pages/Settings/Projects/Widgets/ProjectUsersList.php b/app/Web/Pages/Settings/Projects/Widgets/ProjectUsersList.php index 95fa8cdf..05887bad 100644 --- a/app/Web/Pages/Settings/Projects/Widgets/ProjectUsersList.php +++ b/app/Web/Pages/Settings/Projects/Widgets/ProjectUsersList.php @@ -46,7 +46,7 @@ public function table(Table $table): Table Tables\Actions\DeleteAction::make() ->label('Remove') ->modalHeading('Remove user from project') - ->visible(function ($record) { + ->visible(function (User $record) { return $this->authorize('update', $this->project)->allowed() && $record->id !== auth()->id(); }) ->using(function ($record) { diff --git a/app/Web/Pages/Settings/Projects/Widgets/ProjectsList.php b/app/Web/Pages/Settings/Projects/Widgets/ProjectsList.php index 9f0cf185..6f5568fe 100644 --- a/app/Web/Pages/Settings/Projects/Widgets/ProjectsList.php +++ b/app/Web/Pages/Settings/Projects/Widgets/ProjectsList.php @@ -27,7 +27,7 @@ protected function getTableColumns(): array ->sortable(), TextColumn::make('created_at') ->label('Created At') - ->formatStateUsing(fn ($record) => $record->created_at_by_timezone) + ->formatStateUsing(fn (Project $record) => $record->created_at_by_timezone) ->searchable() ->sortable(), ]; diff --git a/app/Web/Pages/Settings/ServerProviders/Actions/Create.php b/app/Web/Pages/Settings/ServerProviders/Actions/Create.php index dd634b77..985a98a6 100644 --- a/app/Web/Pages/Settings/ServerProviders/Actions/Create.php +++ b/app/Web/Pages/Settings/ServerProviders/Actions/Create.php @@ -30,15 +30,15 @@ public static function form(): array TextInput::make('token') ->label('API Key') ->validationAttribute('API Key') - ->visible(fn ($get) => isset(CreateServerProvider::rules($get())['token'])) + ->visible(fn (Get $get) => isset(CreateServerProvider::rules($get())['token'])) ->rules(fn (Get $get) => CreateServerProvider::rules($get())['token']), TextInput::make('key') ->label('Access Key') - ->visible(fn ($get) => isset(CreateServerProvider::rules($get())['key'])) + ->visible(fn (Get $get) => isset(CreateServerProvider::rules($get())['key'])) ->rules(fn (Get $get) => CreateServerProvider::rules($get())['key']), TextInput::make('secret') ->label('Secret') - ->visible(fn ($get) => isset(CreateServerProvider::rules($get())['secret'])) + ->visible(fn (Get $get) => isset(CreateServerProvider::rules($get())['secret'])) ->rules(fn (Get $get) => CreateServerProvider::rules($get())['secret']), Checkbox::make('global') ->label('Is Global (Accessible in all projects)'), diff --git a/app/Web/Pages/Settings/ServerProviders/Widgets/ServerProvidersList.php b/app/Web/Pages/Settings/ServerProviders/Widgets/ServerProvidersList.php index d41a88f0..218385de 100644 --- a/app/Web/Pages/Settings/ServerProviders/Widgets/ServerProvidersList.php +++ b/app/Web/Pages/Settings/ServerProviders/Widgets/ServerProvidersList.php @@ -32,20 +32,20 @@ protected function getTableColumns(): array ->icon(fn (ServerProvider $record) => 'icon-'.$record->provider) ->width(24), TextColumn::make('name') - ->default(fn ($record) => $record->profile) + ->default(fn (ServerProvider $record) => $record->profile) ->label('Name') ->searchable() ->sortable(), TextColumn::make('id') ->label('Global') ->badge() - ->color(fn ($record) => $record->project_id ? 'gray' : 'success') + ->color(fn (ServerProvider $record) => $record->project_id ? 'gray' : 'success') ->formatStateUsing(function (ServerProvider $record) { return $record->project_id ? 'No' : 'Yes'; }), TextColumn::make('created_at') ->label('Created At') - ->formatStateUsing(fn ($record) => $record->created_at_by_timezone) + ->formatStateUsing(fn (ServerProvider $record) => $record->created_at_by_timezone) ->searchable() ->sortable(), ]; diff --git a/app/Web/Pages/Settings/SourceControls/Actions/Create.php b/app/Web/Pages/Settings/SourceControls/Actions/Create.php index d4df8684..46929439 100644 --- a/app/Web/Pages/Settings/SourceControls/Actions/Create.php +++ b/app/Web/Pages/Settings/SourceControls/Actions/Create.php @@ -29,21 +29,21 @@ public static function form(): array TextInput::make('token') ->label('API Key') ->validationAttribute('API Key') - ->visible(fn ($get) => in_array($get('provider'), [ + ->visible(fn (Get $get) => in_array($get('provider'), [ SourceControl::GITHUB, SourceControl::GITLAB, ])) ->rules(fn (Get $get) => ConnectSourceControl::rules($get())['token']), TextInput::make('url') ->label('URL (optional)') - ->visible(fn ($get) => $get('provider') == SourceControl::GITLAB) + ->visible(fn (Get $get) => $get('provider') == SourceControl::GITLAB) ->rules(fn (Get $get) => ConnectSourceControl::rules($get())['url']) ->helperText('If you run a self-managed gitlab enter the url here, leave empty to use gitlab.com'), TextInput::make('username') - ->visible(fn ($get) => $get('provider') == SourceControl::BITBUCKET) + ->visible(fn (Get $get) => $get('provider') == SourceControl::BITBUCKET) ->rules(fn (Get $get) => ConnectSourceControl::rules($get())['username']), TextInput::make('password') - ->visible(fn ($get) => $get('provider') == SourceControl::BITBUCKET) + ->visible(fn (Get $get) => $get('provider') == SourceControl::BITBUCKET) ->rules(fn (Get $get) => ConnectSourceControl::rules($get())['password']), Checkbox::make('global') ->label('Is Global (Accessible in all projects)'), diff --git a/app/Web/Pages/Settings/StorageProviders/Actions/Create.php b/app/Web/Pages/Settings/StorageProviders/Actions/Create.php index bd00c0ab..f916ef29 100644 --- a/app/Web/Pages/Settings/StorageProviders/Actions/Create.php +++ b/app/Web/Pages/Settings/StorageProviders/Actions/Create.php @@ -10,6 +10,7 @@ use Filament\Forms\Components\Grid; use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; +use Filament\Forms\Get; use Filament\Notifications\Notification; class Create @@ -25,60 +26,60 @@ public static function form(): array ->live() ->reactive() ->native(false) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['provider']), + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['provider']), TextInput::make('name') - ->rules(fn ($get) => CreateStorageProvider::rules($get())['name']), + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['name']), TextInput::make('token') ->label('API Token') ->validationAttribute('API Token') - ->visible(fn ($get) => $get('provider') == StorageProvider::DROPBOX) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['token']), + ->visible(fn (Get $get) => $get('provider') == StorageProvider::DROPBOX) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['token']), Grid::make() - ->visible(fn ($get) => $get('provider') == StorageProvider::FTP) + ->visible(fn (Get $get) => $get('provider') == StorageProvider::FTP) ->schema([ TextInput::make('host') - ->visible(fn ($get) => $get('provider') == StorageProvider::FTP) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['host']), + ->visible(fn (Get $get) => $get('provider') == StorageProvider::FTP) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['host']), TextInput::make('port') - ->visible(fn ($get) => $get('provider') == StorageProvider::FTP) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['port']), + ->visible(fn (Get $get) => $get('provider') == StorageProvider::FTP) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['port']), TextInput::make('username') - ->visible(fn ($get) => $get('provider') == StorageProvider::FTP) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['username']), + ->visible(fn (Get $get) => $get('provider') == StorageProvider::FTP) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['username']), TextInput::make('password') - ->visible(fn ($get) => $get('provider') == StorageProvider::FTP) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['password']), + ->visible(fn (Get $get) => $get('provider') == StorageProvider::FTP) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['password']), Checkbox::make('ssl') - ->visible(fn ($get) => $get('provider') == StorageProvider::FTP) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['ssl']), + ->visible(fn (Get $get) => $get('provider') == StorageProvider::FTP) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['ssl']), Checkbox::make('passive') - ->visible(fn ($get) => $get('provider') == StorageProvider::FTP) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['passive']), + ->visible(fn (Get $get) => $get('provider') == StorageProvider::FTP) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['passive']), ]), TextInput::make('api_url') ->label('API URL') - ->visible(fn ($get) => $get('provider') == StorageProvider::S3) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['api_url']) + ->visible(fn (Get $get) => $get('provider') == StorageProvider::S3) + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['api_url']) ->helperText('Required if you are using an S3 compatible provider like Cloudflare R2'), TextInput::make('path') - ->visible(fn ($get) => in_array($get('provider'), [ + ->visible(fn (Get $get) => in_array($get('provider'), [ StorageProvider::S3, StorageProvider::FTP, StorageProvider::LOCAL, ])) - ->rules(fn ($get) => CreateStorageProvider::rules($get())['path']) - ->helperText(function ($get) { + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['path']) + ->helperText(function (Get $get) { return match ($get('provider')) { StorageProvider::LOCAL => 'The absolute path on your server that the database exists. like `/home/vito/db-backups`', default => '', }; }), Grid::make() - ->visible(fn ($get) => $get('provider') == StorageProvider::S3) + ->visible(fn (Get $get) => $get('provider') == StorageProvider::S3) ->schema([ TextInput::make('key') - ->rules(fn ($get) => CreateStorageProvider::rules($get())['key']) - ->helperText(function ($get) { + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['key']) + ->helperText(function (Get $get) { return match ($get('provider')) { StorageProvider::S3 => new Link( href: 'https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html', @@ -89,11 +90,11 @@ public static function form(): array }; }), TextInput::make('secret') - ->rules(fn ($get) => CreateStorageProvider::rules($get())['secret']), + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['secret']), TextInput::make('region') - ->rules(fn ($get) => CreateStorageProvider::rules($get())['region']), + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['region']), TextInput::make('bucket') - ->rules(fn ($get) => CreateStorageProvider::rules($get())['bucket']), + ->rules(fn (Get $get) => CreateStorageProvider::rules($get())['bucket']), ]), Checkbox::make('global') ->label('Is Global (Accessible in all projects)'), diff --git a/app/Web/Pages/Settings/StorageProviders/Widgets/StorageProvidersList.php b/app/Web/Pages/Settings/StorageProviders/Widgets/StorageProvidersList.php index 2635d0a1..1713ead2 100644 --- a/app/Web/Pages/Settings/StorageProviders/Widgets/StorageProvidersList.php +++ b/app/Web/Pages/Settings/StorageProviders/Widgets/StorageProvidersList.php @@ -39,13 +39,13 @@ protected function getTableColumns(): array TextColumn::make('id') ->label('Global') ->badge() - ->color(fn ($record) => $record->project_id ? 'gray' : 'success') + ->color(fn (StorageProvider $record) => $record->project_id ? 'gray' : 'success') ->formatStateUsing(function (StorageProvider $record) { return $record->project_id ? 'No' : 'Yes'; }), TextColumn::make('created_at') ->label('Created At') - ->formatStateUsing(fn ($record) => $record->created_at_by_timezone) + ->formatStateUsing(fn (StorageProvider $record) => $record->created_at_by_timezone) ->searchable() ->sortable(), ]; diff --git a/app/Web/Pages/Settings/Tags/Actions/EditTags.php b/app/Web/Pages/Settings/Tags/Actions/EditTags.php index 0357625f..858e626e 100644 --- a/app/Web/Pages/Settings/Tags/Actions/EditTags.php +++ b/app/Web/Pages/Settings/Tags/Actions/EditTags.php @@ -26,8 +26,8 @@ public static function infolist(mixed $taggable): InfolistAction ->modalSubmitActionLabel('Save') ->modalHeading('Edit Tags') ->modalWidth(MaxWidth::Medium) - ->form(static::form($taggable)) - ->action(static::action($taggable)); + ->form(self::form($taggable)) + ->action(self::action($taggable)); } /** @@ -42,8 +42,8 @@ public static function table(mixed $taggable): TableAction ->modalSubmitActionLabel('Save') ->modalHeading('Edit Tags') ->modalWidth(MaxWidth::Medium) - ->form(static::form($taggable)) - ->action(static::action($taggable)); + ->form(self::form($taggable)) + ->action(self::action($taggable)); } /** diff --git a/app/Web/Pages/Settings/Users/Widgets/UsersList.php b/app/Web/Pages/Settings/Users/Widgets/UsersList.php index a981a2bc..2cab3ced 100644 --- a/app/Web/Pages/Settings/Users/Widgets/UsersList.php +++ b/app/Web/Pages/Settings/Users/Widgets/UsersList.php @@ -41,7 +41,7 @@ protected function getTableColumns(): array TextColumn::make('timezone'), TextColumn::make('created_at') ->label('Created At') - ->formatStateUsing(fn ($record) => $record->created_at_by_timezone) + ->formatStateUsing(fn (User $record) => $record->created_at_by_timezone) ->searchable() ->sortable(), TextColumn::make('role'), @@ -56,8 +56,8 @@ public function table(Table $table): Table ->columns($this->getTableColumns()) ->actions([ EditAction::make('edit') - ->authorize(fn ($record) => auth()->user()->can('update', $record)) - ->using(function ($record, array $data) { + ->authorize(fn (User $record) => auth()->user()->can('update', $record)) + ->using(function (User $record, array $data) { app(UpdateUser::class)->update($record, $data); }) ->form(function (Form $form, $record) { @@ -87,8 +87,8 @@ public function table(Table $table): Table Action::make('update-projects') ->label('Projects') ->icon('heroicon-o-rectangle-stack') - ->authorize(fn ($record) => auth()->user()->can('update', $record)) - ->form(function (Form $form, $record) { + ->authorize(fn (User $record) => auth()->user()->can('update', $record)) + ->form(function (Form $form, User $record) { return $form ->schema([ CheckboxList::make('projects') diff --git a/composer.json b/composer.json index 8648b33b..cb7702af 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,7 @@ "fakerphp/faker": "^1.9.1", "knuckleswtf/scribe": "^4.37", "laradumps/laradumps": "^3.0", + "larastan/larastan": "^3.0", "laravel/pint": "^1.10", "laravel/sail": "^1.18", "mockery/mockery": "^1.4.4", diff --git a/composer.lock b/composer.lock index 236aaca2..4488cd61 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "be3e63b7efd71f649cbffb0d469ba7c1", + "content-hash": "32d13903a06cb568080e7a0d2f2fb9fb", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -8801,6 +8801,99 @@ ], "time": "2024-12-09T16:58:35+00:00" }, + { + "name": "larastan/larastan", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/larastan/larastan.git", + "reference": "b2e24e1605cff1d1097ccb6fb8af3bbd1dfe1c6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/larastan/larastan/zipball/b2e24e1605cff1d1097ccb6fb8af3bbd1dfe1c6f", + "reference": "b2e24e1605cff1d1097ccb6fb8af3bbd1dfe1c6f", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^11.15.0", + "illuminate/container": "^11.15.0", + "illuminate/contracts": "^11.15.0", + "illuminate/database": "^11.15.0", + "illuminate/http": "^11.15.0", + "illuminate/pipeline": "^11.15.0", + "illuminate/support": "^11.15.0", + "php": "^8.2", + "phpmyadmin/sql-parser": "^5.9.0", + "phpstan/phpstan": "^2.0.2" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0", + "laravel/framework": "^11.15.0", + "mockery/mockery": "^1.6", + "nikic/php-parser": "^5.3", + "orchestra/canvas": "^v9.1.3", + "orchestra/testbench-core": "^9.5.2", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpunit/phpunit": "^10.5.16" + }, + "suggest": { + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Larastan\\Larastan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Can Vural", + "email": "can9119@gmail.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan wrapper for Laravel", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "larastan", + "laravel", + "package", + "php", + "static analysis" + ], + "support": { + "issues": "https://github.com/larastan/larastan/issues", + "source": "https://github.com/larastan/larastan/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://github.com/canvural", + "type": "github" + } + ], + "time": "2024-11-26T23:15:21+00:00" + }, { "name": "laravel/pint", "version": "v1.18.3", @@ -9341,6 +9434,151 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpmyadmin/sql-parser", + "version": "5.10.2", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/sql-parser.git", + "reference": "72afbce7e4b421593b60d2eb7281e37a50734df8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/72afbce7e4b421593b60d2eb7281e37a50734df8", + "reference": "72afbce7e4b421593b60d2eb7281e37a50734df8", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "phpmyadmin/motranslator": "<3.0" + }, + "require-dev": { + "phpbench/phpbench": "^1.1", + "phpmyadmin/coding-standard": "^3.0", + "phpmyadmin/motranslator": "^4.0 || ^5.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.9.12", + "phpstan/phpstan-phpunit": "^1.3.3", + "phpunit/phpunit": "^8.5 || ^9.6", + "psalm/plugin-phpunit": "^0.16.1", + "vimeo/psalm": "^4.11", + "zumba/json-serializer": "~3.0.2" + }, + "suggest": { + "ext-mbstring": "For best performance", + "phpmyadmin/motranslator": "Translate messages to your favorite locale" + }, + "bin": [ + "bin/highlight-query", + "bin/lint-query", + "bin/sql-parser", + "bin/tokenize-query" + ], + "type": "library", + "autoload": { + "psr-4": { + "PhpMyAdmin\\SqlParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "A validating SQL lexer and parser with a focus on MySQL dialect.", + "homepage": "https://github.com/phpmyadmin/sql-parser", + "keywords": [ + "analysis", + "lexer", + "parser", + "query linter", + "sql", + "sql lexer", + "sql linter", + "sql parser", + "sql syntax highlighter", + "sql tokenizer" + ], + "support": { + "issues": "https://github.com/phpmyadmin/sql-parser/issues", + "source": "https://github.com/phpmyadmin/sql-parser" + }, + "funding": [ + { + "url": "https://www.phpmyadmin.net/donate/", + "type": "other" + } + ], + "time": "2024-12-05T15:04:09+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "50d276fc3bf1430ec315f2f109bbde2769821524" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/50d276fc3bf1430ec315f2f109bbde2769821524", + "reference": "50d276fc3bf1430ec315f2f109bbde2769821524", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2024-12-17T17:14:01+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "10.1.16", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..c217f809 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,11 @@ +includes: + - vendor/larastan/larastan/extension.neon +parameters: + level: 2 + paths: + - app/ + checkExplicitMixed: true + checkImplicitMixed: true + ignoreErrors: + - identifier: larastan.noModelMake + - identifier: encapsedStringPart.nonString diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..09974a17 --- /dev/null +++ b/rector.php @@ -0,0 +1,20 @@ +withPaths([ + __DIR__ . '/app', + ]) + ->withRules([ + AddGenericReturnTypeToRelationsRector::class, + ]) + // ->withTypeCoverageLevel(0) +;