mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 07:04:03 +00:00
get down to 21 phpstan errors
This commit is contained in:
parent
a94227a19c
commit
f98a901aeb
16 changed files with 85 additions and 26 deletions
12
phpstan.neon
12
phpstan.neon
|
|
@ -31,6 +31,18 @@ parameters:
|
|||
message: '#PHPDoc tag \@param has invalid value \(dynamic#'
|
||||
paths:
|
||||
- src/helpers.php
|
||||
-
|
||||
message: '#Illuminate\\Routing\\UrlGenerator#'
|
||||
paths:
|
||||
- src/Bootstrappers/FilesystemTenancyBootstrapper.php
|
||||
-
|
||||
message: '#select\(\) expects string, Illuminate\\Database\\Query\\Expression given#'
|
||||
paths:
|
||||
- src/Database/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php
|
||||
-
|
||||
message: '#Trying to invoke Closure\|null but it might not be a callable#'
|
||||
paths:
|
||||
- src/Database/DatabaseConfig.php
|
||||
|
||||
checkMissingIterableValueType: false
|
||||
treatPhpDocTypesAsCertain: false
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class QueueTenancyBootstrapper implements TenancyBootstrapper
|
|||
tenancy()->initialize($tenant);
|
||||
}
|
||||
|
||||
protected static function revertToPreviousState($event, ?Tenant &$previousTenant): void
|
||||
protected static function revertToPreviousState(JobProcessed|JobFailed $event, ?Tenant &$previousTenant): void
|
||||
{
|
||||
$tenantId = $event->job->payload()['tenant_id'] ?? null;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class Down extends DownCommand
|
|||
|
||||
protected $description = 'Put tenants into maintenance mode.';
|
||||
|
||||
public function handle(): void
|
||||
public function handle(): int
|
||||
{
|
||||
// The base down command is heavily used. Instead of saving the data inside a file,
|
||||
// the data is stored the tenant database, which means some Laravel features
|
||||
|
|
@ -29,16 +29,18 @@ class Down extends DownCommand
|
|||
$payload = $this->getDownDatabasePayload();
|
||||
|
||||
// This runs for all tenants if no --tenants are specified
|
||||
tenancy()->runForMultiple($this->option('tenants'), function ($tenant) use ($payload) {
|
||||
tenancy()->runForMultiple($this->getTenants(), function ($tenant) use ($payload) {
|
||||
$this->line("Tenant: {$tenant['id']}");
|
||||
$tenant->putDownForMaintenance($payload);
|
||||
});
|
||||
|
||||
$this->comment('Tenants are now in maintenance mode.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Get the payload to be placed in the "down" file. */
|
||||
protected function getDownDatabasePayload()
|
||||
protected function getDownDatabasePayload(): array
|
||||
{
|
||||
return [
|
||||
'except' => $this->excludedPaths(),
|
||||
|
|
@ -46,7 +48,7 @@ class Down extends DownCommand
|
|||
'retry' => $this->getRetryTime(),
|
||||
'refresh' => $this->option('refresh'),
|
||||
'secret' => $this->option('secret'),
|
||||
'status' => (int) $this->option('status', 503),
|
||||
'status' => (int) ($this->option('status') ?? 503),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ class Link extends Command
|
|||
{
|
||||
CreateStorageSymlinksAction::handle(
|
||||
$tenants,
|
||||
$this->option('relative') ?? false,
|
||||
$this->option('force') ?? false,
|
||||
(bool) ($this->option('relative') ?? false),
|
||||
(bool) ($this->option('force') ?? false),
|
||||
);
|
||||
|
||||
$this->info('The links have been created.');
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Rollback extends RollbackCommand
|
|||
return 1;
|
||||
}
|
||||
|
||||
tenancy()->runForMultiple($this->option('tenants'), function ($tenant) {
|
||||
tenancy()->runForMultiple($this->getTenants(), function ($tenant) {
|
||||
$this->line("Tenant: {$tenant->getTenantKey()}");
|
||||
|
||||
event(new RollingBackDatabase($tenant));
|
||||
|
|
|
|||
|
|
@ -6,11 +6,14 @@ namespace Stancl\Tenancy\Commands;
|
|||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Stancl\Tenancy\Concerns\HasATenantsOption;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
class Run extends Command
|
||||
{
|
||||
use HasATenantsOption;
|
||||
|
||||
protected $description = 'Run a command for tenant(s)';
|
||||
|
||||
protected $signature = 'tenants:run {commandname : The artisan command.}
|
||||
|
|
@ -19,7 +22,8 @@ class Run extends Command
|
|||
public function handle(): void
|
||||
{
|
||||
$argvInput = $this->argvInput();
|
||||
tenancy()->runForMultiple($this->option('tenants'), function ($tenant) use ($argvInput) {
|
||||
|
||||
tenancy()->runForMultiple($this->getTenants(), function ($tenant) use ($argvInput) {
|
||||
$this->line("Tenant: {$tenant->getTenantKey()}");
|
||||
|
||||
$this->getLaravel()
|
||||
|
|
@ -30,12 +34,15 @@ class Run extends Command
|
|||
|
||||
protected function argvInput(): ArgvInput
|
||||
{
|
||||
/** @var string $commandname */
|
||||
$commandname = $this->argument('commandname');
|
||||
|
||||
// Convert string command to array
|
||||
$subCommand = explode(' ', $this->argument('commandname'));
|
||||
$subcommand = explode(' ', $commandname);
|
||||
|
||||
// Add "artisan" as first parameter because ArgvInput expects "artisan" as first parameter and later removes it
|
||||
array_unshift($subCommand, 'artisan');
|
||||
array_unshift($subcommand, 'artisan');
|
||||
|
||||
return new ArgvInput($subCommand);
|
||||
return new ArgvInput($subcommand);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class Seed extends SeedCommand
|
|||
return 1;
|
||||
}
|
||||
|
||||
tenancy()->runForMultiple($this->option('tenants'), function ($tenant) {
|
||||
tenancy()->runForMultiple($this->getTenants(), function ($tenant) {
|
||||
$this->line("Tenant: {$tenant->getTenantKey()}");
|
||||
|
||||
event(new SeedingDatabase($tenant));
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Contracts;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property-read Tenant $tenant
|
||||
*
|
||||
|
|
@ -15,5 +17,5 @@ namespace Stancl\Tenancy\Contracts;
|
|||
*/
|
||||
interface Domain
|
||||
{
|
||||
public function tenant();
|
||||
public function tenant(): BelongsTo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ abstract class TenantCannotBeCreatedException extends \Exception
|
|||
{
|
||||
abstract public function reason(): string;
|
||||
|
||||
/** @var string */
|
||||
protected $message;
|
||||
|
||||
public function __construct()
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace Stancl\Tenancy\Controllers;
|
|||
|
||||
use Closure;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Throwable;
|
||||
|
||||
class TenantAssetsController extends Controller // todo rename this to TenantAssetController & update references in docs
|
||||
|
|
@ -17,7 +18,10 @@ class TenantAssetsController extends Controller // todo rename this to TenantAss
|
|||
$this->middleware(static::$tenancyMiddleware);
|
||||
}
|
||||
|
||||
public function asset(string $path = null)
|
||||
/**
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function asset(string $path = null): BinaryFileResponse
|
||||
{
|
||||
abort_if($path === null, 404);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,5 +9,15 @@ use Stancl\Tenancy\Database\DatabaseConfig;
|
|||
|
||||
interface TenantWithDatabase extends Tenant
|
||||
{
|
||||
/** Get the tenant's database config. */
|
||||
public function database(): DatabaseConfig;
|
||||
|
||||
/** Get the internal prefix. */
|
||||
public static function internalPrefix(): string;
|
||||
|
||||
/** Get an internal key. */
|
||||
public function getInternal(string $key): mixed;
|
||||
|
||||
/** Set internal key. */
|
||||
public function setInternal(string $key, mixed $value): static;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class DatabaseConfig
|
|||
*/
|
||||
public function makeCredentials(): void
|
||||
{
|
||||
$this->tenant->setInternal('db_name', $this->getName() ?? (static::$databaseNameGenerator)($this->tenant));
|
||||
$this->tenant->setInternal('db_name', $this->getName());
|
||||
|
||||
if ($this->manager() instanceof Contracts\ManagesDatabaseUsers) {
|
||||
$this->tenant->setInternal('db_username', $this->getUsername() ?? (static::$usernameGenerator)($this->tenant));
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class TenantConfig implements Feature
|
|||
{
|
||||
public array $originalConfig = [];
|
||||
|
||||
/** @var array<string, string> */
|
||||
/** @var array<string, string|array> */
|
||||
public static array $storageToConfigMap = [
|
||||
// 'paypal_api_key' => 'services.paypal.api_key',
|
||||
];
|
||||
|
|
@ -30,7 +30,10 @@ class TenantConfig implements Feature
|
|||
public function bootstrap(Tenancy $tenancy): void
|
||||
{
|
||||
Event::listen(TenancyBootstrapped::class, function (TenancyBootstrapped $event) {
|
||||
$this->setTenantConfig($event->tenancy->tenant);
|
||||
/** @var Tenant $tenant */
|
||||
$tenant = $event->tenancy->tenant;
|
||||
|
||||
$this->setTenantConfig($tenant);
|
||||
});
|
||||
|
||||
Event::listen(RevertedToCentralContext::class, function () {
|
||||
|
|
@ -40,8 +43,8 @@ class TenantConfig implements Feature
|
|||
|
||||
public function setTenantConfig(Tenant $tenant): void
|
||||
{
|
||||
/** @var Tenant|Model $tenant */
|
||||
foreach (static::$storageToConfigMap as $storageKey => $configKey) {
|
||||
/** @var Tenant&Model $tenant */
|
||||
$override = Arr::get($tenant, $storageKey);
|
||||
|
||||
if (! is_null($override)) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Listeners;
|
||||
|
||||
use Stancl\Tenancy\Contracts\Tenant;
|
||||
use Stancl\Tenancy\Events\BootstrappingTenancy;
|
||||
use Stancl\Tenancy\Events\TenancyBootstrapped;
|
||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||
|
|
@ -15,7 +16,10 @@ class BootstrapTenancy
|
|||
event(new BootstrappingTenancy($event->tenancy));
|
||||
|
||||
foreach ($event->tenancy->getBootstrappers() as $bootstrapper) {
|
||||
$bootstrapper->bootstrap($event->tenancy->tenant);
|
||||
/** @var Tenant $tenant */
|
||||
$tenant = $event->tenancy->tenant;
|
||||
|
||||
$bootstrapper->bootstrap($tenant);
|
||||
}
|
||||
|
||||
event(new TenancyBootstrapped($event->tenancy));
|
||||
|
|
|
|||
|
|
@ -99,19 +99,30 @@ class Tenancy
|
|||
{
|
||||
$class = config('tenancy.tenant_model');
|
||||
|
||||
return new $class;
|
||||
/** @var Tenant&Model $model */
|
||||
$model = new $class;
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a tenant using an ID.
|
||||
*
|
||||
* @return (Tenant&Model)|null
|
||||
*/
|
||||
public static function find(int|string $id): Tenant|null
|
||||
{
|
||||
return static::model()->where(static::model()->getTenantKeyName(), $id)->first();
|
||||
/** @var (Tenant&Model)|null */
|
||||
$tenant = static::model()->where(static::model()->getTenantKeyName(), $id)->first();
|
||||
|
||||
return $tenant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a callback in the central context.
|
||||
* Atomic, safely reverts to previous context.
|
||||
*/
|
||||
public function central(Closure $callback)
|
||||
public function central(Closure $callback): mixed
|
||||
{
|
||||
$previousTenant = $this->tenant;
|
||||
|
||||
|
|
@ -132,7 +143,7 @@ class Tenancy
|
|||
* Run a callback for multiple tenants.
|
||||
* More performant than running $tenant->run() one by one.
|
||||
*
|
||||
* @param array<Tenant>|array<string>|\Traversable|null $tenants
|
||||
* @param array<Tenant>|array<string|int>|\Traversable|string|int|null $tenants
|
||||
*/
|
||||
public function runForMultiple($tenants, Closure $callback): void
|
||||
{
|
||||
|
|
@ -155,6 +166,7 @@ class Tenancy
|
|||
$tenant = $this->find($tenant);
|
||||
}
|
||||
|
||||
/** @var Tenant $tenant */
|
||||
$this->initialize($tenant);
|
||||
$callback($tenant);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\DatabaseManager;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
|
@ -201,8 +202,9 @@ test('run command with array of tenants works', function () {
|
|||
Artisan::call('tenants:migrate-fresh');
|
||||
|
||||
pest()->artisan("tenants:run --tenants=$tenantId1 --tenants=$tenantId2 'foo foo --b=bar --c=xyz'")
|
||||
->expectsOutput('Tenant: ' . $tenantId1)
|
||||
->expectsOutput('Tenant: ' . $tenantId2);
|
||||
->expectsOutputToContain('Tenant: ' . $tenantId1)
|
||||
->expectsOutputToContain('Tenant: ' . $tenantId2)
|
||||
->assertExitCode(0);
|
||||
});
|
||||
|
||||
test('link command works', function() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue