From 8af354c20e9678abb8ef7a25d8363c11dfc45807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Tue, 30 Aug 2022 05:44:23 +0200 Subject: [PATCH] get phpstan errors down from 252 to 189 --- CONTRIBUTING.md | 16 ++++++++++++++++ composer.json | 1 + phpstan.neon | 9 ++++++++- src/Contracts/Syncable.php | 4 ++-- src/Contracts/TenantResolver.php | 2 +- src/Controllers/TenantAssetsController.php | 2 +- .../Concerns/BelongsToPrimaryModel.php | 2 +- src/Database/Concerns/BelongsToTenant.php | 2 +- .../Concerns/ConvertsDomainsToLowercase.php | 2 +- .../Concerns/EnsuresDomainIsNotOccupied.php | 2 +- src/Database/Concerns/GeneratesIds.php | 2 +- .../Concerns/InvalidatesResolverCache.php | 2 +- .../InvalidatesTenantsResolverCache.php | 2 +- src/Database/Concerns/ResourceSyncing.php | 4 ++-- src/Database/DatabaseManager.php | 10 +++++----- .../Exceptions/NoConnectionSetException.php | 2 +- src/Database/Models/Domain.php | 3 ++- src/Database/Models/ImpersonationToken.php | 14 +++++++------- src/Database/Models/TenantPivot.php | 2 +- src/Events/SyncedResourceSaved.php | 9 ++++----- src/Features/TenantConfig.php | 13 ++++++------- src/Features/UserImpersonation.php | 1 + src/Jobs/CreateDatabase.php | 10 +++------- src/Jobs/DeleteDatabase.php | 13 +++++-------- src/Jobs/DeleteDomains.php | 10 ++++++---- src/Jobs/MigrateDatabase.php | 18 +++++------------- src/Jobs/SeedDatabase.php | 18 +++++------------- src/Listeners/BootstrapTenancy.php | 2 +- src/Listeners/CreateTenantConnection.php | 2 +- src/Listeners/QueueableListener.php | 4 ++-- src/Listeners/RevertToCentralContext.php | 2 +- src/Listeners/UpdateSyncedResource.php | 11 ++++++----- .../Contracts/CachedTenantResolver.php | 6 +++--- src/Resolvers/DomainTenantResolver.php | 2 +- src/Resolvers/PathTenantResolver.php | 2 +- src/Resolvers/RequestDataTenantResolver.php | 2 +- src/Tenancy.php | 3 ++- src/helpers.php | 17 ++++++++--------- tests/EventListenerTest.php | 2 +- tests/ResourceSyncingTest.php | 4 ++-- 40 files changed, 119 insertions(+), 115 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 12e5e55b..d76a686a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,24 @@ php-cs-fixer will fix code style violations in your pull requests. Run `composer docker-up` to start the containers. Then run `composer test` to run the tests. +If you need to pass additional flags to phpunit, use `./test --foo` instead of `composer test --foo`. Composer scripts unfortunately don't pass CLI arguments. + When you're done testing, run `composer docker-down` to shut down the containers. ### Docker on M1 Run `composer docker-m1` to symlink `docker-compose-m1.override.yml` to `docker-compose.override.yml`. This will reconfigure a few services in the docker compose config to be compatible with M1. + +### Coverage reports + +To run tests and generate coverage reports, use `composer test-full`. + +To view the coverage reports in your browser, use `composer coverage` (works on macOS; on other operating systems you can manually open `coverage/phpunit/html/index.html` in your browser). + +### Rebuilding containers + +If you need to rebuild the container for any reason (e.g. a change in `Dockerfile`), you can use `composer docker-rebuild`. + +## PHPStan + +Use `composer phpstan` to run our phpstan suite. diff --git a/composer.json b/composer.json index 16822ac3..ff5befd9 100644 --- a/composer.json +++ b/composer.json @@ -62,6 +62,7 @@ "docker-rebuild": "PHP_VERSION=8.1 docker-compose up -d --no-deps --build", "docker-m1": "ln -s docker-compose-m1.override.yml docker-compose.override.yml", "coverage": "open coverage/phpunit/html/index.html", + "phpstan": "vendor/bin/phpstan", "test": "PHP_VERSION=8.1 ./test --no-coverage", "test-full": "PHP_VERSION=8.1 ./test" }, diff --git a/phpstan.neon b/phpstan.neon index c84dfecb..9ff082dd 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -12,7 +12,14 @@ parameters: - Illuminate\Routing\Route ignoreErrors: + - + message: '#Cannot access offset (.*?) on Illuminate\\Contracts\\Foundation\\Application#' + paths: + - src/TenancyServiceProvider.php + - + message: '#invalid type Laravel\\Telescope\\IncomingEntry#' + paths: + - src/Features/TelescopeTags.php checkMissingIterableValueType: false treatPhpDocTypesAsCertain: false - diff --git a/src/Contracts/Syncable.php b/src/Contracts/Syncable.php index 1f6e36e7..e09f4f7e 100644 --- a/src/Contracts/Syncable.php +++ b/src/Contracts/Syncable.php @@ -8,11 +8,11 @@ interface Syncable { public function getGlobalIdentifierKeyName(): string; - public function getGlobalIdentifierKey(); + public function getGlobalIdentifierKey(): string|int; public function getCentralModelName(): string; public function getSyncedAttributeNames(): array; - public function triggerSyncEvent(); + public function triggerSyncEvent(): void; } diff --git a/src/Contracts/TenantResolver.php b/src/Contracts/TenantResolver.php index bba72f34..b4b45f4b 100644 --- a/src/Contracts/TenantResolver.php +++ b/src/Contracts/TenantResolver.php @@ -11,5 +11,5 @@ interface TenantResolver * * @throws TenantCouldNotBeIdentifiedException */ - public function resolve(...$args): Tenant; + public function resolve(mixed ...$args): Tenant; } diff --git a/src/Controllers/TenantAssetsController.php b/src/Controllers/TenantAssetsController.php index 893f5662..03d600d0 100644 --- a/src/Controllers/TenantAssetsController.php +++ b/src/Controllers/TenantAssetsController.php @@ -17,7 +17,7 @@ class TenantAssetsController extends Controller $this->middleware(static::$tenancyMiddleware); } - public function asset($path = null) + public function asset(string $path = null) { abort_if($path === null, 404); diff --git a/src/Database/Concerns/BelongsToPrimaryModel.php b/src/Database/Concerns/BelongsToPrimaryModel.php index 72101d6a..a50f9d9e 100644 --- a/src/Database/Concerns/BelongsToPrimaryModel.php +++ b/src/Database/Concerns/BelongsToPrimaryModel.php @@ -10,7 +10,7 @@ trait BelongsToPrimaryModel { abstract public function getRelationshipToPrimaryModel(): string; - public static function bootBelongsToPrimaryModel() + public static function bootBelongsToPrimaryModel(): void { static::addGlobalScope(new ParentModelScope); } diff --git a/src/Database/Concerns/BelongsToTenant.php b/src/Database/Concerns/BelongsToTenant.php index 5410758d..ade966a8 100644 --- a/src/Database/Concerns/BelongsToTenant.php +++ b/src/Database/Concerns/BelongsToTenant.php @@ -19,7 +19,7 @@ trait BelongsToTenant return $this->belongsTo(config('tenancy.tenant_model'), BelongsToTenant::$tenantIdColumn); } - public static function bootBelongsToTenant() + public static function bootBelongsToTenant(): void { static::addGlobalScope(new TenantScope); diff --git a/src/Database/Concerns/ConvertsDomainsToLowercase.php b/src/Database/Concerns/ConvertsDomainsToLowercase.php index e3f0c6ac..8068902d 100644 --- a/src/Database/Concerns/ConvertsDomainsToLowercase.php +++ b/src/Database/Concerns/ConvertsDomainsToLowercase.php @@ -6,7 +6,7 @@ namespace Stancl\Tenancy\Database\Concerns; trait ConvertsDomainsToLowercase { - public static function bootConvertsDomainsToLowercase() + public static function bootConvertsDomainsToLowercase(): void { static::saving(function ($model) { $model->domain = strtolower($model->domain); diff --git a/src/Database/Concerns/EnsuresDomainIsNotOccupied.php b/src/Database/Concerns/EnsuresDomainIsNotOccupied.php index 2b1c56ee..a853c437 100644 --- a/src/Database/Concerns/EnsuresDomainIsNotOccupied.php +++ b/src/Database/Concerns/EnsuresDomainIsNotOccupied.php @@ -8,7 +8,7 @@ use Stancl\Tenancy\Exceptions\DomainOccupiedByOtherTenantException; trait EnsuresDomainIsNotOccupied { - public static function bootEnsuresDomainIsNotOccupied() + public static function bootEnsuresDomainIsNotOccupied(): void { static::saving(function ($self) { if ($domain = $self->newQuery()->where('domain', $self->domain)->first()) { diff --git a/src/Database/Concerns/GeneratesIds.php b/src/Database/Concerns/GeneratesIds.php index d2796ba4..301ea385 100644 --- a/src/Database/Concerns/GeneratesIds.php +++ b/src/Database/Concerns/GeneratesIds.php @@ -8,7 +8,7 @@ use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator; trait GeneratesIds { - public static function bootGeneratesIds() + public static function bootGeneratesIds(): void { static::creating(function (self $model) { if (! $model->getKey() && $model->shouldGenerateId()) { diff --git a/src/Database/Concerns/InvalidatesResolverCache.php b/src/Database/Concerns/InvalidatesResolverCache.php index 7dff35ad..3b864789 100644 --- a/src/Database/Concerns/InvalidatesResolverCache.php +++ b/src/Database/Concerns/InvalidatesResolverCache.php @@ -16,7 +16,7 @@ trait InvalidatesResolverCache Resolvers\RequestDataTenantResolver::class, ]; - public static function bootInvalidatesResolverCache() + public static function bootInvalidatesResolverCache(): void { static::saved(function (Tenant $tenant) { foreach (static::$resolvers as $resolver) { diff --git a/src/Database/Concerns/InvalidatesTenantsResolverCache.php b/src/Database/Concerns/InvalidatesTenantsResolverCache.php index 555aceeb..8d7c2845 100644 --- a/src/Database/Concerns/InvalidatesTenantsResolverCache.php +++ b/src/Database/Concerns/InvalidatesTenantsResolverCache.php @@ -19,7 +19,7 @@ trait InvalidatesTenantsResolverCache Resolvers\RequestDataTenantResolver::class, ]; - public static function bootInvalidatesTenantsResolverCache() + public static function bootInvalidatesTenantsResolverCache(): void { static::saved(function (Model $model) { foreach (static::$resolvers as $resolver) { diff --git a/src/Database/Concerns/ResourceSyncing.php b/src/Database/Concerns/ResourceSyncing.php index f1026f7a..df5b0766 100644 --- a/src/Database/Concerns/ResourceSyncing.php +++ b/src/Database/Concerns/ResourceSyncing.php @@ -10,7 +10,7 @@ use Stancl\Tenancy\Events\SyncedResourceSaved; trait ResourceSyncing { - public static function bootResourceSyncing() + public static function bootResourceSyncing(): void { static::saved(function (Syncable $model) { /** @var ResourceSyncing $model */ @@ -27,7 +27,7 @@ trait ResourceSyncing }); } - public function triggerSyncEvent() + public function triggerSyncEvent(): void { /** @var Syncable $this */ event(new SyncedResourceSaved($this, tenant())); diff --git a/src/Database/DatabaseManager.php b/src/Database/DatabaseManager.php index 00afe938..a92ccb7b 100644 --- a/src/Database/DatabaseManager.php +++ b/src/Database/DatabaseManager.php @@ -34,7 +34,7 @@ class DatabaseManager /** * Connect to a tenant's database. */ - public function connectToTenant(TenantWithDatabase $tenant) + public function connectToTenant(TenantWithDatabase $tenant): void { $this->purgeTenantConnection(); $this->createTenantConnection($tenant); @@ -44,7 +44,7 @@ class DatabaseManager /** * Reconnect to the default non-tenant connection. */ - public function reconnectToCentral() + public function reconnectToCentral(): void { $this->purgeTenantConnection(); $this->setDefaultConnection($this->config->get('tenancy.database.central_connection')); @@ -53,7 +53,7 @@ class DatabaseManager /** * Change the default database connection config. */ - public function setDefaultConnection(string $connection) + public function setDefaultConnection(string $connection): void { $this->config['database.default'] = $connection; $this->database->setDefaultConnection($connection); @@ -62,7 +62,7 @@ class DatabaseManager /** * Create the tenant database connection. */ - public function createTenantConnection(TenantWithDatabase $tenant) + public function createTenantConnection(TenantWithDatabase $tenant): void { $this->config['database.connections.tenant'] = $tenant->database()->connection(); } @@ -70,7 +70,7 @@ class DatabaseManager /** * Purge the tenant database connection. */ - public function purgeTenantConnection() + public function purgeTenantConnection(): void { if (array_key_exists('tenant', $this->database->getConnections())) { $this->database->purge('tenant'); diff --git a/src/Database/Exceptions/NoConnectionSetException.php b/src/Database/Exceptions/NoConnectionSetException.php index 1db73d04..75c5c77d 100644 --- a/src/Database/Exceptions/NoConnectionSetException.php +++ b/src/Database/Exceptions/NoConnectionSetException.php @@ -8,7 +8,7 @@ use Exception; class NoConnectionSetException extends Exception { - public function __construct($manager) + public function __construct(string $manager) { parent::__construct("No connection was set on this $manager instance."); } diff --git a/src/Database/Models/Domain.php b/src/Database/Models/Domain.php index 261918c4..16695711 100644 --- a/src/Database/Models/Domain.php +++ b/src/Database/Models/Domain.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Stancl\Tenancy\Database\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Stancl\Tenancy\Contracts; use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Database\Concerns; @@ -25,7 +26,7 @@ class Domain extends Model implements Contracts\Domain protected $guarded = []; - public function tenant() + public function tenant(): BelongsTo { return $this->belongsTo(config('tenancy.tenant_model')); } diff --git a/src/Database/Models/ImpersonationToken.php b/src/Database/Models/ImpersonationToken.php index d73b436b..8161aca7 100644 --- a/src/Database/Models/ImpersonationToken.php +++ b/src/Database/Models/ImpersonationToken.php @@ -10,12 +10,12 @@ use Illuminate\Support\Str; use Stancl\Tenancy\Database\Concerns\CentralConnection; /** - * @param string $token - * @param string $tenant_id - * @param string $user_id - * @param string $auth_guard - * @param string $redirect_url - * @param Carbon $created_at + * @property string $token + * @property string $tenant_id + * @property string $user_id + * @property string $auth_guard + * @property string $redirect_url + * @property Carbon $created_at */ class ImpersonationToken extends Model { @@ -35,7 +35,7 @@ class ImpersonationToken extends Model 'created_at', ]; - public static function booted() + public static function booted(): void { static::creating(function ($model) { $model->created_at = $model->created_at ?? $model->freshTimestamp(); diff --git a/src/Database/Models/TenantPivot.php b/src/Database/Models/TenantPivot.php index 5c0d6a37..2c7583c1 100644 --- a/src/Database/Models/TenantPivot.php +++ b/src/Database/Models/TenantPivot.php @@ -9,7 +9,7 @@ use Stancl\Tenancy\Contracts\Syncable; class TenantPivot extends Pivot { - public static function booted() + public static function booted(): void { static::saved(function (self $pivot) { $parent = $pivot->pivotParent; diff --git a/src/Events/SyncedResourceSaved.php b/src/Events/SyncedResourceSaved.php index 23e56e21..72d34d16 100644 --- a/src/Events/SyncedResourceSaved.php +++ b/src/Events/SyncedResourceSaved.php @@ -10,13 +10,12 @@ use Stancl\Tenancy\Database\Contracts\TenantWithDatabase; class SyncedResourceSaved { - /** @var Syncable|Model */ - public $model; + public Syncable&Model $model; - /** @var TenantWithDatabase|Model|null */ - public $tenant; + /** @var (TenantWithDatabase&Model)|null */ + public TenantWithDatabase|null $tenant; - public function __construct(Syncable $model, ?TenantWithDatabase $tenant) + public function __construct(Syncable $model, TenantWithDatabase|null $tenant) { $this->model = $model; $this->tenant = $tenant; diff --git a/src/Features/TenantConfig.php b/src/Features/TenantConfig.php index 95691f0d..50756b2c 100644 --- a/src/Features/TenantConfig.php +++ b/src/Features/TenantConfig.php @@ -19,8 +19,7 @@ class TenantConfig implements Feature /** @var Repository */ protected $config; - /** @var array */ - public $originalConfig = []; + public array $originalConfig = []; public static $storageToConfigMap = [ // 'paypal_api_key' => 'services.paypal.api_key', @@ -51,14 +50,14 @@ class TenantConfig implements Feature if (! is_null($override)) { if (is_array($configKey)) { foreach ($configKey as $key) { - $this->originalConfig[$key] = $this->originalConfig[$key] ?? $this->config[$key]; + $this->originalConfig[$key] = $this->originalConfig[$key] ?? $this->config->get($key); - $this->config[$key] = $override; + $this->config->set($key, $override); } } else { - $this->originalConfig[$configKey] = $this->originalConfig[$configKey] ?? $this->config[$configKey]; + $this->originalConfig[$configKey] = $this->originalConfig[$configKey] ?? $this->config->get($configKey); - $this->config[$configKey] = $override; + $this->config->set($configKey, $override); } } } @@ -67,7 +66,7 @@ class TenantConfig implements Feature public function unsetTenantConfig(): void { foreach ($this->originalConfig as $key => $value) { - $this->config[$key] = $value; + $this->config->set($key, $value); } } } diff --git a/src/Features/UserImpersonation.php b/src/Features/UserImpersonation.php index 021b44fc..41bf774b 100644 --- a/src/Features/UserImpersonation.php +++ b/src/Features/UserImpersonation.php @@ -31,6 +31,7 @@ class UserImpersonation implements Feature /** Impersonate a user and get an HTTP redirect response. */ public static function makeResponse(string|ImpersonationToken $token, int $ttl = null): RedirectResponse { + /** @var ImpersonationToken $token */ $token = $token instanceof ImpersonationToken ? $token : ImpersonationToken::findOrFail($token); $ttl ??= static::$ttl; diff --git a/src/Jobs/CreateDatabase.php b/src/Jobs/CreateDatabase.php index b4c0d400..cb807c95 100644 --- a/src/Jobs/CreateDatabase.php +++ b/src/Jobs/CreateDatabase.php @@ -19,13 +19,9 @@ class CreateDatabase implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - /** @var TenantWithDatabase|Model */ - protected $tenant; - - public function __construct(TenantWithDatabase $tenant) - { - $this->tenant = $tenant; - } + public function __construct( + protected TenantWithDatabase&Model $tenant, + ) {} public function handle(DatabaseManager $databaseManager) { diff --git a/src/Jobs/DeleteDatabase.php b/src/Jobs/DeleteDatabase.php index 87f78d32..b59a1c05 100644 --- a/src/Jobs/DeleteDatabase.php +++ b/src/Jobs/DeleteDatabase.php @@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; @@ -17,15 +18,11 @@ class DeleteDatabase implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - /** @var TenantWithDatabase */ - protected $tenant; + public function __construct( + protected TenantWithDatabase&Model $tenant, + ) {} - public function __construct(TenantWithDatabase $tenant) - { - $this->tenant = $tenant; - } - - public function handle() + public function handle(): void { event(new DeletingDatabase($this->tenant)); diff --git a/src/Jobs/DeleteDomains.php b/src/Jobs/DeleteDomains.php index c720d4f7..f8d7f764 100644 --- a/src/Jobs/DeleteDomains.php +++ b/src/Jobs/DeleteDomains.php @@ -5,24 +5,26 @@ declare(strict_types=1); namespace Stancl\Tenancy\Jobs; use Illuminate\Bus\Queueable; +use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Stancl\Tenancy\Database\Contracts\TenantWithDatabase; +use Stancl\Tenancy\Database\Concerns\HasDomains; class DeleteDomains { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - /** @var TenantWithDatabase */ - protected $tenant; + /** @var TenantWithDatabase&Model&HasDomains */ // todo unresolvable type for phpstan + protected TenantWithDatabase&Model $tenant; - public function __construct(TenantWithDatabase $tenant) + public function __construct(TenantWithDatabase&Model $tenant) { $this->tenant = $tenant; } - public function handle() + public function handle(): void { $this->tenant->domains->each->delete(); } diff --git a/src/Jobs/MigrateDatabase.php b/src/Jobs/MigrateDatabase.php index d34b1ee4..424dacc9 100644 --- a/src/Jobs/MigrateDatabase.php +++ b/src/Jobs/MigrateDatabase.php @@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; @@ -16,20 +17,11 @@ class MigrateDatabase implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - /** @var TenantWithDatabase */ - protected $tenant; + public function __construct( + protected TenantWithDatabase&Model $tenant, + ) {} - public function __construct(TenantWithDatabase $tenant) - { - $this->tenant = $tenant; - } - - /** - * Execute the job. - * - * @return void - */ - public function handle() + public function handle(): void { Artisan::call('tenants:migrate', [ '--tenants' => [$this->tenant->getTenantKey()], diff --git a/src/Jobs/SeedDatabase.php b/src/Jobs/SeedDatabase.php index 4400c21a..9958695e 100644 --- a/src/Jobs/SeedDatabase.php +++ b/src/Jobs/SeedDatabase.php @@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; @@ -16,20 +17,11 @@ class SeedDatabase implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - /** @var TenantWithDatabase */ - protected $tenant; + public function __construct( + protected TenantWithDatabase&Model $tenant, + ) {} - public function __construct(TenantWithDatabase $tenant) - { - $this->tenant = $tenant; - } - - /** - * Execute the job. - * - * @return void - */ - public function handle() + public function handle(): void { Artisan::call('tenants:seed', [ '--tenants' => [$this->tenant->getTenantKey()], diff --git a/src/Listeners/BootstrapTenancy.php b/src/Listeners/BootstrapTenancy.php index d03da698..205efc5f 100644 --- a/src/Listeners/BootstrapTenancy.php +++ b/src/Listeners/BootstrapTenancy.php @@ -10,7 +10,7 @@ use Stancl\Tenancy\Events\TenancyInitialized; class BootstrapTenancy { - public function handle(TenancyInitialized $event) + public function handle(TenancyInitialized $event): void { event(new BootstrappingTenancy($event->tenancy)); diff --git a/src/Listeners/CreateTenantConnection.php b/src/Listeners/CreateTenantConnection.php index 987a8804..01351c08 100644 --- a/src/Listeners/CreateTenantConnection.php +++ b/src/Listeners/CreateTenantConnection.php @@ -17,7 +17,7 @@ class CreateTenantConnection $this->database = $database; } - public function handle(TenantEvent $event) + public function handle(TenantEvent $event): void { $this->database->createTenantConnection($event->tenant); } diff --git a/src/Listeners/QueueableListener.php b/src/Listeners/QueueableListener.php index b3afba0b..e10c1e7a 100644 --- a/src/Listeners/QueueableListener.php +++ b/src/Listeners/QueueableListener.php @@ -11,9 +11,9 @@ use Illuminate\Contracts\Queue\ShouldQueue; */ abstract class QueueableListener implements ShouldQueue { - public static $shouldQueue = false; + public static bool $shouldQueue = false; - public function shouldQueue($event) + public function shouldQueue($event): bool { if (static::$shouldQueue) { return true; diff --git a/src/Listeners/RevertToCentralContext.php b/src/Listeners/RevertToCentralContext.php index 788e3876..ac746ed4 100644 --- a/src/Listeners/RevertToCentralContext.php +++ b/src/Listeners/RevertToCentralContext.php @@ -10,7 +10,7 @@ use Stancl\Tenancy\Events\TenancyEnded; class RevertToCentralContext { - public function handle(TenancyEnded $event) + public function handle(TenancyEnded $event): void { event(new RevertingToCentralContext($event->tenancy)); diff --git a/src/Listeners/UpdateSyncedResource.php b/src/Listeners/UpdateSyncedResource.php index 9be290f0..45f73516 100644 --- a/src/Listeners/UpdateSyncedResource.php +++ b/src/Listeners/UpdateSyncedResource.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Stancl\Tenancy\Listeners; +use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Pivot; use Stancl\Tenancy\Contracts\SyncMaster; @@ -13,9 +14,9 @@ use Stancl\Tenancy\Exceptions\ModelNotSyncMasterException; class UpdateSyncedResource extends QueueableListener { - public static $shouldQueue = false; + public static bool $shouldQueue = false; - public function handle(SyncedResourceSaved $event) + public function handle(SyncedResourceSaved $event): void { $syncedAttributes = $event->model->only($event->model->getSyncedAttributeNames()); @@ -29,7 +30,7 @@ class UpdateSyncedResource extends QueueableListener $this->updateResourceInTenantDatabases($tenants, $event, $syncedAttributes); } - protected function getTenantsForCentralModel($centralModel) + protected function getTenantsForCentralModel($centralModel): EloquentCollection { if (! $centralModel instanceof SyncMaster) { // If we're trying to use a tenant User model instead of the central User model, for example. @@ -45,7 +46,7 @@ class UpdateSyncedResource extends QueueableListener return $centralModel->tenants; } - protected function updateResourceInCentralDatabaseAndGetTenants($event, $syncedAttributes) + protected function updateResourceInCentralDatabaseAndGetTenants($event, $syncedAttributes): EloquentCollection { /** @var Model|SyncMaster $centralModel */ $centralModel = $event->model->getCentralModelName()::where($event->model->getGlobalIdentifierKeyName(), $event->model->getGlobalIdentifierKey()) @@ -85,7 +86,7 @@ class UpdateSyncedResource extends QueueableListener }); } - protected function updateResourceInTenantDatabases($tenants, $event, $syncedAttributes) + protected function updateResourceInTenantDatabases($tenants, $event, $syncedAttributes): void { tenancy()->runForMultiple($tenants, function ($tenant) use ($event, $syncedAttributes) { // Forget instance state and find the model, diff --git a/src/Resolvers/Contracts/CachedTenantResolver.php b/src/Resolvers/Contracts/CachedTenantResolver.php index a3e3daeb..f93d7bb5 100644 --- a/src/Resolvers/Contracts/CachedTenantResolver.php +++ b/src/Resolvers/Contracts/CachedTenantResolver.php @@ -25,7 +25,7 @@ abstract class CachedTenantResolver implements TenantResolver $this->cache = $cache->store(static::$cacheStore); } - public function resolve(...$args): Tenant + public function resolve(mixed ...$args): Tenant { if (! static::$shouldCache) { return $this->resolveWithoutCache(...$args); @@ -58,12 +58,12 @@ abstract class CachedTenantResolver implements TenantResolver } } - public function getCacheKey(...$args): string + public function getCacheKey(mixed ...$args): string { return '_tenancy_resolver:' . static::class . ':' . json_encode($args); } - abstract public function resolveWithoutCache(...$args): Tenant; + abstract public function resolveWithoutCache(mixed ...$args): Tenant; public function resolved(Tenant $tenant, ...$args): void { diff --git a/src/Resolvers/DomainTenantResolver.php b/src/Resolvers/DomainTenantResolver.php index eb25ad26..926c02c0 100644 --- a/src/Resolvers/DomainTenantResolver.php +++ b/src/Resolvers/DomainTenantResolver.php @@ -20,7 +20,7 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver public static string|null $cacheStore = null; // default - public function resolveWithoutCache(...$args): Tenant + public function resolveWithoutCache(mixed ...$args): Tenant { $domain = $args[0]; diff --git a/src/Resolvers/PathTenantResolver.php b/src/Resolvers/PathTenantResolver.php index 36a05a83..2ac2a59f 100644 --- a/src/Resolvers/PathTenantResolver.php +++ b/src/Resolvers/PathTenantResolver.php @@ -18,7 +18,7 @@ class PathTenantResolver extends Contracts\CachedTenantResolver public static string|null $cacheStore = null; // default - public function resolveWithoutCache(...$args): Tenant + public function resolveWithoutCache(mixed ...$args): Tenant { /** @var Route $route */ $route = $args[0]; diff --git a/src/Resolvers/RequestDataTenantResolver.php b/src/Resolvers/RequestDataTenantResolver.php index 65d4ce38..5ed65495 100644 --- a/src/Resolvers/RequestDataTenantResolver.php +++ b/src/Resolvers/RequestDataTenantResolver.php @@ -15,7 +15,7 @@ class RequestDataTenantResolver extends Contracts\CachedTenantResolver public static string|null $cacheStore = null; // default - public function resolveWithoutCache(...$args): Tenant + public function resolveWithoutCache(mixed ...$args): Tenant { $payload = $args[0]; diff --git a/src/Tenancy.php b/src/Tenancy.php index d08e34ce..012881ae 100644 --- a/src/Tenancy.php +++ b/src/Tenancy.php @@ -28,7 +28,7 @@ class Tenancy public ?Closure $getBootstrappersUsing = null; /** Is tenancy fully initialized? */ - public $initialized = false; // todo document the difference between $tenant being set and $initialized being true (e.g. end of initialize() method) + public bool $initialized = false; // todo document the difference between $tenant being set and $initialized being true (e.g. end of initialize() method) /** Initialize tenancy for the passed tenant. */ public function initialize(Tenant|int|string $tenant): void @@ -42,6 +42,7 @@ class Tenancy } } + // todo0 for phpstan this should be $this->tenant?, but first I want to clean up the $initialized logic and explore removing the property if ($this->initialized && $this->tenant->getTenantKey() === $tenant->getTenantKey()) { return; } diff --git a/src/helpers.php b/src/helpers.php index 9c3b75cd..23b5a627 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -15,15 +15,14 @@ if (! function_exists('tenancy')) { if (! function_exists('tenant')) { /** - * Get a key from the current tenant's storage. + * Get the current tenant or a key from the current tenant's properties. * - * @param string|null $key * @return Tenant|null|mixed */ - function tenant($key = null) + function tenant(string $key = null): mixed { if (! app()->bound(Tenant::class)) { - return; + return null; } if (is_null($key)) { @@ -35,15 +34,15 @@ if (! function_exists('tenant')) { } if (! function_exists('tenant_asset')) { - /** @return string */ - function tenant_asset($asset) + // todo docblock + function tenant_asset(string|null $asset): string { return route('stancl.tenancy.asset', ['path' => $asset]); } } if (! function_exists('global_asset')) { - function global_asset($asset) + function global_asset(string $asset) // todo types, also inside the globalUrl implementation { return app('globalUrl')->asset($asset); } @@ -57,9 +56,9 @@ if (! function_exists('global_cache')) { } if (! function_exists('tenant_route')) { - function tenant_route(string $domain, $route, $parameters = [], $absolute = true) + function tenant_route(string $domain, string $route, array $parameters = [], bool $absolute = true): string { - // replace first occurance of hostname fragment with $domain + // replace the first occurrence of the hostname fragment with $domain $url = route($route, $parameters, $absolute); $hostname = parse_url($url, PHP_URL_HOST); $position = strpos($url, $hostname); diff --git a/tests/EventListenerTest.php b/tests/EventListenerTest.php index 85203f07..454c86ed 100644 --- a/tests/EventListenerTest.php +++ b/tests/EventListenerTest.php @@ -181,7 +181,7 @@ test('database is not migrated if creation is disabled', function () { class FooListener extends QueueableListener { - public static $shouldQueue = false; + public static bool $shouldQueue = false; public function handle() { diff --git a/tests/ResourceSyncingTest.php b/tests/ResourceSyncingTest.php index fad84aef..214a9f47 100644 --- a/tests/ResourceSyncingTest.php +++ b/tests/ResourceSyncingTest.php @@ -575,7 +575,7 @@ class CentralUser extends Model implements SyncMaster return ResourceUser::class; } - public function getGlobalIdentifierKey() + public function getGlobalIdentifierKey(): string|int { return $this->getAttribute($this->getGlobalIdentifierKeyName()); } @@ -610,7 +610,7 @@ class ResourceUser extends Model implements Syncable public $timestamps = false; - public function getGlobalIdentifierKey() + public function getGlobalIdentifierKey(): string|int { return $this->getAttribute($this->getGlobalIdentifierKeyName()); }