diff --git a/phpstan.neon b/phpstan.neon index 082a22fe..27341217 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -14,8 +14,11 @@ parameters: - Illuminate\Database\Eloquent\Model ignoreErrors: + - + identifier: missingType.iterableValue - '#Cannot access offset (.*?) on Illuminate\\Contracts\\Foundation\\Application#' - '#Cannot access offset (.*?) on Illuminate\\Contracts\\Config\\Repository#' + - '#Call to an undefined method(.*?)Tenant\:\:run\(\).#' - message: '#Call to an undefined (method|static method) Illuminate\\Database\\Eloquent\\(Model|Builder)#' paths: @@ -23,7 +26,10 @@ parameters: - src/Commands/ClearPendingTenants.php - src/Database/Concerns/PendingScope.php - src/Database/ParentModelScope.php - - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder\:\:withPending\(\)#' + - + message: '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder\:\:withPending\(\)#' + paths: + - src/Concerns/HasTenantOptions.php - message: '#invalid type Laravel\\Telescope\\IncomingEntry#' paths: @@ -53,6 +59,4 @@ parameters: paths: - src/RLS/PolicyManagers/TraitRLSManager.php - checkMissingIterableValueType: false - checkGenericClassInNonGenericObjectType: false # later we may want to enable this treatPhpDocTypesAsCertain: false diff --git a/src/Actions/CloneRoutesAsTenant.php b/src/Actions/CloneRoutesAsTenant.php index c2c22508..70c277eb 100644 --- a/src/Actions/CloneRoutesAsTenant.php +++ b/src/Actions/CloneRoutesAsTenant.php @@ -73,6 +73,9 @@ class CloneRoutesAsTenant return $this; } + /** + * @return Collection + */ protected function getRoutesToClone(): Collection { $tenantParameterName = PathTenantResolver::tenantParameterName(); diff --git a/src/Actions/CreateStorageSymlinksAction.php b/src/Actions/CreateStorageSymlinksAction.php index 41327a63..2de9e915 100644 --- a/src/Actions/CreateStorageSymlinksAction.php +++ b/src/Actions/CreateStorageSymlinksAction.php @@ -16,6 +16,9 @@ class CreateStorageSymlinksAction { use DealsWithTenantSymlinks; + /** + * @param Tenant|Collection|LazyCollection $tenants + */ public function __invoke(Tenant|Collection|LazyCollection $tenants, bool $relativeLink = false, bool $force = false): void { $tenants = $tenants instanceof Tenant ? collect([$tenants]) : $tenants; diff --git a/src/Actions/RemoveStorageSymlinksAction.php b/src/Actions/RemoveStorageSymlinksAction.php index 1108b892..7b7b04d5 100644 --- a/src/Actions/RemoveStorageSymlinksAction.php +++ b/src/Actions/RemoveStorageSymlinksAction.php @@ -15,6 +15,9 @@ class RemoveStorageSymlinksAction { use DealsWithTenantSymlinks; + /** + * @param Tenant|Collection|LazyCollection $tenants + */ public function __invoke(Tenant|Collection|LazyCollection $tenants): void { $tenants = $tenants instanceof Tenant ? collect([$tenants]) : $tenants; diff --git a/src/Commands/Link.php b/src/Commands/Link.php index 7d712290..ea1506e6 100644 --- a/src/Commands/Link.php +++ b/src/Commands/Link.php @@ -42,6 +42,9 @@ class Link extends Command return 0; } + /** + * @param LazyCollection $tenants + */ protected function removeLinks(LazyCollection $tenants): void { (new RemoveStorageSymlinksAction)($tenants); @@ -49,6 +52,9 @@ class Link extends Command $this->components->info('The links have been removed.'); } + /** + * @param LazyCollection $tenants + */ protected function createLinks(LazyCollection $tenants): void { (new CreateStorageSymlinksAction)( diff --git a/src/Commands/Migrate.php b/src/Commands/Migrate.php index 9f09910e..c3ba37e4 100644 --- a/src/Commands/Migrate.php +++ b/src/Commands/Migrate.php @@ -52,20 +52,23 @@ class Migrate extends MigrateCommand if ($this->getProcesses() > 1) { return $this->runConcurrently($this->getTenantChunks()->map(function ($chunk) { - return $this->getTenants(array_values($chunk->all())); + return $this->getTenants($chunk->all()); })); } return $this->migrateTenants($this->getTenants()) ? 0 : 1; } - protected function childHandle(...$args): bool + protected function childHandle(mixed ...$args): bool { $chunk = $args[0]; return $this->migrateTenants($chunk); } + /** + * @param LazyCollection $tenants + */ protected function migrateTenants(LazyCollection $tenants): bool { $success = true; diff --git a/src/Commands/MigrateFresh.php b/src/Commands/MigrateFresh.php index 00a40540..02e4c189 100644 --- a/src/Commands/MigrateFresh.php +++ b/src/Commands/MigrateFresh.php @@ -38,14 +38,18 @@ class MigrateFresh extends BaseCommand if ($this->getProcesses() > 1) { return $this->runConcurrently($this->getTenantChunks()->map(function ($chunk) { - return $this->getTenants(array_values($chunk->all())); + return $this->getTenants($chunk->all()); })); } tenancy()->runForMultiple($this->getTenants(), function ($tenant) use (&$success) { $this->components->info("Tenant: {$tenant->getTenantKey()}"); - $this->components->task('Dropping tables', fn () => $success = $success && $this->wipeDB()); - $this->components->task('Migrating', fn () => $success = $success && $this->migrateTenant($tenant)); + $this->components->task('Dropping tables', function () use (&$success) { + $success = $success && $this->wipeDB(); + }); + $this->components->task('Migrating', function () use ($tenant, &$success) { + $success = $success && $this->migrateTenant($tenant); + }); }); return $success ? 0 : 1; @@ -69,13 +73,16 @@ class MigrateFresh extends BaseCommand ]) === 0; } - protected function childHandle(...$args): bool + protected function childHandle(mixed ...$args): bool { $chunk = $args[0]; return $this->migrateFreshTenants($chunk); } + /** + * @param LazyCollection $tenants + */ protected function migrateFreshTenants(LazyCollection $tenants): bool { $success = true; diff --git a/src/Commands/Rollback.php b/src/Commands/Rollback.php index d32db47c..7ea01f08 100644 --- a/src/Commands/Rollback.php +++ b/src/Commands/Rollback.php @@ -42,7 +42,7 @@ class Rollback extends RollbackCommand if ($this->getProcesses() > 1) { return $this->runConcurrently($this->getTenantChunks()->map(function ($chunk) { - return $this->getTenants(array_values($chunk->all())); + return $this->getTenants($chunk->all()); })); } @@ -54,13 +54,16 @@ class Rollback extends RollbackCommand return 'tenants:rollback'; } - protected function childHandle(...$args): bool + protected function childHandle(mixed ...$args): bool { $chunk = $args[0]; return $this->rollbackTenants($chunk); } + /** + * @param LazyCollection $tenants + */ protected function rollbackTenants(LazyCollection $tenants): bool { $success = true; diff --git a/src/Commands/TenantList.php b/src/Commands/TenantList.php index ef39fe7d..37505901 100644 --- a/src/Commands/TenantList.php +++ b/src/Commands/TenantList.php @@ -41,6 +41,9 @@ class TenantList extends Command } /** Generate the visual CLI output for the domain names. */ + /** + * @param Collection|null $domains + */ protected function domainsCLI(?Collection $domains): ?string { if (! $domains) { diff --git a/src/Concerns/HasTenantOptions.php b/src/Concerns/HasTenantOptions.php index 09309766..8cd105ba 100644 --- a/src/Concerns/HasTenantOptions.php +++ b/src/Concerns/HasTenantOptions.php @@ -22,11 +22,17 @@ trait HasTenantOptions ], parent::getOptions()); } + /** + * @return LazyCollection + */ protected function getTenants(?array $tenantKeys = null): LazyCollection { return $this->getTenantsQuery($tenantKeys)->cursor(); } + /** + * @return Builder<\Stancl\Tenancy\Contracts\Tenant&\Illuminate\Database\Eloquent\Model> + */ protected function getTenantsQuery(?array $tenantKeys = null): Builder { return tenancy()->query() diff --git a/src/Concerns/ParallelCommand.php b/src/Concerns/ParallelCommand.php index 27981cf3..55383788 100644 --- a/src/Concerns/ParallelCommand.php +++ b/src/Concerns/ParallelCommand.php @@ -13,14 +13,14 @@ trait ParallelCommand { public const MAX_PROCESSES = 24; - abstract protected function childHandle(...$args): bool; + abstract protected function childHandle(mixed ...$args): bool; public function addProcessesOption(): void { $this->addOption('processes', 'p', InputOption::VALUE_OPTIONAL, 'How many processes to spawn. Maximum value: ' . static::MAX_PROCESSES . ', recommended value: core count', 1); } - protected function forkProcess(...$args): int + protected function forkProcess(mixed ...$args): int { $pid = pcntl_fork(); @@ -53,14 +53,25 @@ trait ParallelCommand return $processes; } + /** + * @return Collection>> + */ protected function getTenantChunks(): Collection { $idCol = tenancy()->model()->getTenantKeyName(); $tenants = tenancy()->model()->orderBy($idCol, 'asc')->pluck($idCol); - return $tenants->chunk(ceil($tenants->count() / $this->getProcesses())); + return $tenants->chunk((int) ceil($tenants->count() / $this->getProcesses()))->map(function ($chunk) { + $chunk = array_values($chunk->all()); + + /** @var Collection $chunk */ + return $chunk; + }); } + /** + * @param array|ArrayAccess|null $args + */ protected function runConcurrently(array|ArrayAccess|null $args = null): int { $processes = $this->getProcesses(); diff --git a/src/Contracts/Domain.php b/src/Contracts/Domain.php index 60747fb7..aa91b2da 100644 --- a/src/Contracts/Domain.php +++ b/src/Contracts/Domain.php @@ -5,15 +5,19 @@ declare(strict_types=1); namespace Stancl\Tenancy\Contracts; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use \Illuminate\Database\Eloquent\Model; /** * @property-read Tenant $tenant * * @see \Stancl\Tenancy\Database\Models\Domain * - * @mixin \Illuminate\Database\Eloquent\Model + * @mixin Model */ interface Domain { + /** + * @return BelongsTo + */ public function tenant(): BelongsTo; } diff --git a/src/Database/Concerns/PendingScope.php b/src/Database/Concerns/PendingScope.php index d9bbd17f..b5b6b9cb 100644 --- a/src/Database/Concerns/PendingScope.php +++ b/src/Database/Concerns/PendingScope.php @@ -20,6 +20,8 @@ class PendingScope implements Scope /** * Apply the scope to a given Eloquent query builder. * + * @param Builder<\Stancl\Tenancy\Contracts\Tenant&Model> $builder + * * @return void */ public function apply(Builder $builder, Model $model) @@ -32,6 +34,8 @@ class PendingScope implements Scope /** * Extend the query builder with the needed functions. * + * @param Builder<\Stancl\Tenancy\Contracts\Tenant&Model> $builder + * * @return void */ public function extend(Builder $builder) @@ -43,6 +47,8 @@ class PendingScope implements Scope /** * Add the with-pending extension to the builder. * + * @param Builder<\Stancl\Tenancy\Contracts\Tenant&Model> $builder + * * @return void */ protected function addWithPending(Builder $builder) @@ -59,6 +65,8 @@ class PendingScope implements Scope /** * Add the without-pending extension to the builder. * + * @param Builder<\Stancl\Tenancy\Contracts\Tenant&Model> $builder + * * @return void */ protected function addWithoutPending(Builder $builder) @@ -75,6 +83,8 @@ class PendingScope implements Scope /** * Add the only-pending extension to the builder. * + * @param Builder<\Stancl\Tenancy\Contracts\Tenant&Model> $builder + * * @return void */ protected function addOnlyPending(Builder $builder) diff --git a/src/Database/ParentModelScope.php b/src/Database/ParentModelScope.php index c91a23e1..ee1a200e 100644 --- a/src/Database/ParentModelScope.php +++ b/src/Database/ParentModelScope.php @@ -10,6 +10,9 @@ use Illuminate\Database\Eloquent\Scope; class ParentModelScope implements Scope { + /** + * @param Builder $builder + */ public function apply(Builder $builder, Model $model): void { if (! tenancy()->initialized) { @@ -19,6 +22,9 @@ class ParentModelScope implements Scope $builder->whereHas($builder->getModel()->getRelationshipToPrimaryModel()); } + /** + * @param Builder $builder + */ public function extend(Builder $builder): void { $builder->macro('withoutParentModel', function (Builder $builder) { diff --git a/src/Database/TenantCollection.php b/src/Database/TenantCollection.php index 45a137fe..229200d6 100644 --- a/src/Database/TenantCollection.php +++ b/src/Database/TenantCollection.php @@ -14,6 +14,8 @@ use Stancl\Tenancy\Contracts\Tenant; * @method Tenant[] toArray() * @method Tenant offsetGet($key) * @method Tenant first() + * + * @extends Collection */ class TenantCollection extends Collection { diff --git a/src/Database/TenantScope.php b/src/Database/TenantScope.php index c3cd6015..050da365 100644 --- a/src/Database/TenantScope.php +++ b/src/Database/TenantScope.php @@ -11,6 +11,9 @@ use Stancl\Tenancy\Tenancy; class TenantScope implements Scope { + /** + * @param Builder $builder + */ public function apply(Builder $builder, Model $model) { if (! tenancy()->initialized) { @@ -20,6 +23,9 @@ class TenantScope implements Scope $builder->where($model->qualifyColumn(Tenancy::tenantKeyColumn()), tenant()->getTenantKey()); } + /** + * @param Builder $builder + */ public function extend(Builder $builder): void { $builder->macro('withoutTenancy', function (Builder $builder) { diff --git a/src/Middleware/InitializeTenancyByRequestData.php b/src/Middleware/InitializeTenancyByRequestData.php index 78f5db0d..fb61fac7 100644 --- a/src/Middleware/InitializeTenancyByRequestData.php +++ b/src/Middleware/InitializeTenancyByRequestData.php @@ -64,7 +64,7 @@ class InitializeTenancyByRequestData extends IdentificationMiddleware } elseif (static::$cookie && $request->hasCookie(static::$cookie)) { $payload = $request->cookie(static::$cookie); - if ($payload) { + if ($payload && is_string($payload)) { $payload = $this->getTenantFromCookie($payload); } } else { diff --git a/src/RLS/PolicyManagers/TraitRLSManager.php b/src/RLS/PolicyManagers/TraitRLSManager.php index e83181dd..42b6d5af 100644 --- a/src/RLS/PolicyManagers/TraitRLSManager.php +++ b/src/RLS/PolicyManagers/TraitRLSManager.php @@ -72,6 +72,9 @@ class TraitRLSManager implements RLSPolicyManager SQL; } + /** + * @param BelongsTo $parentRelationship + */ protected function generateIndirectRLSPolicyQuery(Model $model, BelongsTo $parentRelationship): string { $table = $model->getTable(); diff --git a/src/ResourceSyncing/SyncMaster.php b/src/ResourceSyncing/SyncMaster.php index f4f6f07a..0e35f1ae 100644 --- a/src/ResourceSyncing/SyncMaster.php +++ b/src/ResourceSyncing/SyncMaster.php @@ -16,6 +16,9 @@ use Stancl\Tenancy\Contracts\Tenant; */ interface SyncMaster extends Syncable { + /** + * @return BelongsToMany + */ public function tenants(): BelongsToMany; public function getTenantModelName(): string; diff --git a/src/Tenancy.php b/src/Tenancy.php index c1c62916..cf6ee060 100644 --- a/src/Tenancy.php +++ b/src/Tenancy.php @@ -128,6 +128,9 @@ class Tenancy return in_array($bootstrapper, static::getBootstrappers(), true); } + /** + * @return Builder + */ public static function query(): Builder { return static::model()->query();