mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 15:34:03 +00:00
get phpstan errors down from 252 to 189
This commit is contained in:
parent
fb8b9c1614
commit
8af354c20e
40 changed files with 119 additions and 115 deletions
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,5 @@ interface TenantResolver
|
||||||
*
|
*
|
||||||
* @throws TenantCouldNotBeIdentifiedException
|
* @throws TenantCouldNotBeIdentifiedException
|
||||||
*/
|
*/
|
||||||
public function resolve(...$args): Tenant;
|
public function resolve(mixed ...$args): Tenant;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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()));
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
|
|
|
||||||
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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'));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()],
|
||||||
|
|
|
||||||
|
|
@ -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()],
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue