From 87212e5390a463b78eb629e55728265ea8ea791d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Thu, 29 Sep 2022 02:47:13 +0200 Subject: [PATCH] phpstan, global_cache, resolver improvements, InitializationHelpers trait --- phpstan.neon | 9 +++++ src/Commands/Install.php | 15 +------- src/Commands/Link.php | 17 +--------- src/Commands/Migrate.php | 14 ++++---- src/Commands/MigrateFresh.php | 15 ++------ src/Commands/Rollback.php | 32 ++++++----------- src/Commands/Run.php | 22 ++---------- src/Commands/Seed.php | 19 +++-------- src/Commands/TenantList.php | 15 +------- src/Concerns/DealsWithMigrations.php | 4 +-- src/Contracts/UniqueIdentifierGenerator.php | 6 ++-- src/Database/Concerns/HasDomains.php | 2 ++ .../Concerns/InitializationHelpers.php | 19 +++++++++++ src/Database/Models/Tenant.php | 1 + src/Events/Contracts/TenancyEvent.php | 10 ++---- src/Middleware/IdentificationMiddleware.php | 14 ++++---- src/Middleware/InitializeTenancyByDomain.php | 27 +++++---------- .../InitializeTenancyByDomainOrSubdomain.php | 9 ++--- src/Middleware/InitializeTenancyByPath.php | 21 ++++-------- .../InitializeTenancyByRequestData.php | 34 +++++-------------- .../InitializeTenancyBySubdomain.php | 12 +++---- .../PreventAccessFromCentralDomains.php | 7 ++-- src/Middleware/ScopeSessions.php | 3 +- .../Contracts/CachedTenantResolver.php | 2 +- src/Resolvers/DomainTenantResolver.php | 3 +- src/Resolvers/PathTenantResolver.php | 4 +-- src/Resolvers/RequestDataTenantResolver.php | 4 +-- src/UUIDGenerator.php | 3 +- src/helpers.php | 34 +++++++++++++++++-- tests/DomainTest.php | 2 +- tests/Etc/Tenant.php | 3 ++ tests/GlobalCacheTest.php | 14 ++++++++ tests/PathIdentificationTest.php | 2 +- tests/RequestDataIdentificationTest.php | 1 - tests/SubdomainTest.php | 2 +- 35 files changed, 170 insertions(+), 231 deletions(-) create mode 100644 src/Database/Concerns/InitializationHelpers.php diff --git a/phpstan.neon b/phpstan.neon index 9ff082dd..f325f3ec 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -10,6 +10,7 @@ parameters: universalObjectCratesClasses: - Illuminate\Routing\Route + - Illuminate\Database\Eloquent\Model ignoreErrors: - @@ -20,6 +21,14 @@ parameters: message: '#invalid type Laravel\\Telescope\\IncomingEntry#' paths: - src/Features/TelescopeTags.php + - + message: '#Parameter \#1 \$key of method Illuminate\\Contracts\\Cache\\Repository::put\(\) expects string#' + paths: + - src/helpers.php + - + message: '#PHPDoc tag \@param has invalid value \(dynamic#' + paths: + - src/helpers.php checkMissingIterableValueType: false treatPhpDocTypesAsCertain: false diff --git a/src/Commands/Install.php b/src/Commands/Install.php index 41492b26..12a2c2c9 100644 --- a/src/Commands/Install.php +++ b/src/Commands/Install.php @@ -8,24 +8,11 @@ use Illuminate\Console\Command; class Install extends Command { - /** - * The name and signature of the console command. - * - * @var string - */ protected $signature = 'tenancy:install'; - /** - * The console command description. - * - * @var string - */ protected $description = 'Install stancl/tenancy.'; - /** - * Execute the console command. - */ - public function handle() + public function handle(): void { $this->comment('Installing stancl/tenancy...'); $this->callSilent('vendor:publish', [ diff --git a/src/Commands/Link.php b/src/Commands/Link.php index 061f2d3d..2b9ee4cf 100644 --- a/src/Commands/Link.php +++ b/src/Commands/Link.php @@ -15,30 +15,15 @@ class Link extends Command { use HasATenantsOption; - /** - * The console command signature. - * - * @var string - */ protected $signature = 'tenants:link {--tenants=* : The tenant(s) to run the command for. Default: all} {--relative : Create the symbolic link using relative paths} {--force : Recreate existing symbolic links} {--remove : Remove symbolic links}'; - /** - * The console command description. - * - * @var string - */ protected $description = 'Create or remove tenant symbolic links.'; - /** - * Execute the console command. - * - * @return void - */ - public function handle() + public function handle(): void { $tenants = $this->getTenants(); diff --git a/src/Commands/Migrate.php b/src/Commands/Migrate.php index 52ecd47f..739b56de 100644 --- a/src/Commands/Migrate.php +++ b/src/Commands/Migrate.php @@ -7,7 +7,6 @@ namespace Stancl\Tenancy\Commands; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Database\Console\Migrations\MigrateCommand; use Illuminate\Database\Migrations\Migrator; -use Stancl\Tenancy\Concerns\DealsWithMigrations; use Stancl\Tenancy\Concerns\ExtendsLaravelCommand; use Stancl\Tenancy\Concerns\HasATenantsOption; use Stancl\Tenancy\Events\DatabaseMigrated; @@ -15,7 +14,7 @@ use Stancl\Tenancy\Events\MigratingDatabase; class Migrate extends MigrateCommand { - use HasATenantsOption, DealsWithMigrations, ExtendsLaravelCommand; + use HasATenantsOption, ExtendsLaravelCommand; protected $description = 'Run migrations for tenant(s)'; @@ -31,10 +30,7 @@ class Migrate extends MigrateCommand $this->specifyParameters(); } - /** - * Execute the console command. - */ - public function handle() + public function handle(): int { foreach (config('tenancy.migration_parameters') as $parameter => $value) { if (! $this->input->hasParameterOption($parameter)) { @@ -43,10 +39,10 @@ class Migrate extends MigrateCommand } if (! $this->confirmToProceed()) { - return; + return 1; } - tenancy()->runForMultiple($this->option('tenants'), function ($tenant) { + tenancy()->runForMultiple($this->getTenants(), function ($tenant) { $this->line("Tenant: {$tenant->getTenantKey()}"); event(new MigratingDatabase($tenant)); @@ -56,5 +52,7 @@ class Migrate extends MigrateCommand event(new DatabaseMigrated($tenant)); }); + + return 0; } } diff --git a/src/Commands/MigrateFresh.php b/src/Commands/MigrateFresh.php index 63860153..56a6047f 100644 --- a/src/Commands/MigrateFresh.php +++ b/src/Commands/MigrateFresh.php @@ -5,19 +5,13 @@ declare(strict_types=1); namespace Stancl\Tenancy\Commands; use Illuminate\Console\Command; -use Stancl\Tenancy\Concerns\DealsWithMigrations; use Stancl\Tenancy\Concerns\HasATenantsOption; use Symfony\Component\Console\Input\InputOption; final class MigrateFresh extends Command { - use HasATenantsOption, DealsWithMigrations; + use HasATenantsOption; - /** - * The console command description. - * - * @var string - */ protected $description = 'Drop all tables and re-run all migrations for tenant(s)'; public function __construct() @@ -29,12 +23,9 @@ final class MigrateFresh extends Command $this->setName('tenants:migrate-fresh'); } - /** - * Execute the console command. - */ - public function handle() + public function handle(): void { - tenancy()->runForMultiple($this->option('tenants'), function ($tenant) { + tenancy()->runForMultiple($this->getTenants(), function ($tenant) { $this->info('Dropping tables.'); $this->call('db:wipe', array_filter([ '--database' => 'tenant', diff --git a/src/Commands/Rollback.php b/src/Commands/Rollback.php index 1c434189..d61083d4 100644 --- a/src/Commands/Rollback.php +++ b/src/Commands/Rollback.php @@ -6,7 +6,6 @@ namespace Stancl\Tenancy\Commands; use Illuminate\Database\Console\Migrations\RollbackCommand; use Illuminate\Database\Migrations\Migrator; -use Stancl\Tenancy\Concerns\DealsWithMigrations; use Stancl\Tenancy\Concerns\ExtendsLaravelCommand; use Stancl\Tenancy\Concerns\HasATenantsOption; use Stancl\Tenancy\Events\DatabaseRolledBack; @@ -14,25 +13,10 @@ use Stancl\Tenancy\Events\RollingBackDatabase; class Rollback extends RollbackCommand { - use HasATenantsOption, DealsWithMigrations, ExtendsLaravelCommand; + use HasATenantsOption, ExtendsLaravelCommand; - protected static function getTenantCommandName(): string - { - return 'tenants:rollback'; - } - - /** - * The console command description. - * - * @var string - */ protected $description = 'Rollback migrations for tenant(s).'; - /** - * Create a new command instance. - * - * @return void - */ public function __construct(Migrator $migrator) { parent::__construct($migrator); @@ -40,10 +24,7 @@ class Rollback extends RollbackCommand $this->specifyTenantSignature(); } - /** - * Execute the console command. - */ - public function handle() + public function handle(): int { foreach (config('tenancy.migration_parameters') as $parameter => $value) { if (! $this->input->hasParameterOption($parameter)) { @@ -52,7 +33,7 @@ class Rollback extends RollbackCommand } if (! $this->confirmToProceed()) { - return; + return 1; } tenancy()->runForMultiple($this->option('tenants'), function ($tenant) { @@ -65,5 +46,12 @@ class Rollback extends RollbackCommand event(new DatabaseRolledBack($tenant)); }); + + return 0; + } + + protected static function getTenantCommandName(): string + { + return 'tenants:rollback'; } } diff --git a/src/Commands/Run.php b/src/Commands/Run.php index a24fb9c7..403ffd1b 100644 --- a/src/Commands/Run.php +++ b/src/Commands/Run.php @@ -11,27 +11,14 @@ use Symfony\Component\Console\Output\ConsoleOutput; class Run extends Command { - /** - * The console command description. - * - * @var string - */ protected $description = 'Run a command for tenant(s)'; - /** - * The name and signature of the console command. - * - * @var string - */ protected $signature = 'tenants:run {commandname : The artisan command.} {--tenants=* : The tenant(s) to run the command for. Default: all}'; - /** - * Execute the console command. - */ - public function handle() + public function handle(): void { - $argvInput = $this->ArgvInput(); + $argvInput = $this->argvInput(); tenancy()->runForMultiple($this->option('tenants'), function ($tenant) use ($argvInput) { $this->line("Tenant: {$tenant->getTenantKey()}"); @@ -41,10 +28,7 @@ class Run extends Command }); } - /** - * Get command as ArgvInput instance. - */ - protected function ArgvInput(): ArgvInput + protected function argvInput(): ArgvInput { // Convert string command to array $subCommand = explode(' ', $this->argument('commandname')); diff --git a/src/Commands/Seed.php b/src/Commands/Seed.php index 8c525208..b59e0062 100644 --- a/src/Commands/Seed.php +++ b/src/Commands/Seed.php @@ -14,29 +14,16 @@ class Seed extends SeedCommand { use HasATenantsOption; - /** - * The console command description. - * - * @var string - */ protected $description = 'Seed tenant database(s).'; protected $name = 'tenants:seed'; - /** - * Create a new command instance. - * - * @return void - */ public function __construct(ConnectionResolverInterface $resolver) { parent::__construct($resolver); } - /** - * Execute the console command. - */ - public function handle() + public function handle(): int { foreach (config('tenancy.seeder_parameters') as $parameter => $value) { if (! $this->input->hasParameterOption($parameter)) { @@ -45,7 +32,7 @@ class Seed extends SeedCommand } if (! $this->confirmToProceed()) { - return; + return 1; } tenancy()->runForMultiple($this->option('tenants'), function ($tenant) { @@ -58,5 +45,7 @@ class Seed extends SeedCommand event(new DatabaseSeeded($tenant)); }); + + return 0; } } diff --git a/src/Commands/TenantList.php b/src/Commands/TenantList.php index 13775676..ce8dfcec 100644 --- a/src/Commands/TenantList.php +++ b/src/Commands/TenantList.php @@ -9,24 +9,11 @@ use Stancl\Tenancy\Contracts\Tenant; class TenantList extends Command { - /** - * The name and signature of the console command. - * - * @var string - */ protected $signature = 'tenants:list'; - /** - * The console command description. - * - * @var string - */ protected $description = 'List tenants.'; - /** - * Execute the console command. - */ - public function handle() + public function handle(): void { $this->info('Listing all tenants.'); tenancy() diff --git a/src/Concerns/DealsWithMigrations.php b/src/Concerns/DealsWithMigrations.php index 4bb6b44c..3129c68d 100644 --- a/src/Concerns/DealsWithMigrations.php +++ b/src/Concerns/DealsWithMigrations.php @@ -6,12 +6,12 @@ namespace Stancl\Tenancy\Concerns; trait DealsWithMigrations { - protected function getMigrationPaths() + protected function getMigrationPaths(): array { if ($this->input->hasOption('path') && $this->input->getOption('path')) { return parent::getMigrationPaths(); } - return database_path('migrations/tenant'); + return [database_path('migrations/tenant')]; } } diff --git a/src/Contracts/UniqueIdentifierGenerator.php b/src/Contracts/UniqueIdentifierGenerator.php index b21d6028..14d91ae0 100644 --- a/src/Contracts/UniqueIdentifierGenerator.php +++ b/src/Contracts/UniqueIdentifierGenerator.php @@ -4,10 +4,12 @@ declare(strict_types=1); namespace Stancl\Tenancy\Contracts; +use Illuminate\Database\Eloquent\Model; + interface UniqueIdentifierGenerator { /** - * Generate a unique identifier. + * Generate a unique identifier for a model. */ - public static function generate($resource): string; + public static function generate(Model $model): string; } diff --git a/src/Database/Concerns/HasDomains.php b/src/Database/Concerns/HasDomains.php index 594e9a81..bd512e23 100644 --- a/src/Database/Concerns/HasDomains.php +++ b/src/Database/Concerns/HasDomains.php @@ -10,6 +10,8 @@ use Stancl\Tenancy\Contracts\Domain; /** * @property-read Domain[]|\Illuminate\Database\Eloquent\Collection $domains + * @mixin \Illuminate\Database\Eloquent\Model + * @mixin \Stancl\Tenancy\Contracts\Tenant */ trait HasDomains { diff --git a/src/Database/Concerns/InitializationHelpers.php b/src/Database/Concerns/InitializationHelpers.php new file mode 100644 index 00000000..ff142c5a --- /dev/null +++ b/src/Database/Concerns/InitializationHelpers.php @@ -0,0 +1,19 @@ +initialize($this); + } + + public function leave(): void + { + tenancy()->end(); + } +} diff --git a/src/Database/Models/Tenant.php b/src/Database/Models/Tenant.php index 4518e7b7..88c34146 100644 --- a/src/Database/Models/Tenant.php +++ b/src/Database/Models/Tenant.php @@ -26,6 +26,7 @@ class Tenant extends Model implements Contracts\Tenant Concerns\HasDataColumn, Concerns\HasInternalKeys, Concerns\TenantRun, + Concerns\InitializationHelpers, Concerns\InvalidatesResolverCache; protected $table = 'tenants'; diff --git a/src/Events/Contracts/TenancyEvent.php b/src/Events/Contracts/TenancyEvent.php index f292049d..9a85085d 100644 --- a/src/Events/Contracts/TenancyEvent.php +++ b/src/Events/Contracts/TenancyEvent.php @@ -8,11 +8,7 @@ use Stancl\Tenancy\Tenancy; abstract class TenancyEvent { - /** @var Tenancy */ - public $tenancy; - - public function __construct(Tenancy $tenancy) - { - $this->tenancy = $tenancy; - } + public function __construct( + public Tenancy $tenancy, + ) {} } diff --git a/src/Middleware/IdentificationMiddleware.php b/src/Middleware/IdentificationMiddleware.php index 38f4684d..ed582c93 100644 --- a/src/Middleware/IdentificationMiddleware.php +++ b/src/Middleware/IdentificationMiddleware.php @@ -4,20 +4,18 @@ declare(strict_types=1); namespace Stancl\Tenancy\Middleware; +use Closure; use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException; use Stancl\Tenancy\Contracts\TenantResolver; use Stancl\Tenancy\Tenancy; +/** + * @property Tenancy $tenancy + * @property TenantResolver $resolver + */ abstract class IdentificationMiddleware { - /** @var callable */ - public static $onFail; - - /** @var Tenancy */ - protected $tenancy; - - /** @var TenantResolver */ - protected $resolver; + public static ?Closure $onFail = null; public function initializeTenancy($request, $next, ...$resolverArguments) { diff --git a/src/Middleware/InitializeTenancyByDomain.php b/src/Middleware/InitializeTenancyByDomain.php index 5a07112d..8e4423fd 100644 --- a/src/Middleware/InitializeTenancyByDomain.php +++ b/src/Middleware/InitializeTenancyByDomain.php @@ -5,32 +5,21 @@ declare(strict_types=1); namespace Stancl\Tenancy\Middleware; use Closure; +use Illuminate\Http\Request; use Stancl\Tenancy\Resolvers\DomainTenantResolver; use Stancl\Tenancy\Tenancy; class InitializeTenancyByDomain extends IdentificationMiddleware { - /** @var callable|null */ - public static $onFail; + public static ?Closure $onFail = null; - /** @var Tenancy */ - protected $tenancy; + public function __construct( + protected Tenancy $tenancy, + protected DomainTenantResolver $resolver, + ) {} - /** @var DomainTenantResolver */ - protected $resolver; - - public function __construct(Tenancy $tenancy, DomainTenantResolver $resolver) - { - $this->tenancy = $tenancy; - $this->resolver = $resolver; - } - - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - */ - public function handle($request, Closure $next) + /** @return \Illuminate\Http\Response|mixed */ + public function handle(Request $request, Closure $next): mixed { return $this->initializeTenancy( $request, diff --git a/src/Middleware/InitializeTenancyByDomainOrSubdomain.php b/src/Middleware/InitializeTenancyByDomainOrSubdomain.php index 9b153db3..1a30001a 100644 --- a/src/Middleware/InitializeTenancyByDomainOrSubdomain.php +++ b/src/Middleware/InitializeTenancyByDomainOrSubdomain.php @@ -5,16 +5,13 @@ declare(strict_types=1); namespace Stancl\Tenancy\Middleware; use Closure; +use Illuminate\Http\Request; use Illuminate\Support\Str; class InitializeTenancyByDomainOrSubdomain { - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - */ - public function handle($request, Closure $next) + /** @return \Illuminate\Http\Response|mixed */ + public function handle(Request $request, Closure $next): mixed { if ($this->isSubdomain($request->getHost())) { return app(InitializeTenancyBySubdomain::class)->handle($request, $next); diff --git a/src/Middleware/InitializeTenancyByPath.php b/src/Middleware/InitializeTenancyByPath.php index ae15323c..c02fc23c 100644 --- a/src/Middleware/InitializeTenancyByPath.php +++ b/src/Middleware/InitializeTenancyByPath.php @@ -16,22 +16,15 @@ use Stancl\Tenancy\Tenancy; class InitializeTenancyByPath extends IdentificationMiddleware { - /** @var callable|null */ - public static $onFail; + public static ?Closure $onFail = null; - /** @var Tenancy */ - protected $tenancy; + public function __construct( + protected Tenancy $tenancy, + protected PathTenantResolver $resolver, + ) {} - /** @var PathTenantResolver */ - protected $resolver; - - public function __construct(Tenancy $tenancy, PathTenantResolver $resolver) - { - $this->tenancy = $tenancy; - $this->resolver = $resolver; - } - - public function handle(Request $request, Closure $next) + /** @return \Illuminate\Http\Response|mixed */ + public function handle(Request $request, Closure $next): mixed { /** @var Route $route */ $route = $request->route(); diff --git a/src/Middleware/InitializeTenancyByRequestData.php b/src/Middleware/InitializeTenancyByRequestData.php index 4e1d33ff..93ca42ab 100644 --- a/src/Middleware/InitializeTenancyByRequestData.php +++ b/src/Middleware/InitializeTenancyByRequestData.php @@ -11,33 +11,17 @@ use Stancl\Tenancy\Tenancy; class InitializeTenancyByRequestData extends IdentificationMiddleware { - /** @var string|null */ - public static $header = 'X-Tenant'; + public static string $header = 'X-Tenant'; + public static string $queryParameter = 'tenant'; + public static ?Closure $onFail = null; - /** @var string|null */ - public static $queryParameter = 'tenant'; + public function __construct( + protected Tenancy $tenancy, + protected RequestDataTenantResolver $resolver, + ) {} - /** @var callable|null */ - public static $onFail; - - /** @var Tenancy */ - protected $tenancy; - - /** @var TenantResolver */ - protected $resolver; - - public function __construct(Tenancy $tenancy, RequestDataTenantResolver $resolver) - { - $this->tenancy = $tenancy; - $this->resolver = $resolver; - } - - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - */ - public function handle($request, Closure $next) + /** @return \Illuminate\Http\Response|mixed */ + public function handle(Request $request, Closure $next): mixed { if ($request->method() !== 'OPTIONS') { return $this->initializeTenancy($request, $next, $this->getPayload($request)); diff --git a/src/Middleware/InitializeTenancyBySubdomain.php b/src/Middleware/InitializeTenancyBySubdomain.php index 76389df7..1bf083f3 100644 --- a/src/Middleware/InitializeTenancyBySubdomain.php +++ b/src/Middleware/InitializeTenancyBySubdomain.php @@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Middleware; use Closure; use Exception; +use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Str; use Stancl\Tenancy\Exceptions\NotASubdomainException; @@ -21,15 +22,10 @@ class InitializeTenancyBySubdomain extends InitializeTenancyByDomain */ public static $subdomainIndex = 0; - /** @var callable|null */ - public static $onFail; + public static ?Closure $onFail = null; - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - */ - public function handle($request, Closure $next) + /** @return Response|mixed */ + public function handle(Request $request, Closure $next): mixed { $subdomain = $this->makeSubdomain($request->getHost()); diff --git a/src/Middleware/PreventAccessFromCentralDomains.php b/src/Middleware/PreventAccessFromCentralDomains.php index 14b2306d..40718730 100644 --- a/src/Middleware/PreventAccessFromCentralDomains.php +++ b/src/Middleware/PreventAccessFromCentralDomains.php @@ -11,12 +11,11 @@ class PreventAccessFromCentralDomains { /** * Set this property if you want to customize the on-fail behavior. - * - * @var callable|null */ - public static $abortRequest; + public static ?Closure $abortRequest; - public function handle(Request $request, Closure $next) + /** @return \Illuminate\Http\Response|mixed */ + public function handle(Request $request, Closure $next): mixed { if (in_array($request->getHost(), config('tenancy.central_domains'))) { $abortRequest = static::$abortRequest ?? function () { diff --git a/src/Middleware/ScopeSessions.php b/src/Middleware/ScopeSessions.php index 8abfcfe8..a72146d7 100644 --- a/src/Middleware/ScopeSessions.php +++ b/src/Middleware/ScopeSessions.php @@ -12,7 +12,8 @@ class ScopeSessions { public static $tenantIdKey = '_tenant_id'; - public function handle(Request $request, Closure $next) + /** @return \Illuminate\Http\Response|mixed */ + public function handle(Request $request, Closure $next): mixed { if (! tenancy()->initialized) { throw new TenancyNotInitializedException('Tenancy needs to be initialized before the session scoping middleware is executed'); diff --git a/src/Resolvers/Contracts/CachedTenantResolver.php b/src/Resolvers/Contracts/CachedTenantResolver.php index f93d7bb5..d4d5ba6e 100644 --- a/src/Resolvers/Contracts/CachedTenantResolver.php +++ b/src/Resolvers/Contracts/CachedTenantResolver.php @@ -65,7 +65,7 @@ abstract class CachedTenantResolver implements TenantResolver abstract public function resolveWithoutCache(mixed ...$args): Tenant; - public function resolved(Tenant $tenant, ...$args): void + public function resolved(Tenant $tenant, mixed ...$args): void { } diff --git a/src/Resolvers/DomainTenantResolver.php b/src/Resolvers/DomainTenantResolver.php index 926c02c0..d2970bb5 100644 --- a/src/Resolvers/DomainTenantResolver.php +++ b/src/Resolvers/DomainTenantResolver.php @@ -24,7 +24,6 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver { $domain = $args[0]; - /** @var Tenant|null $tenant */ $tenant = config('tenancy.tenant_model')::query() ->whereHas('domains', fn (Builder $query) => $query->where('domain', $domain)) ->with('domains') @@ -39,7 +38,7 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver throw new TenantCouldNotBeIdentifiedOnDomainException($args[0]); } - public function resolved(Tenant $tenant, ...$args): void + public function resolved(Tenant $tenant, mixed ...$args): void { $this->setCurrentDomain($tenant, $args[0]); } diff --git a/src/Resolvers/PathTenantResolver.php b/src/Resolvers/PathTenantResolver.php index 2ac2a59f..c98ac37e 100644 --- a/src/Resolvers/PathTenantResolver.php +++ b/src/Resolvers/PathTenantResolver.php @@ -23,7 +23,7 @@ class PathTenantResolver extends Contracts\CachedTenantResolver /** @var Route $route */ $route = $args[0]; - if ($id = $route->parameter(static::$tenantParameterName)) { + if ($id = (string) $route->parameter(static::$tenantParameterName)) { $route->forgetParameter(static::$tenantParameterName); if ($tenant = tenancy()->find($id)) { @@ -37,7 +37,7 @@ class PathTenantResolver extends Contracts\CachedTenantResolver public function getArgsForTenant(Tenant $tenant): array { return [ - [$tenant->id], + [$tenant->getTenantKey()], ]; } } diff --git a/src/Resolvers/RequestDataTenantResolver.php b/src/Resolvers/RequestDataTenantResolver.php index 5ed65495..8a5bbc53 100644 --- a/src/Resolvers/RequestDataTenantResolver.php +++ b/src/Resolvers/RequestDataTenantResolver.php @@ -17,7 +17,7 @@ class RequestDataTenantResolver extends Contracts\CachedTenantResolver public function resolveWithoutCache(mixed ...$args): Tenant { - $payload = $args[0]; + $payload = (string) $args[0]; if ($payload && $tenant = tenancy()->find($payload)) { return $tenant; @@ -29,7 +29,7 @@ class RequestDataTenantResolver extends Contracts\CachedTenantResolver public function getArgsForTenant(Tenant $tenant): array { return [ - [$tenant->id], + [$tenant->getTenantKey()], ]; } } diff --git a/src/UUIDGenerator.php b/src/UUIDGenerator.php index 736a6924..a0974862 100644 --- a/src/UUIDGenerator.php +++ b/src/UUIDGenerator.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Stancl\Tenancy; +use Illuminate\Database\Eloquent\Model; use Ramsey\Uuid\Uuid; use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator; @@ -11,7 +12,7 @@ use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator; class UUIDGenerator implements UniqueIdentifierGenerator { - public static function generate($resource): string + public static function generate(Model $model): string { return Uuid::uuid4()->toString(); } diff --git a/src/helpers.php b/src/helpers.php index ac805aa5..3f910a5b 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Stancl\Tenancy\CacheManager; use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Tenancy; @@ -35,6 +36,7 @@ if (! function_exists('tenant')) { if (! function_exists('tenant_asset')) { // todo docblock + // todo add an option to generate paths respecting the ASSET_URL function tenant_asset(string|null $asset): string { return route('stancl.tenancy.asset', ['path' => $asset]); @@ -42,16 +44,42 @@ if (! function_exists('tenant_asset')) { } if (! function_exists('global_asset')) { - function global_asset(string $asset) // todo types, also inside the globalUrl implementation + function global_asset(string $asset): string { return app('globalUrl')->asset($asset); } } if (! function_exists('global_cache')) { - function global_cache() + /** + * Get / set the specified cache value in the global cache store. + * + * If an array is passed, we'll assume you want to put to the cache. + * + * @param dynamic key|key,default|data,expiration|null + * @return mixed|\Illuminate\Cache\CacheManager + * + * @throws \InvalidArgumentException + */ + function global_cache(): mixed { - return app('globalCache'); + $arguments = func_get_args(); + + if (empty($arguments)) { + return app('globalCache'); + } + + if (is_string($arguments[0])) { + return app('globalCache')->get(...$arguments); + } + + if (!is_array($arguments[0])) { + throw new InvalidArgumentException( + 'When setting a value in the cache, you must pass an array of key / value pairs.' + ); + } + + return app('globalCache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1] ?? null); } } diff --git a/tests/DomainTest.php b/tests/DomainTest.php index 594270e1..6995da24 100644 --- a/tests/DomainTest.php +++ b/tests/DomainTest.php @@ -81,7 +81,7 @@ test('tenant can be identified by domain', function () { test('onfail logic can be customized', function () { InitializeTenancyByDomain::$onFail = function () { - return 'foo'; + return response('foo'); }; pest() diff --git a/tests/Etc/Tenant.php b/tests/Etc/Tenant.php index 20a96072..f20b0000 100644 --- a/tests/Etc/Tenant.php +++ b/tests/Etc/Tenant.php @@ -9,6 +9,9 @@ use Stancl\Tenancy\Database\Concerns\HasDatabase; use Stancl\Tenancy\Database\Concerns\HasDomains; use Stancl\Tenancy\Database\Models; +/** + * @method static static create(array $attributes = []) + */ class Tenant extends Models\Tenant implements TenantWithDatabase { use HasDatabase, HasDomains; diff --git a/tests/GlobalCacheTest.php b/tests/GlobalCacheTest.php index 8a13395c..ea38341b 100644 --- a/tests/GlobalCacheTest.php +++ b/tests/GlobalCacheTest.php @@ -50,3 +50,17 @@ test('global cache manager stores data in global cache', function () { expect(cache('def'))->toBe('ghi'); }); +test('the global_cache helper supports the same syntax as the cache helper', function () { + $tenant = Tenant::create(); + $tenant->enter(); + + expect(cache('foo'))->toBe(null); // tenant cache is empty + + global_cache(['foo' => 'bar']); + expect(global_cache('foo'))->toBe('bar'); + + global_cache()->set('foo', 'baz'); + expect(global_cache()->get('foo'))->toBe('baz'); + + expect(cache('foo'))->toBe(null); // tenant cache is not affected +}); diff --git a/tests/PathIdentificationTest.php b/tests/PathIdentificationTest.php index bfa8f8ad..517fa396 100644 --- a/tests/PathIdentificationTest.php +++ b/tests/PathIdentificationTest.php @@ -71,7 +71,7 @@ test('exception is thrown when tenant cannot be identified by path', function () test('onfail logic can be customized', function () { InitializeTenancyByPath::$onFail = function () { - return 'foo'; + return response('foo'); }; pest() diff --git a/tests/RequestDataIdentificationTest.php b/tests/RequestDataIdentificationTest.php index 81bdda53..e5a05f65 100644 --- a/tests/RequestDataIdentificationTest.php +++ b/tests/RequestDataIdentificationTest.php @@ -37,7 +37,6 @@ test('header identification works', function () { }); test('query parameter identification works', function () { - InitializeTenancyByRequestData::$header = null; InitializeTenancyByRequestData::$queryParameter = 'tenant'; $tenant = Tenant::create(); diff --git a/tests/SubdomainTest.php b/tests/SubdomainTest.php index 00096d8c..0ff52bc0 100644 --- a/tests/SubdomainTest.php +++ b/tests/SubdomainTest.php @@ -44,7 +44,7 @@ test('tenant can be identified by subdomain', function () { test('onfail logic can be customized', function () { InitializeTenancyBySubdomain::$onFail = function () { - return 'foo'; + return response('foo'); }; pest()