1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 14:14:04 +00:00

get phpstan errors down from 252 to 189

This commit is contained in:
Samuel Štancl 2022-08-30 05:44:23 +02:00
parent fb8b9c1614
commit 8af354c20e
40 changed files with 119 additions and 115 deletions

View file

@ -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. 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. When you're done testing, run `composer docker-down` to shut down the containers.
### Docker on M1 ### 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. 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.

View file

@ -62,6 +62,7 @@
"docker-rebuild": "PHP_VERSION=8.1 docker-compose up -d --no-deps --build", "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", "docker-m1": "ln -s docker-compose-m1.override.yml docker-compose.override.yml",
"coverage": "open coverage/phpunit/html/index.html", "coverage": "open coverage/phpunit/html/index.html",
"phpstan": "vendor/bin/phpstan",
"test": "PHP_VERSION=8.1 ./test --no-coverage", "test": "PHP_VERSION=8.1 ./test --no-coverage",
"test-full": "PHP_VERSION=8.1 ./test" "test-full": "PHP_VERSION=8.1 ./test"
}, },

View file

@ -12,7 +12,14 @@ parameters:
- Illuminate\Routing\Route - Illuminate\Routing\Route
ignoreErrors: 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 checkMissingIterableValueType: false
treatPhpDocTypesAsCertain: false treatPhpDocTypesAsCertain: false

View file

@ -8,11 +8,11 @@ interface Syncable
{ {
public function getGlobalIdentifierKeyName(): string; public function getGlobalIdentifierKeyName(): string;
public function getGlobalIdentifierKey(); public function getGlobalIdentifierKey(): string|int;
public function getCentralModelName(): string; public function getCentralModelName(): string;
public function getSyncedAttributeNames(): array; public function getSyncedAttributeNames(): array;
public function triggerSyncEvent(); public function triggerSyncEvent(): void;
} }

View file

@ -11,5 +11,5 @@ interface TenantResolver
* *
* @throws TenantCouldNotBeIdentifiedException * @throws TenantCouldNotBeIdentifiedException
*/ */
public function resolve(...$args): Tenant; public function resolve(mixed ...$args): Tenant;
} }

View file

@ -17,7 +17,7 @@ class TenantAssetsController extends Controller
$this->middleware(static::$tenancyMiddleware); $this->middleware(static::$tenancyMiddleware);
} }
public function asset($path = null) public function asset(string $path = null)
{ {
abort_if($path === null, 404); abort_if($path === null, 404);

View file

@ -10,7 +10,7 @@ trait BelongsToPrimaryModel
{ {
abstract public function getRelationshipToPrimaryModel(): string; abstract public function getRelationshipToPrimaryModel(): string;
public static function bootBelongsToPrimaryModel() public static function bootBelongsToPrimaryModel(): void
{ {
static::addGlobalScope(new ParentModelScope); static::addGlobalScope(new ParentModelScope);
} }

View file

@ -19,7 +19,7 @@ trait BelongsToTenant
return $this->belongsTo(config('tenancy.tenant_model'), BelongsToTenant::$tenantIdColumn); return $this->belongsTo(config('tenancy.tenant_model'), BelongsToTenant::$tenantIdColumn);
} }
public static function bootBelongsToTenant() public static function bootBelongsToTenant(): void
{ {
static::addGlobalScope(new TenantScope); static::addGlobalScope(new TenantScope);

View file

@ -6,7 +6,7 @@ namespace Stancl\Tenancy\Database\Concerns;
trait ConvertsDomainsToLowercase trait ConvertsDomainsToLowercase
{ {
public static function bootConvertsDomainsToLowercase() public static function bootConvertsDomainsToLowercase(): void
{ {
static::saving(function ($model) { static::saving(function ($model) {
$model->domain = strtolower($model->domain); $model->domain = strtolower($model->domain);

View file

@ -8,7 +8,7 @@ use Stancl\Tenancy\Exceptions\DomainOccupiedByOtherTenantException;
trait EnsuresDomainIsNotOccupied trait EnsuresDomainIsNotOccupied
{ {
public static function bootEnsuresDomainIsNotOccupied() public static function bootEnsuresDomainIsNotOccupied(): void
{ {
static::saving(function ($self) { static::saving(function ($self) {
if ($domain = $self->newQuery()->where('domain', $self->domain)->first()) { if ($domain = $self->newQuery()->where('domain', $self->domain)->first()) {

View file

@ -8,7 +8,7 @@ use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
trait GeneratesIds trait GeneratesIds
{ {
public static function bootGeneratesIds() public static function bootGeneratesIds(): void
{ {
static::creating(function (self $model) { static::creating(function (self $model) {
if (! $model->getKey() && $model->shouldGenerateId()) { if (! $model->getKey() && $model->shouldGenerateId()) {

View file

@ -16,7 +16,7 @@ trait InvalidatesResolverCache
Resolvers\RequestDataTenantResolver::class, Resolvers\RequestDataTenantResolver::class,
]; ];
public static function bootInvalidatesResolverCache() public static function bootInvalidatesResolverCache(): void
{ {
static::saved(function (Tenant $tenant) { static::saved(function (Tenant $tenant) {
foreach (static::$resolvers as $resolver) { foreach (static::$resolvers as $resolver) {

View file

@ -19,7 +19,7 @@ trait InvalidatesTenantsResolverCache
Resolvers\RequestDataTenantResolver::class, Resolvers\RequestDataTenantResolver::class,
]; ];
public static function bootInvalidatesTenantsResolverCache() public static function bootInvalidatesTenantsResolverCache(): void
{ {
static::saved(function (Model $model) { static::saved(function (Model $model) {
foreach (static::$resolvers as $resolver) { foreach (static::$resolvers as $resolver) {

View file

@ -10,7 +10,7 @@ use Stancl\Tenancy\Events\SyncedResourceSaved;
trait ResourceSyncing trait ResourceSyncing
{ {
public static function bootResourceSyncing() public static function bootResourceSyncing(): void
{ {
static::saved(function (Syncable $model) { static::saved(function (Syncable $model) {
/** @var ResourceSyncing $model */ /** @var ResourceSyncing $model */
@ -27,7 +27,7 @@ trait ResourceSyncing
}); });
} }
public function triggerSyncEvent() public function triggerSyncEvent(): void
{ {
/** @var Syncable $this */ /** @var Syncable $this */
event(new SyncedResourceSaved($this, tenant())); event(new SyncedResourceSaved($this, tenant()));

View file

@ -34,7 +34,7 @@ class DatabaseManager
/** /**
* Connect to a tenant's database. * Connect to a tenant's database.
*/ */
public function connectToTenant(TenantWithDatabase $tenant) public function connectToTenant(TenantWithDatabase $tenant): void
{ {
$this->purgeTenantConnection(); $this->purgeTenantConnection();
$this->createTenantConnection($tenant); $this->createTenantConnection($tenant);
@ -44,7 +44,7 @@ class DatabaseManager
/** /**
* Reconnect to the default non-tenant connection. * Reconnect to the default non-tenant connection.
*/ */
public function reconnectToCentral() public function reconnectToCentral(): void
{ {
$this->purgeTenantConnection(); $this->purgeTenantConnection();
$this->setDefaultConnection($this->config->get('tenancy.database.central_connection')); $this->setDefaultConnection($this->config->get('tenancy.database.central_connection'));
@ -53,7 +53,7 @@ class DatabaseManager
/** /**
* Change the default database connection config. * Change the default database connection config.
*/ */
public function setDefaultConnection(string $connection) public function setDefaultConnection(string $connection): void
{ {
$this->config['database.default'] = $connection; $this->config['database.default'] = $connection;
$this->database->setDefaultConnection($connection); $this->database->setDefaultConnection($connection);
@ -62,7 +62,7 @@ class DatabaseManager
/** /**
* Create the tenant database connection. * Create the tenant database connection.
*/ */
public function createTenantConnection(TenantWithDatabase $tenant) public function createTenantConnection(TenantWithDatabase $tenant): void
{ {
$this->config['database.connections.tenant'] = $tenant->database()->connection(); $this->config['database.connections.tenant'] = $tenant->database()->connection();
} }
@ -70,7 +70,7 @@ class DatabaseManager
/** /**
* Purge the tenant database connection. * Purge the tenant database connection.
*/ */
public function purgeTenantConnection() public function purgeTenantConnection(): void
{ {
if (array_key_exists('tenant', $this->database->getConnections())) { if (array_key_exists('tenant', $this->database->getConnections())) {
$this->database->purge('tenant'); $this->database->purge('tenant');

View file

@ -8,7 +8,7 @@ use Exception;
class NoConnectionSetException extends Exception class NoConnectionSetException extends Exception
{ {
public function __construct($manager) public function __construct(string $manager)
{ {
parent::__construct("No connection was set on this $manager instance."); parent::__construct("No connection was set on this $manager instance.");
} }

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Database\Models; namespace Stancl\Tenancy\Database\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Stancl\Tenancy\Contracts; use Stancl\Tenancy\Contracts;
use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Contracts\Tenant;
use Stancl\Tenancy\Database\Concerns; use Stancl\Tenancy\Database\Concerns;
@ -25,7 +26,7 @@ class Domain extends Model implements Contracts\Domain
protected $guarded = []; protected $guarded = [];
public function tenant() public function tenant(): BelongsTo
{ {
return $this->belongsTo(config('tenancy.tenant_model')); return $this->belongsTo(config('tenancy.tenant_model'));
} }

View file

@ -10,12 +10,12 @@ use Illuminate\Support\Str;
use Stancl\Tenancy\Database\Concerns\CentralConnection; use Stancl\Tenancy\Database\Concerns\CentralConnection;
/** /**
* @param string $token * @property string $token
* @param string $tenant_id * @property string $tenant_id
* @param string $user_id * @property string $user_id
* @param string $auth_guard * @property string $auth_guard
* @param string $redirect_url * @property string $redirect_url
* @param Carbon $created_at * @property Carbon $created_at
*/ */
class ImpersonationToken extends Model class ImpersonationToken extends Model
{ {
@ -35,7 +35,7 @@ class ImpersonationToken extends Model
'created_at', 'created_at',
]; ];
public static function booted() public static function booted(): void
{ {
static::creating(function ($model) { static::creating(function ($model) {
$model->created_at = $model->created_at ?? $model->freshTimestamp(); $model->created_at = $model->created_at ?? $model->freshTimestamp();

View file

@ -9,7 +9,7 @@ use Stancl\Tenancy\Contracts\Syncable;
class TenantPivot extends Pivot class TenantPivot extends Pivot
{ {
public static function booted() public static function booted(): void
{ {
static::saved(function (self $pivot) { static::saved(function (self $pivot) {
$parent = $pivot->pivotParent; $parent = $pivot->pivotParent;

View file

@ -10,13 +10,12 @@ use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
class SyncedResourceSaved class SyncedResourceSaved
{ {
/** @var Syncable|Model */ public Syncable&Model $model;
public $model;
/** @var TenantWithDatabase|Model|null */ /** @var (TenantWithDatabase&Model)|null */
public $tenant; public TenantWithDatabase|null $tenant;
public function __construct(Syncable $model, ?TenantWithDatabase $tenant) public function __construct(Syncable $model, TenantWithDatabase|null $tenant)
{ {
$this->model = $model; $this->model = $model;
$this->tenant = $tenant; $this->tenant = $tenant;

View file

@ -19,8 +19,7 @@ class TenantConfig implements Feature
/** @var Repository */ /** @var Repository */
protected $config; protected $config;
/** @var array */ public array $originalConfig = [];
public $originalConfig = [];
public static $storageToConfigMap = [ public static $storageToConfigMap = [
// 'paypal_api_key' => 'services.paypal.api_key', // 'paypal_api_key' => 'services.paypal.api_key',
@ -51,14 +50,14 @@ class TenantConfig implements Feature
if (! is_null($override)) { if (! is_null($override)) {
if (is_array($configKey)) { if (is_array($configKey)) {
foreach ($configKey as $key) { 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 { } 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 public function unsetTenantConfig(): void
{ {
foreach ($this->originalConfig as $key => $value) { foreach ($this->originalConfig as $key => $value) {
$this->config[$key] = $value; $this->config->set($key, $value);
} }
} }
} }

View file

@ -31,6 +31,7 @@ class UserImpersonation implements Feature
/** Impersonate a user and get an HTTP redirect response. */ /** Impersonate a user and get an HTTP redirect response. */
public static function makeResponse(string|ImpersonationToken $token, int $ttl = null): RedirectResponse public static function makeResponse(string|ImpersonationToken $token, int $ttl = null): RedirectResponse
{ {
/** @var ImpersonationToken $token */
$token = $token instanceof ImpersonationToken ? $token : ImpersonationToken::findOrFail($token); $token = $token instanceof ImpersonationToken ? $token : ImpersonationToken::findOrFail($token);
$ttl ??= static::$ttl; $ttl ??= static::$ttl;

View file

@ -19,13 +19,9 @@ class CreateDatabase implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var TenantWithDatabase|Model */ public function __construct(
protected $tenant; protected TenantWithDatabase&Model $tenant,
) {}
public function __construct(TenantWithDatabase $tenant)
{
$this->tenant = $tenant;
}
public function handle(DatabaseManager $databaseManager) public function handle(DatabaseManager $databaseManager)
{ {

View file

@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Jobs;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
@ -17,15 +18,11 @@ class DeleteDatabase implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var TenantWithDatabase */ public function __construct(
protected $tenant; protected TenantWithDatabase&Model $tenant,
) {}
public function __construct(TenantWithDatabase $tenant) public function handle(): void
{
$this->tenant = $tenant;
}
public function handle()
{ {
event(new DeletingDatabase($this->tenant)); event(new DeletingDatabase($this->tenant));

View file

@ -5,24 +5,26 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Jobs; namespace Stancl\Tenancy\Jobs;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase; use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Database\Concerns\HasDomains;
class DeleteDomains class DeleteDomains
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var TenantWithDatabase */ /** @var TenantWithDatabase&Model&HasDomains */ // todo unresolvable type for phpstan
protected $tenant; protected TenantWithDatabase&Model $tenant;
public function __construct(TenantWithDatabase $tenant) public function __construct(TenantWithDatabase&Model $tenant)
{ {
$this->tenant = $tenant; $this->tenant = $tenant;
} }
public function handle() public function handle(): void
{ {
$this->tenant->domains->each->delete(); $this->tenant->domains->each->delete();
} }

View file

@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Jobs;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
@ -16,20 +17,11 @@ class MigrateDatabase implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var TenantWithDatabase */ public function __construct(
protected $tenant; protected TenantWithDatabase&Model $tenant,
) {}
public function __construct(TenantWithDatabase $tenant) public function handle(): void
{
$this->tenant = $tenant;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{ {
Artisan::call('tenants:migrate', [ Artisan::call('tenants:migrate', [
'--tenants' => [$this->tenant->getTenantKey()], '--tenants' => [$this->tenant->getTenantKey()],

View file

@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Jobs;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
@ -16,20 +17,11 @@ class SeedDatabase implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var TenantWithDatabase */ public function __construct(
protected $tenant; protected TenantWithDatabase&Model $tenant,
) {}
public function __construct(TenantWithDatabase $tenant) public function handle(): void
{
$this->tenant = $tenant;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{ {
Artisan::call('tenants:seed', [ Artisan::call('tenants:seed', [
'--tenants' => [$this->tenant->getTenantKey()], '--tenants' => [$this->tenant->getTenantKey()],

View file

@ -10,7 +10,7 @@ use Stancl\Tenancy\Events\TenancyInitialized;
class BootstrapTenancy class BootstrapTenancy
{ {
public function handle(TenancyInitialized $event) public function handle(TenancyInitialized $event): void
{ {
event(new BootstrappingTenancy($event->tenancy)); event(new BootstrappingTenancy($event->tenancy));

View file

@ -17,7 +17,7 @@ class CreateTenantConnection
$this->database = $database; $this->database = $database;
} }
public function handle(TenantEvent $event) public function handle(TenantEvent $event): void
{ {
$this->database->createTenantConnection($event->tenant); $this->database->createTenantConnection($event->tenant);
} }

View file

@ -11,9 +11,9 @@ use Illuminate\Contracts\Queue\ShouldQueue;
*/ */
abstract class QueueableListener implements 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) { if (static::$shouldQueue) {
return true; return true;

View file

@ -10,7 +10,7 @@ use Stancl\Tenancy\Events\TenancyEnded;
class RevertToCentralContext class RevertToCentralContext
{ {
public function handle(TenancyEnded $event) public function handle(TenancyEnded $event): void
{ {
event(new RevertingToCentralContext($event->tenancy)); event(new RevertingToCentralContext($event->tenancy));

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Listeners; namespace Stancl\Tenancy\Listeners;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\Relations\Pivot;
use Stancl\Tenancy\Contracts\SyncMaster; use Stancl\Tenancy\Contracts\SyncMaster;
@ -13,9 +14,9 @@ use Stancl\Tenancy\Exceptions\ModelNotSyncMasterException;
class UpdateSyncedResource extends QueueableListener 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()); $syncedAttributes = $event->model->only($event->model->getSyncedAttributeNames());
@ -29,7 +30,7 @@ class UpdateSyncedResource extends QueueableListener
$this->updateResourceInTenantDatabases($tenants, $event, $syncedAttributes); $this->updateResourceInTenantDatabases($tenants, $event, $syncedAttributes);
} }
protected function getTenantsForCentralModel($centralModel) protected function getTenantsForCentralModel($centralModel): EloquentCollection
{ {
if (! $centralModel instanceof SyncMaster) { if (! $centralModel instanceof SyncMaster) {
// If we're trying to use a tenant User model instead of the central User model, for example. // 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; return $centralModel->tenants;
} }
protected function updateResourceInCentralDatabaseAndGetTenants($event, $syncedAttributes) protected function updateResourceInCentralDatabaseAndGetTenants($event, $syncedAttributes): EloquentCollection
{ {
/** @var Model|SyncMaster $centralModel */ /** @var Model|SyncMaster $centralModel */
$centralModel = $event->model->getCentralModelName()::where($event->model->getGlobalIdentifierKeyName(), $event->model->getGlobalIdentifierKey()) $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) { tenancy()->runForMultiple($tenants, function ($tenant) use ($event, $syncedAttributes) {
// Forget instance state and find the model, // Forget instance state and find the model,

View file

@ -25,7 +25,7 @@ abstract class CachedTenantResolver implements TenantResolver
$this->cache = $cache->store(static::$cacheStore); $this->cache = $cache->store(static::$cacheStore);
} }
public function resolve(...$args): Tenant public function resolve(mixed ...$args): Tenant
{ {
if (! static::$shouldCache) { if (! static::$shouldCache) {
return $this->resolveWithoutCache(...$args); 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); 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 public function resolved(Tenant $tenant, ...$args): void
{ {

View file

@ -20,7 +20,7 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver
public static string|null $cacheStore = null; // default public static string|null $cacheStore = null; // default
public function resolveWithoutCache(...$args): Tenant public function resolveWithoutCache(mixed ...$args): Tenant
{ {
$domain = $args[0]; $domain = $args[0];

View file

@ -18,7 +18,7 @@ class PathTenantResolver extends Contracts\CachedTenantResolver
public static string|null $cacheStore = null; // default public static string|null $cacheStore = null; // default
public function resolveWithoutCache(...$args): Tenant public function resolveWithoutCache(mixed ...$args): Tenant
{ {
/** @var Route $route */ /** @var Route $route */
$route = $args[0]; $route = $args[0];

View file

@ -15,7 +15,7 @@ class RequestDataTenantResolver extends Contracts\CachedTenantResolver
public static string|null $cacheStore = null; // default public static string|null $cacheStore = null; // default
public function resolveWithoutCache(...$args): Tenant public function resolveWithoutCache(mixed ...$args): Tenant
{ {
$payload = $args[0]; $payload = $args[0];

View file

@ -28,7 +28,7 @@ class Tenancy
public ?Closure $getBootstrappersUsing = null; public ?Closure $getBootstrappersUsing = null;
/** Is tenancy fully initialized? */ /** 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. */ /** Initialize tenancy for the passed tenant. */
public function initialize(Tenant|int|string $tenant): void 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()) { if ($this->initialized && $this->tenant->getTenantKey() === $tenant->getTenantKey()) {
return; return;
} }

View file

@ -15,15 +15,14 @@ if (! function_exists('tenancy')) {
if (! function_exists('tenant')) { 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 * @return Tenant|null|mixed
*/ */
function tenant($key = null) function tenant(string $key = null): mixed
{ {
if (! app()->bound(Tenant::class)) { if (! app()->bound(Tenant::class)) {
return; return null;
} }
if (is_null($key)) { if (is_null($key)) {
@ -35,15 +34,15 @@ if (! function_exists('tenant')) {
} }
if (! function_exists('tenant_asset')) { if (! function_exists('tenant_asset')) {
/** @return string */ // todo docblock
function tenant_asset($asset) function tenant_asset(string|null $asset): string
{ {
return route('stancl.tenancy.asset', ['path' => $asset]); return route('stancl.tenancy.asset', ['path' => $asset]);
} }
} }
if (! function_exists('global_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); return app('globalUrl')->asset($asset);
} }
@ -57,9 +56,9 @@ if (! function_exists('global_cache')) {
} }
if (! function_exists('tenant_route')) { 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); $url = route($route, $parameters, $absolute);
$hostname = parse_url($url, PHP_URL_HOST); $hostname = parse_url($url, PHP_URL_HOST);
$position = strpos($url, $hostname); $position = strpos($url, $hostname);

View file

@ -181,7 +181,7 @@ test('database is not migrated if creation is disabled', function () {
class FooListener extends QueueableListener class FooListener extends QueueableListener
{ {
public static $shouldQueue = false; public static bool $shouldQueue = false;
public function handle() public function handle()
{ {

View file

@ -575,7 +575,7 @@ class CentralUser extends Model implements SyncMaster
return ResourceUser::class; return ResourceUser::class;
} }
public function getGlobalIdentifierKey() public function getGlobalIdentifierKey(): string|int
{ {
return $this->getAttribute($this->getGlobalIdentifierKeyName()); return $this->getAttribute($this->getGlobalIdentifierKeyName());
} }
@ -610,7 +610,7 @@ class ResourceUser extends Model implements Syncable
public $timestamps = false; public $timestamps = false;
public function getGlobalIdentifierKey() public function getGlobalIdentifierKey(): string|int
{ {
return $this->getAttribute($this->getGlobalIdentifierKeyName()); return $this->getAttribute($this->getGlobalIdentifierKeyName());
} }