mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 12:24:04 +00:00
Refactor more old code and get tests to pass
This commit is contained in:
parent
c5377a16f7
commit
c32f229dd5
72 changed files with 425 additions and 531 deletions
|
|
@ -2,20 +2,36 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use Closure;
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
||||||
use Stancl\Tenancy\Events\DatabaseCreated;
|
use Stancl\Tenancy\Events\DatabaseCreated;
|
||||||
use Stancl\Tenancy\Events\DatabaseDeleted;
|
use Stancl\Tenancy\Events\DatabaseDeleted;
|
||||||
use Stancl\Tenancy\Events\DatabaseMigrated;
|
use Stancl\Tenancy\Events\DatabaseMigrated;
|
||||||
|
use Stancl\Tenancy\Events\DatabaseRolledBack;
|
||||||
use Stancl\Tenancy\Events\DatabaseSeeded;
|
use Stancl\Tenancy\Events\DatabaseSeeded;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Events\DomainCreated;
|
||||||
|
use Stancl\Tenancy\Events\DomainDeleted;
|
||||||
|
use Stancl\Tenancy\Events\DomainSaved;
|
||||||
|
use Stancl\Tenancy\Events\DomainUpdated;
|
||||||
|
use Stancl\Tenancy\Events\RevertedToCentralContext;
|
||||||
|
use Stancl\Tenancy\Events\TenancyBootstrapped;
|
||||||
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
use Stancl\Tenancy\Events\TenantDeleted;
|
use Stancl\Tenancy\Events\TenantDeleted;
|
||||||
|
use Stancl\Tenancy\Events\TenantSaved;
|
||||||
|
use Stancl\Tenancy\Events\TenantUpdated;
|
||||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||||
use Stancl\Tenancy\Jobs\DeleteDatabase;
|
use Stancl\Tenancy\Jobs\DeleteDatabase;
|
||||||
use Stancl\Tenancy\Jobs\MigrateDatabase;
|
use Stancl\Tenancy\Jobs\MigrateDatabase;
|
||||||
use Stancl\Tenancy\Jobs\SeedDatabase;
|
use Stancl\Tenancy\Jobs\SeedDatabase;
|
||||||
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
class TenancyServiceProvider extends ServiceProvider
|
class TenancyServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
@ -25,35 +41,82 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
TenantCreated::class => [
|
TenantCreated::class => [
|
||||||
JobPipeline::make([
|
JobPipeline::make([
|
||||||
CreateDatabase::class,
|
CreateDatabase::class,
|
||||||
MigrateDatabase::class, // triggers DatabaseMigrated event
|
MigrateDatabase::class,
|
||||||
SeedDatabase::class,
|
SeedDatabase::class,
|
||||||
|
|
||||||
|
// Your own jobs to prepare the tenant.
|
||||||
|
// Provision API keys, create S3 buckets, anything you want!
|
||||||
|
|
||||||
])->send(function (TenantCreated $event) {
|
])->send(function (TenantCreated $event) {
|
||||||
return $event->tenant;
|
return $event->tenant;
|
||||||
})->queue(true),
|
})->queue(false), // `false` by default, but you probably want to make this `true` for production.
|
||||||
],
|
],
|
||||||
DatabaseCreated::class => [],
|
TenantSaved::class => [],
|
||||||
DatabaseMigrated::class => [],
|
TenantUpdated::class => [],
|
||||||
DatabaseSeeded::class => [],
|
|
||||||
TenantDeleted::class => [
|
TenantDeleted::class => [
|
||||||
JobPipeline::make([
|
JobPipeline::make([
|
||||||
DeleteDatabase::class,
|
DeleteDatabase::class,
|
||||||
])->send(function (TenantDeleted $event) {
|
])->send(function (TenantDeleted $event) {
|
||||||
return $event->tenant;
|
return $event->tenant;
|
||||||
})->queue(true),
|
})->queue(false), // `false` by default, but you probably want to make this `true` for production.
|
||||||
// DeleteStorage::class,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
DomainCreated::class => [],
|
||||||
|
DomainSaved::class => [],
|
||||||
|
DomainUpdated::class => [],
|
||||||
|
DomainDeleted::class => [],
|
||||||
|
|
||||||
|
|
||||||
|
DatabaseCreated::class => [],
|
||||||
|
DatabaseMigrated::class => [],
|
||||||
|
DatabaseSeeded::class => [],
|
||||||
|
DatabaseRolledBack::class => [],
|
||||||
DatabaseDeleted::class => [],
|
DatabaseDeleted::class => [],
|
||||||
|
|
||||||
|
TenancyInitialized::class => [
|
||||||
|
BootstrapTenancy::class,
|
||||||
|
],
|
||||||
|
TenancyEnded::class => [
|
||||||
|
RevertToCentralContext::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
TenancyBootstrapped::class => [],
|
||||||
|
RevertedToCentralContext::class => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
//
|
// Make sure Tenancy is stateful.
|
||||||
|
$this->app->singleton(Tenancy::class);
|
||||||
|
|
||||||
|
// Make sure features are bootstrapped as soon as Tenancy is instantiated.
|
||||||
|
$this->app->extend(Tenancy::class, function (Tenancy $tenancy) {
|
||||||
|
foreach ($this->app['config']['tenancy.features'] as $feature) {
|
||||||
|
$this->app[$feature]->bootstrap($tenancy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tenancy;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make it possible to inject the current tenant by typehinting the Tenant contract.
|
||||||
|
$this->app->bind(Tenant::class, function ($app) {
|
||||||
|
return $app[Tenancy::class]->tenant;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure bootstrappers are stateful (singletons).
|
||||||
|
foreach ($this->app['config']['tenancy.bootstrappers'] as $bootstrapper) {
|
||||||
|
$this->app->singleton($bootstrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the class in the tenancy.id_generator config to the UniqueIdentifierGenerator abstract.
|
||||||
|
$this->app->bind(UniqueIdentifierGenerator::class, $this->app['config']['tenancy.id_generator']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
$this->bootEvents();
|
$this->bootEvents();
|
||||||
|
$this->mapRoutes();
|
||||||
|
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
@ -70,4 +133,15 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function mapRoutes()
|
||||||
|
{
|
||||||
|
$this->app->booted(function () {
|
||||||
|
if (file_exists(base_path('routes/tenant.php'))) {
|
||||||
|
Route::middleware(['web'])
|
||||||
|
->namespace($this->app['config']['tenancy.tenant_route_namespace'] ?? 'App\Http\Controllers')
|
||||||
|
->group(base_path('routes/tenant.php'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,23 +24,6 @@ return [
|
||||||
'localhost',
|
'localhost',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
'storage' => [
|
|
||||||
'data_column' => 'data',
|
|
||||||
'custom_columns' => [
|
|
||||||
// 'plan',
|
|
||||||
],
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Here you can enable the Cached Tenant Lookup.
|
|
||||||
*
|
|
||||||
* You can specify what cache store should be used to cache the tenant resolution.
|
|
||||||
* Set to string with a specific cache store name, or to null to disable cache.
|
|
||||||
*/
|
|
||||||
'cache_store' => null, // env('CACHE_DRIVER')
|
|
||||||
'cache_ttl' => 3600, // seconds
|
|
||||||
],
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller namespace used by routes in routes/tenant.php.
|
* Controller namespace used by routes in routes/tenant.php.
|
||||||
*/
|
*/
|
||||||
|
|
@ -76,7 +59,6 @@ return [
|
||||||
*/
|
*/
|
||||||
'prefix' => 'tenant',
|
'prefix' => 'tenant',
|
||||||
'suffix' => '',
|
'suffix' => '',
|
||||||
// todo get rid of this stuff, just set the closure instead
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -194,18 +176,11 @@ return [
|
||||||
* See the documentation page for each class to
|
* See the documentation page for each class to
|
||||||
* understand which ones you want to enable.
|
* understand which ones you want to enable.
|
||||||
*/
|
*/
|
||||||
'features' => [ // todo test features
|
'features' => [
|
||||||
// Stancl\Tenancy\Features\Timestamps::class, // https://tenancy.samuelstancl.me/docs/v2/features/timestamps/
|
|
||||||
// Stancl\Tenancy\Features\TenantConfig::class, // https://tenancy.samuelstancl.me/docs/v2/features/tenant-config/
|
// Stancl\Tenancy\Features\TenantConfig::class, // https://tenancy.samuelstancl.me/docs/v2/features/tenant-config/
|
||||||
// Stancl\Tenancy\Features\TelescopeTags::class, // https://tenancy.samuelstancl.me/docs/v2/telescope/
|
|
||||||
// Stancl\Tenancy\Features\CrossDomainRedirect::class, // https://tenancy.samuelstancl.me/docs/v2/features/tenant-redirect/
|
// Stancl\Tenancy\Features\CrossDomainRedirect::class, // https://tenancy.samuelstancl.me/docs/v2/features/tenant-redirect/
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL to which users will be redirected when they try to acceess a central route on a tenant domain.
|
|
||||||
*/
|
|
||||||
'home_url' => '/app', // todo move this to static
|
|
||||||
|
|
||||||
'migration_parameters' => [
|
'migration_parameters' => [
|
||||||
'--force' => true, // Set this to true to be able to run migrations in production
|
'--force' => true, // Set this to true to be able to run migrations in production
|
||||||
'--path' => [database_path('migrations/tenant')],
|
'--path' => [database_path('migrations/tenant')],
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,17 @@
|
||||||
|
|
|
|
||||||
| Here you can register the tenant routes for your application.
|
| Here you can register the tenant routes for your application.
|
||||||
| These routes are loaded by the TenantRouteServiceProvider
|
| These routes are loaded by the TenantRouteServiceProvider
|
||||||
| with the tenancy and web middleware groups. Good luck!
|
| with the namespace configured in your tenancy config.
|
||||||
|
|
|
||||||
|
| Feel free to customize them however you want. Good luck!
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::get('/app', function () {
|
Route::group([
|
||||||
return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
|
'middleware' => InitializeTenancyByDomain::class,
|
||||||
|
'prefix' => '/app',
|
||||||
|
], function () {
|
||||||
|
Route::get('/', function () {
|
||||||
|
return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -9,6 +9,7 @@ use Illuminate\Database\Console\Migrations\RollbackCommand;
|
||||||
use Illuminate\Database\Migrations\Migrator;
|
use Illuminate\Database\Migrations\Migrator;
|
||||||
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
||||||
use Stancl\Tenancy\DatabaseManager;
|
use Stancl\Tenancy\DatabaseManager;
|
||||||
|
use Stancl\Tenancy\Events\DatabaseRolledBack;
|
||||||
use Stancl\Tenancy\Traits\DealsWithMigrations;
|
use Stancl\Tenancy\Traits\DealsWithMigrations;
|
||||||
use Stancl\Tenancy\Traits\HasATenantsOption;
|
use Stancl\Tenancy\Traits\HasATenantsOption;
|
||||||
|
|
||||||
|
|
@ -62,7 +63,7 @@ class Rollback extends RollbackCommand
|
||||||
// Rollback
|
// Rollback
|
||||||
parent::handle();
|
parent::handle();
|
||||||
|
|
||||||
// todo DatabaseRolledBack event
|
event(new DatabaseRolledBack($tenant));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Contracts;
|
namespace Stancl\Tenancy\Contracts;
|
||||||
|
|
||||||
use Stancl\Tenancy\Facades\Tenancy;
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
/** Additional features, like Telescope tags and tenant redirects. */
|
/** Additional features, like Telescope tags and tenant redirects. */
|
||||||
interface Feature
|
interface Feature
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Contracts\Future;
|
|
||||||
|
|
||||||
use Stancl\Tenancy\Tenant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface will be part of the StorageDriver interface in 3.x.
|
|
||||||
*/
|
|
||||||
interface CanDeleteKeys
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Delete keys from the storage.
|
|
||||||
*
|
|
||||||
* @param string[] $keys
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function deleteMany(array $keys, Tenant $tenant = null): void;
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Contracts\Future;
|
|
||||||
|
|
||||||
use Stancl\Tenancy\Exceptions\TenantDoesNotExistException;
|
|
||||||
use Stancl\Tenancy\Tenant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface *might* be part of the StorageDriver interface in 3.x.
|
|
||||||
*/
|
|
||||||
interface CanFindByAnyKey
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Find a tenant using an arbitrary key.
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @param mixed $value
|
|
||||||
* @return Tenant
|
|
||||||
* @throws TenantDoesNotExistException
|
|
||||||
*/
|
|
||||||
public function findBy(string $key, $value): Tenant;
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Contracts\Future;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface *might* be part of the TenantDatabaseManager interface in 3.x.
|
|
||||||
*/
|
|
||||||
interface CanSetConnection
|
|
||||||
{
|
|
||||||
public function setConnection(string $connection): void;
|
|
||||||
}
|
|
||||||
|
|
@ -9,8 +9,7 @@ namespace Stancl\Tenancy\Contracts;
|
||||||
*/
|
*/
|
||||||
interface TenancyBootstrapper
|
interface TenancyBootstrapper
|
||||||
{
|
{
|
||||||
// todo rename methods
|
public function bootstrap(Tenant $tenant);
|
||||||
public function start(Tenant $tenant);
|
|
||||||
|
|
||||||
public function end();
|
public function revert();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,12 @@ interface TenantDatabaseManager
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function makeConnectionConfig(array $baseConfig, string $databaseName): array;
|
public function makeConnectionConfig(array $baseConfig, string $databaseName): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the DB connection that should be used by the tenant database manager.
|
||||||
|
*
|
||||||
|
* @param string $connection
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setConnection(string $connection): void;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Models\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
trait CentralConnection
|
trait CentralConnection
|
||||||
{
|
{
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Models\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
||||||
|
|
||||||
|
|
@ -14,4 +14,9 @@ trait GeneratesIds
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getIncrementing()
|
||||||
|
{
|
||||||
|
return ! app()->bound(UniqueIdentifierGenerator::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
// todo move namespace one dir above
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
namespace Stancl\Tenancy\Database\Models\Concerns;
|
|
||||||
|
|
||||||
// todo rename
|
|
||||||
trait HasADataColumn
|
trait HasADataColumn
|
||||||
{
|
{
|
||||||
public static $priorityListeners = [];
|
public static $priorityListeners = [];
|
||||||
|
|
@ -53,11 +51,17 @@ trait HasADataColumn
|
||||||
$model->dataEncodingStatus = 'decoded';
|
$model->dataEncodingStatus = 'decoded';
|
||||||
};
|
};
|
||||||
|
|
||||||
static::registerPriorityListener('retrieved', $decode);
|
static::registerPriorityListener('retrieved', function ($model) use ($decode) {
|
||||||
|
// We always decode after model retrieval.
|
||||||
|
$model->dataEncodingStatus = 'encoded';
|
||||||
|
|
||||||
|
$decode($model);
|
||||||
|
});
|
||||||
|
|
||||||
static::registerPriorityListener('saving', $encode);
|
static::registerPriorityListener('saving', $encode);
|
||||||
static::registerPriorityListener('creating', $encode);
|
static::registerPriorityListener('creating', $encode);
|
||||||
static::registerPriorityListener('updating', $encode);
|
static::registerPriorityListener('updating', $encode);
|
||||||
|
|
||||||
static::registerPriorityListener('saved', $decode);
|
static::registerPriorityListener('saved', $decode);
|
||||||
static::registerPriorityListener('created', $decode);
|
static::registerPriorityListener('created', $decode);
|
||||||
static::registerPriorityListener('updated', $decode);
|
static::registerPriorityListener('updated', $decode);
|
||||||
16
src/Database/Concerns/HasDomains.php
Normal file
16
src/Database/Concerns/HasDomains.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Contracts\Domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property-read Domain[] $domains
|
||||||
|
*/
|
||||||
|
trait HasDomains
|
||||||
|
{
|
||||||
|
public function domains()
|
||||||
|
{
|
||||||
|
return $this->hasMany(config('tenancy.domain_model'), 'tenant_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Models\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property-read string $primary_domain_hostname
|
* @property-read string $primary_domain_hostname
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Models\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
use Stancl\Tenancy\Contracts\Syncable;
|
use Stancl\Tenancy\Contracts\Syncable;
|
||||||
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Models\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
trait TenantConnection
|
trait TenantConnection
|
||||||
{
|
{
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Models\Concerns;
|
|
||||||
|
|
||||||
trait HasDomains
|
|
||||||
{
|
|
||||||
public function domains()
|
|
||||||
{
|
|
||||||
return $this->hasMany(config('tenancy.domain_model'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,18 +2,30 @@
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Models;
|
namespace Stancl\Tenancy\Database\Models;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Stancl\Tenancy\DatabaseConfig;
|
use Stancl\Tenancy\DatabaseConfig;
|
||||||
use Stancl\Tenancy\Events;
|
use Stancl\Tenancy\Events;
|
||||||
use Stancl\Tenancy\Contracts;
|
use Stancl\Tenancy\Contracts;
|
||||||
|
use Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
// todo @property
|
/**
|
||||||
class Tenant extends Model implements Contracts\TenantWithDatabase
|
* @property string|int $id
|
||||||
|
* @property Carbon $created_at
|
||||||
|
* @property Carbon $updated_at
|
||||||
|
* @property array $data
|
||||||
|
*/
|
||||||
|
class Tenant extends Model implements Contracts\TenantWithDatabase // todo base model that isn't TenantWithDatabase & domains
|
||||||
{
|
{
|
||||||
use Concerns\CentralConnection, Concerns\HasADataColumn, Concerns\GeneratesIds, Concerns\HasADataColumn {
|
use Concerns\CentralConnection,
|
||||||
|
Concerns\HasADataColumn,
|
||||||
|
Concerns\GeneratesIds,
|
||||||
|
Concerns\HasADataColumn,
|
||||||
|
Concerns\HasDomains {
|
||||||
Concerns\HasADataColumn::getCasts as dataColumnCasts;
|
Concerns\HasADataColumn::getCasts as dataColumnCasts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected $table = 'tenants';
|
||||||
public $primaryKey = 'id';
|
public $primaryKey = 'id';
|
||||||
public $guarded = [];
|
public $guarded = [];
|
||||||
|
|
||||||
|
|
@ -34,11 +46,6 @@ class Tenant extends Model implements Contracts\TenantWithDatabase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIncrementing()
|
|
||||||
{
|
|
||||||
return config('tenancy.id_generator') === null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function internalPrefix(): string
|
public static function internalPrefix(): string
|
||||||
{
|
{
|
||||||
return config('tenancy.internal_prefix');
|
return config('tenancy.internal_prefix');
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@ namespace Stancl\Tenancy;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
|
||||||
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
|
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
|
||||||
use Stancl\Tenancy\Contracts\ModifiesDatabaseNameForConnection;
|
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Exceptions\DatabaseManagerNotRegisteredException;
|
use Stancl\Tenancy\Exceptions\DatabaseManagerNotRegisteredException;
|
||||||
|
|
@ -79,6 +77,11 @@ class DatabaseConfig
|
||||||
return $this->tenant->getInternal('db_password') ?? null;
|
return $this->tenant->getInternal('db_password') ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate DB name, username & password and write them to the tenant model.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function makeCredentials(): void
|
public function makeCredentials(): void
|
||||||
{
|
{
|
||||||
$this->tenant->setInternal('db_name', $this->getName() ?? (static::$databaseNameGenerator)($this->tenant));
|
$this->tenant->setInternal('db_name', $this->getName() ?? (static::$databaseNameGenerator)($this->tenant));
|
||||||
|
|
@ -151,9 +154,7 @@ class DatabaseConfig
|
||||||
/** @var TenantDatabaseManager $databaseManager */
|
/** @var TenantDatabaseManager $databaseManager */
|
||||||
$databaseManager = app($databaseManagers[$driver]);
|
$databaseManager = app($databaseManagers[$driver]);
|
||||||
|
|
||||||
if ($databaseManager instanceof CanSetConnection) {
|
$databaseManager->setConnection($this->getTemplateConnectionName());
|
||||||
$databaseManager->setConnection($this->getTemplateConnectionName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $databaseManager;
|
return $databaseManager;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
src/Events/DatabaseRolledBack.php
Normal file
6
src/Events/DatabaseRolledBack.php
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Events;
|
||||||
|
|
||||||
|
class DatabaseRolledBack extends Contracts\TenantEvent
|
||||||
|
{}
|
||||||
16
src/Events/RevertedToCentralContext.php
Normal file
16
src/Events/RevertedToCentralContext.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Events;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
|
class RevertedToCentralContext
|
||||||
|
{
|
||||||
|
/** @var Tenancy */
|
||||||
|
public $tenancy;
|
||||||
|
|
||||||
|
public function __construct(Tenancy $tenancy)
|
||||||
|
{
|
||||||
|
$this->tenancy = $tenancy;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/Events/TenancyBootstrapped.php
Normal file
16
src/Events/TenancyBootstrapped.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Events;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
|
class TenancyBootstrapped
|
||||||
|
{
|
||||||
|
/** @var Tenancy */
|
||||||
|
public $tenancy;
|
||||||
|
|
||||||
|
public function __construct(Tenancy $tenancy)
|
||||||
|
{
|
||||||
|
$this->tenancy = $tenancy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,11 @@ declare(strict_types=1);
|
||||||
namespace Stancl\Tenancy\Facades;
|
namespace Stancl\Tenancy\Facades;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
use Stancl\Tenancy\TenantManager;
|
|
||||||
|
|
||||||
class Tenancy extends Facade
|
class Tenancy extends Facade
|
||||||
{
|
{
|
||||||
protected static function getFacadeAccessor()
|
protected static function getFacadeAccessor()
|
||||||
{
|
{
|
||||||
return TenantManager::class;
|
return \Stancl\Tenancy\Tenancy::class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Features;
|
|
||||||
|
|
||||||
use Laravel\Telescope\IncomingEntry;
|
|
||||||
use Laravel\Telescope\Telescope;
|
|
||||||
use Stancl\Tenancy\Contracts\Feature;
|
|
||||||
use Stancl\Tenancy\Middleware\PreventAccessFromTenantDomains;
|
|
||||||
use Stancl\Tenancy\Tenancy;
|
|
||||||
|
|
||||||
// todo rewrite this
|
|
||||||
class TelescopeTags implements Feature
|
|
||||||
{
|
|
||||||
/** @var callable User-specific callback that returns tags. */
|
|
||||||
protected $callback;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->callback = function ($entry) {
|
|
||||||
return [];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function bootstrap(Tenancy $tenancy): void
|
|
||||||
{
|
|
||||||
if (! class_exists(Telescope::class)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Telescope::tag(function (IncomingEntry $entry) {
|
|
||||||
$tags = $this->getTags($entry);
|
|
||||||
|
|
||||||
if (! request()->route()) {
|
|
||||||
return $tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo lines below
|
|
||||||
$tenantRoute = PreventAccessFromTenantDomains::routeHasMiddleware(request()->route(), 'tenancy')
|
|
||||||
|| PreventAccessFromTenantDomains::routeHasMiddleware(request()->route(), 'universal');
|
|
||||||
|
|
||||||
// Don't do anything if we're visiting a universal route on a central domain
|
|
||||||
if ($tenantRoute && tenancy()->initialized) {
|
|
||||||
$tags = array_merge($tags, [
|
|
||||||
'tenant:' . tenant('id'),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tags;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTags(IncomingEntry $entry): array
|
|
||||||
{
|
|
||||||
return ($this->callback)($entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCallback(callable $callback)
|
|
||||||
{
|
|
||||||
$this->callback = $callback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,12 +5,13 @@ declare(strict_types=1);
|
||||||
namespace Stancl\Tenancy\Features;
|
namespace Stancl\Tenancy\Features;
|
||||||
|
|
||||||
use Illuminate\Contracts\Config\Repository;
|
use Illuminate\Contracts\Config\Repository;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
use Stancl\Tenancy\Contracts\Feature;
|
use Stancl\Tenancy\Contracts\Feature;
|
||||||
|
use Stancl\Tenancy\Events\RevertedToCentralContext;
|
||||||
|
use Stancl\Tenancy\Events\TenancyBootstrapped;
|
||||||
use Stancl\Tenancy\Tenancy;
|
use Stancl\Tenancy\Tenancy;
|
||||||
use Stancl\Tenancy\Tenant;
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
use Stancl\Tenancy\TenantManager;
|
|
||||||
|
|
||||||
// todo rewrite this
|
|
||||||
class TenantConfig implements Feature
|
class TenantConfig implements Feature
|
||||||
{
|
{
|
||||||
/** @var Repository */
|
/** @var Repository */
|
||||||
|
|
@ -27,26 +28,26 @@ class TenantConfig implements Feature
|
||||||
{
|
{
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
|
||||||
foreach ($this->getStorageToConfigMap() as $configKey) {
|
foreach (static::$storageToConfigMap as $configKey) {
|
||||||
$this->originalConfig[$configKey] = $this->config[$configKey];
|
$this->originalConfig[$configKey] = $this->config[$configKey];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bootstrap(Tenancy $tenancy): void
|
public function bootstrap(Tenancy $tenancy): void
|
||||||
{
|
{
|
||||||
$tenantManager->eventListener('bootstrapped', function (TenantManager $manager) {
|
Event::listen(TenancyBootstrapped::class, function (TenancyBootstrapped $event) {
|
||||||
$this->setTenantConfig($manager->getTenant());
|
$this->setTenantConfig($event->tenancy->tenant);
|
||||||
});
|
});
|
||||||
|
|
||||||
$tenantManager->eventListener('ended', function () {
|
Event::listen(RevertedToCentralContext::class, function () {
|
||||||
$this->unsetTenantConfig();
|
$this->unsetTenantConfig();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTenantConfig(Tenant $tenant): void
|
public function setTenantConfig(Tenant $tenant): void
|
||||||
{
|
{
|
||||||
foreach ($this->getStorageToConfigMap() as $storageKey => $configKey) {
|
foreach (static::$storageToConfigMap as $storageKey => $configKey) {
|
||||||
$override = $tenant->data[$storageKey] ?? null;
|
$override = $tenant->$storageKey ?? null;
|
||||||
if (! is_null($override)) {
|
if (! is_null($override)) {
|
||||||
$this->config[$configKey] = $override;
|
$this->config[$configKey] = $override;
|
||||||
}
|
}
|
||||||
|
|
@ -55,13 +56,8 @@ class TenantConfig implements Feature
|
||||||
|
|
||||||
public function unsetTenantConfig(): void
|
public function unsetTenantConfig(): void
|
||||||
{
|
{
|
||||||
foreach ($this->getStorageToConfigMap() as $configKey) {
|
foreach (static::$storageToConfigMap as $configKey) {
|
||||||
$this->config[$configKey] = $this->originalConfig[$configKey];
|
$this->config[$configKey] = $this->originalConfig[$configKey];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStorageToConfigMap(): array
|
|
||||||
{
|
|
||||||
return static::$storageToConfigMap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Features;
|
|
||||||
|
|
||||||
use Illuminate\Config\Repository;
|
|
||||||
use Illuminate\Support\Facades\Date;
|
|
||||||
use Stancl\Tenancy\Contracts\Feature;
|
|
||||||
use Stancl\Tenancy\Tenant;
|
|
||||||
use Stancl\Tenancy\TenantManager;
|
|
||||||
|
|
||||||
// todo rewrite this
|
|
||||||
class Timestamps implements Feature
|
|
||||||
{
|
|
||||||
/** @var Repository */
|
|
||||||
protected $config;
|
|
||||||
|
|
||||||
public static $format = 'c'; // ISO 8601
|
|
||||||
|
|
||||||
public function __construct(Repository $config)
|
|
||||||
{
|
|
||||||
$this->config = $config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function bootstrap(TenantManager $tenantManager): void
|
|
||||||
{
|
|
||||||
$tenantManager->hook('tenant.creating', function ($tm, Tenant $tenant) {
|
|
||||||
$tenant->with('created_at', $this->now());
|
|
||||||
$tenant->with('updated_at', $this->now());
|
|
||||||
});
|
|
||||||
|
|
||||||
$tenantManager->hook('tenant.updating', function ($tm, Tenant $tenant) {
|
|
||||||
$tenant->with('updated_at', $this->now());
|
|
||||||
});
|
|
||||||
|
|
||||||
$tenantManager->hook('tenant.softDeleting', function ($tm, Tenant $tenant) {
|
|
||||||
$tenant->with('deleted_at', $this->now());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function now(): string
|
|
||||||
{
|
|
||||||
return Date::now()->format(static::$format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -12,6 +12,7 @@ use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
||||||
use Stancl\Tenancy\Contracts\Tenant;
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
|
use Stancl\Tenancy\Events\DatabaseCreated;
|
||||||
|
|
||||||
class CreateDatabase implements ShouldQueue
|
class CreateDatabase implements ShouldQueue
|
||||||
{
|
{
|
||||||
|
|
@ -30,6 +31,8 @@ class CreateDatabase implements ShouldQueue
|
||||||
if ($this->tenant->getInternal('create_database') !== false) {
|
if ($this->tenant->getInternal('create_database') !== false) {
|
||||||
$this->tenant->database()->makeCredentials();
|
$this->tenant->database()->makeCredentials();
|
||||||
$this->tenant->database()->manager()->createDatabase($this->tenant);
|
$this->tenant->database()->manager()->createDatabase($this->tenant);
|
||||||
|
|
||||||
|
event(new DatabaseCreated($this->tenant));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
|
use Stancl\Tenancy\Events\DatabaseDeleted;
|
||||||
|
|
||||||
class DeleteDatabase implements ShouldQueue
|
class DeleteDatabase implements ShouldQueue
|
||||||
{
|
{
|
||||||
|
|
@ -27,5 +28,7 @@ class DeleteDatabase implements ShouldQueue
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->tenant->database()->manager()->deleteDatabase($this->tenant);
|
$this->tenant->database()->manager()->deleteDatabase($this->tenant);
|
||||||
|
|
||||||
|
event(new DatabaseDeleted($this->tenant));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,8 @@ class MigrateDatabase implements ShouldQueue
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$migrationParameters = [
|
|
||||||
// todo ...
|
|
||||||
];
|
|
||||||
|
|
||||||
Artisan::call('tenants:migrate', [
|
Artisan::call('tenants:migrate', [
|
||||||
'--tenants' => [$this->tenant->id],
|
'--tenants' => [$this->tenant->id],
|
||||||
] + $migrationParameters);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Events\Listeners;
|
namespace Stancl\Tenancy\Listeners;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Events\TenancyBootstrapped;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
|
|
||||||
class BootstrapTenancy
|
class BootstrapTenancy
|
||||||
|
|
@ -9,7 +10,9 @@ class BootstrapTenancy
|
||||||
public function handle(TenancyInitialized $event)
|
public function handle(TenancyInitialized $event)
|
||||||
{
|
{
|
||||||
foreach ($event->tenancy->getBootstrappers() as $bootstrapper) {
|
foreach ($event->tenancy->getBootstrappers() as $bootstrapper) {
|
||||||
$bootstrapper->start($event->tenancy->tenant);
|
$bootstrapper->bootstrap($event->tenancy->tenant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event(new TenancyBootstrapped($event->tenancy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Events\Listeners;
|
namespace Stancl\Tenancy\Listeners;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
@ -8,7 +8,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
class JobPipeline implements ShouldQueue
|
class JobPipeline implements ShouldQueue
|
||||||
{
|
{
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public static $shouldBeQueuedByDefault = false;
|
public static $queueByDefault = false;
|
||||||
|
|
||||||
/** @var callable[]|string[] */
|
/** @var callable[]|string[] */
|
||||||
public $jobs;
|
public $jobs;
|
||||||
|
|
@ -22,16 +22,16 @@ class JobPipeline implements ShouldQueue
|
||||||
public $passable;
|
public $passable;
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $shouldBeQueued;
|
public $queue;
|
||||||
|
|
||||||
public function __construct($jobs, callable $send = null, bool $shouldBeQueued = null)
|
public function __construct($jobs, callable $send = null, bool $queue = null)
|
||||||
{
|
{
|
||||||
$this->jobs = $jobs;
|
$this->jobs = $jobs;
|
||||||
$this->send = $send ?? function ($event) {
|
$this->send = $send ?? function ($event) {
|
||||||
// If no $send callback is set, we'll just pass the event through the jobs.
|
// If no $send callback is set, we'll just pass the event through the jobs.
|
||||||
return $event;
|
return $event;
|
||||||
};
|
};
|
||||||
$this->shouldBeQueued = $shouldBeQueued ?? static::$shouldBeQueuedByDefault;
|
$this->queue = $queue ?? static::$queueByDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param callable[]|string[] $jobs */
|
/** @param callable[]|string[] $jobs */
|
||||||
|
|
@ -47,9 +47,9 @@ class JobPipeline implements ShouldQueue
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shouldBeQueued(bool $shouldBeQueued)
|
public function queue(bool $queue)
|
||||||
{
|
{
|
||||||
$this->shouldBeQueued = $shouldBeQueued;
|
$this->queue = $queue;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ class JobPipeline implements ShouldQueue
|
||||||
return function (...$args) {
|
return function (...$args) {
|
||||||
$executable = $this->executable($args);
|
$executable = $this->executable($args);
|
||||||
|
|
||||||
if ($this->shouldBeQueued) {
|
if ($this->queue) {
|
||||||
dispatch($executable);
|
dispatch($executable);
|
||||||
} else {
|
} else {
|
||||||
dispatch_now($executable);
|
dispatch_now($executable);
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Events\Listeners;
|
namespace Stancl\Tenancy\Listeners;
|
||||||
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Events\Listeners;
|
namespace Stancl\Tenancy\Listeners;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Events\RevertedToCentralContext;
|
||||||
use Stancl\Tenancy\Events\TenancyEnded;
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
|
|
||||||
class RevertToCentralContext
|
class RevertToCentralContext
|
||||||
|
|
@ -9,7 +10,9 @@ class RevertToCentralContext
|
||||||
public function handle(TenancyEnded $event)
|
public function handle(TenancyEnded $event)
|
||||||
{
|
{
|
||||||
foreach ($event->tenancy->getBootstrappers() as $bootstrapper) {
|
foreach ($event->tenancy->getBootstrappers() as $bootstrapper) {
|
||||||
$bootstrapper->end();
|
$bootstrapper->revert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event(new RevertedToCentralContext($event->tenancy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Events\Listeners;
|
namespace Stancl\Tenancy\Listeners;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||||
|
|
@ -9,7 +9,6 @@ use Illuminate\Http\Request;
|
||||||
use Stancl\Tenancy\Resolvers\RequestDataTenantResolver;
|
use Stancl\Tenancy\Resolvers\RequestDataTenantResolver;
|
||||||
use Stancl\Tenancy\Tenancy;
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
// todo write tests for this
|
|
||||||
class InitializeTenancyByRequestData extends IdentificationMiddleware
|
class InitializeTenancyByRequestData extends IdentificationMiddleware
|
||||||
{
|
{
|
||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class CacheTenancyBootstrapper implements TenancyBootstrapper
|
||||||
$this->app = $app;
|
$this->app = $app;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start(Tenant $tenant)
|
public function bootstrap(Tenant $tenant)
|
||||||
{
|
{
|
||||||
$this->resetFacadeCache();
|
$this->resetFacadeCache();
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ class CacheTenancyBootstrapper implements TenancyBootstrapper
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function end()
|
public function revert()
|
||||||
{
|
{
|
||||||
$this->resetFacadeCache();
|
$this->resetFacadeCache();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class DatabaseTenancyBootstrapper implements TenancyBootstrapper
|
||||||
$this->database = $database;
|
$this->database = $database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start(Tenant $tenant)
|
public function bootstrap(Tenant $tenant)
|
||||||
{
|
{
|
||||||
/** @var TenantWithDatabase $tenant */
|
/** @var TenantWithDatabase $tenant */
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ class DatabaseTenancyBootstrapper implements TenancyBootstrapper
|
||||||
$this->database->connectToTenant($tenant);
|
$this->database->connectToTenant($tenant);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function end()
|
public function revert()
|
||||||
{
|
{
|
||||||
$this->database->reconnectToCentral();
|
$this->database->reconnectToCentral();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class FilesystemTenancyBootstrapper implements TenancyBootstrapper
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start(Tenant $tenant)
|
public function bootstrap(Tenant $tenant)
|
||||||
{
|
{
|
||||||
$suffix = $this->app['config']['tenancy.filesystem.suffix_base'] . $tenant->getTenantKey();
|
$suffix = $this->app['config']['tenancy.filesystem.suffix_base'] . $tenant->getTenantKey();
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ class FilesystemTenancyBootstrapper implements TenancyBootstrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function end()
|
public function revert()
|
||||||
{
|
{
|
||||||
// storage_path()
|
// storage_path()
|
||||||
$this->app->useStoragePath($this->originalPaths['storage']);
|
$this->app->useStoragePath($this->originalPaths['storage']);
|
||||||
|
|
|
||||||
|
|
@ -67,12 +67,12 @@ class QueueTenancyBootstrapper implements TenancyBootstrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start(Tenant $tenant)
|
public function bootstrap(Tenant $tenant)
|
||||||
{
|
{
|
||||||
$this->tenancyInitialized = true;
|
$this->tenancyInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function end()
|
public function revert()
|
||||||
{
|
{
|
||||||
$this->tenancyInitialized = false;
|
$this->tenancyInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class RedisTenancyBootstrapper implements TenancyBootstrapper
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start(Tenant $tenant)
|
public function bootstrap(Tenant $tenant)
|
||||||
{
|
{
|
||||||
foreach ($this->prefixedConnections() as $connection) {
|
foreach ($this->prefixedConnections() as $connection) {
|
||||||
$prefix = $this->config['tenancy.redis.prefix_base'] . $tenant->getTenantKey();
|
$prefix = $this->config['tenancy.redis.prefix_base'] . $tenant->getTenantKey();
|
||||||
|
|
@ -33,7 +33,7 @@ class RedisTenancyBootstrapper implements TenancyBootstrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function end()
|
public function revert()
|
||||||
{
|
{
|
||||||
foreach ($this->prefixedConnections() as $connection) {
|
foreach ($this->prefixedConnections() as $connection) {
|
||||||
$client = Redis::connection($connection)->client();
|
$client = Redis::connection($connection)->client();
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
$this->mergeConfigFrom(__DIR__ . '/../assets/config.php', 'tenancy');
|
$this->mergeConfigFrom(__DIR__ . '/../assets/config.php', 'tenancy');
|
||||||
|
|
||||||
$this->app->bind(Contracts\UniqueIdentifierGenerator::class, $this->app['config']['tenancy.id_generator']);
|
|
||||||
$this->app->singleton(DatabaseManager::class);
|
$this->app->singleton(DatabaseManager::class);
|
||||||
$this->app->singleton(Tenancy::class);
|
|
||||||
$this->app->extend(Tenancy::class, function (Tenancy $tenancy) {
|
|
||||||
foreach ($this->app['config']['tenancy.features'] as $feature) {
|
|
||||||
$this->app[$feature]->bootstrap($tenancy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tenancy;
|
|
||||||
});
|
|
||||||
$this->app->bind(Tenant::class, function ($app) {
|
|
||||||
return $app[Tenancy::class]->tenant;
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach ($this->app['config']['tenancy.bootstrappers'] as $bootstrapper) {
|
|
||||||
$this->app->singleton($bootstrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->app->singleton(Commands\Migrate::class, function ($app) {
|
$this->app->singleton(Commands\Migrate::class, function ($app) {
|
||||||
return new Commands\Migrate($app['migrator'], $app[DatabaseManager::class]);
|
return new Commands\Migrate($app['migrator'], $app[DatabaseManager::class]);
|
||||||
|
|
@ -52,8 +36,6 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
$this->app->bind('globalCache', function ($app) {
|
$this->app->bind('globalCache', function ($app) {
|
||||||
return new CacheManager($app);
|
return new CacheManager($app);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->register(TenantRouteServiceProvider::class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,10 @@ namespace Stancl\Tenancy\TenantDatabaseManagers;
|
||||||
use Illuminate\Contracts\Config\Repository;
|
use Illuminate\Contracts\Config\Repository;
|
||||||
use Illuminate\Database\Connection;
|
use Illuminate\Database\Connection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
||||||
|
|
||||||
class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
class MySQLDatabaseManager implements TenantDatabaseManager
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,10 @@ namespace Stancl\Tenancy\TenantDatabaseManagers;
|
||||||
use Illuminate\Contracts\Config\Repository;
|
use Illuminate\Contracts\Config\Repository;
|
||||||
use Illuminate\Database\Connection;
|
use Illuminate\Database\Connection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
||||||
|
|
||||||
class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
class PostgreSQLDatabaseManager implements TenantDatabaseManager
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,10 @@ namespace Stancl\Tenancy\TenantDatabaseManagers;
|
||||||
use Illuminate\Contracts\Config\Repository;
|
use Illuminate\Contracts\Config\Repository;
|
||||||
use Illuminate\Database\Connection;
|
use Illuminate\Database\Connection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
use Stancl\Tenancy\Contracts\TenantWithDatabase;
|
||||||
|
|
||||||
class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection
|
class PostgreSQLSchemaManager implements TenantDatabaseManager
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
|
||||||
|
|
@ -38,4 +38,9 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
|
|
||||||
return $baseConfig;
|
return $baseConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setConnection(string $connection): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider;
|
|
||||||
use Illuminate\Support\Facades\Route;
|
|
||||||
|
|
||||||
class TenantRouteServiceProvider extends RouteServiceProvider
|
|
||||||
{
|
|
||||||
public function map()
|
|
||||||
{
|
|
||||||
$this->app->booted(function () {
|
|
||||||
if (file_exists(base_path('routes/tenant.php'))) {
|
|
||||||
Route::middleware(['web'])
|
|
||||||
->namespace($this->app['config']['tenancy.tenant_route_namespace'] ?? 'App\Http\Controllers')
|
|
||||||
->group(base_path('routes/tenant.php'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Traits;
|
namespace Stancl\Tenancy\Traits;
|
||||||
|
|
||||||
use Stancl\Tenancy\Tenant;
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
|
|
||||||
trait TenantAwareCommand
|
trait TenantAwareCommand
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Stancl\Tenancy\Contracts\TenancyBootstrapper;
|
use Stancl\Tenancy\Contracts\TenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\Listeners\RevertToCentralContext;
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
use Stancl\Tenancy\Events\TenancyEnded;
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
@ -8,9 +8,9 @@ use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\Listeners\RevertToCentralContext;
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
use Stancl\Tenancy\Events\TenancyEnded;
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\TenancyBootstrappers\CacheTenancyBootstrapper;
|
use Stancl\Tenancy\TenancyBootstrappers\CacheTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Stancl\Tenancy\Database\Models;
|
use Stancl\Tenancy\Database\Models;
|
||||||
use Stancl\Tenancy\Database\Models\Concerns\HasDomains;
|
use Stancl\Tenancy\Database\Concerns\HasDomains;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomainOrSubdomain;
|
use Stancl\Tenancy\Middleware\InitializeTenancyByDomainOrSubdomain;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ class CombinedDomainAndSubdomainIdentificationTest extends TestCase
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
config(['tenancy.tenant_model' => Tenant::class]);
|
config(['tenancy.tenant_model' => CombinedTenant::class]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
@ -30,7 +30,7 @@ class CombinedDomainAndSubdomainIdentificationTest extends TestCase
|
||||||
{
|
{
|
||||||
config(['tenancy.central_domains' => ['localhost']]);
|
config(['tenancy.central_domains' => ['localhost']]);
|
||||||
|
|
||||||
$tenant = Tenant::create([
|
$tenant = CombinedTenant::create([
|
||||||
'id' => 'acme',
|
'id' => 'acme',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ class CombinedDomainAndSubdomainIdentificationTest extends TestCase
|
||||||
{
|
{
|
||||||
config(['tenancy.central_domains' => []]);
|
config(['tenancy.central_domains' => []]);
|
||||||
|
|
||||||
$tenant = Tenant::create([
|
$tenant = CombinedTenant::create([
|
||||||
'id' => 'acme',
|
'id' => 'acme',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ class CombinedDomainAndSubdomainIdentificationTest extends TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tenant extends Models\Tenant
|
class CombinedTenant extends Models\Tenant
|
||||||
{
|
{
|
||||||
use HasDomains;
|
use HasDomains;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
@ -10,9 +10,9 @@ use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
use Stancl\Tenancy\Tests\Etc\ExampleSeeder;
|
use Stancl\Tenancy\Tests\Etc\ExampleSeeder;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\Listeners\RevertToCentralContext;
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
use Stancl\Tenancy\Events\TenancyEnded;
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticable;
|
use Illuminate\Foundation\Auth\User as Authenticable;
|
||||||
|
|
@ -8,7 +8,7 @@ use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||||
use Stancl\Tenancy\Jobs\MigrateDatabase;
|
use Stancl\Tenancy\Jobs\MigrateDatabase;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
|
|
@ -12,9 +12,12 @@ use Stancl\Tenancy\Exceptions\TenantDatabaseUserAlreadyExistsException;
|
||||||
use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager;
|
use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager;
|
||||||
use Stancl\Tenancy\TenantDatabaseManagers\PermissionControlledMySQLDatabaseManager;
|
use Stancl\Tenancy\TenantDatabaseManagers\PermissionControlledMySQLDatabaseManager;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||||
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
|
use Stancl\Tenancy\TenancyBootstrappers\DatabaseTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
||||||
class DatabaseUsersTest extends TestCase
|
class DatabaseUsersTest extends TestCase
|
||||||
|
|
@ -96,19 +99,20 @@ class DatabaseUsersTest extends TestCase
|
||||||
config([
|
config([
|
||||||
'tenancy.database_managers.mysql' => MySQLDatabaseManager::class,
|
'tenancy.database_managers.mysql' => MySQLDatabaseManager::class,
|
||||||
'tenancy.database.suffix' => '',
|
'tenancy.database.suffix' => '',
|
||||||
'tenancy.database.template_connection' => 'mysql',
|
'tenancy.template_tenant_connection' => 'mysql',
|
||||||
|
'tenancy.bootstrappers' => [
|
||||||
|
DatabaseTenancyBootstrapper::class,
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
|
|
||||||
$tenant = Tenant::create([
|
$tenant = Tenant::create([
|
||||||
'id' => 'foo' . Str::random(10),
|
'id' => 'foo' . Str::random(10),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertTrue($tenant->database()->manager() instanceof MySQLDatabaseManager);
|
$this->assertTrue($tenant->database()->manager() instanceof MySQLDatabaseManager);
|
||||||
|
|
||||||
$tenant = Tenant::create([
|
|
||||||
'id' => 'foo' . Str::random(10),
|
|
||||||
]);
|
|
||||||
|
|
||||||
tenancy()->initialize($tenant); // check if everything works
|
tenancy()->initialize($tenant); // check if everything works
|
||||||
tenancy()->end();
|
tenancy()->end();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Stancl\Tenancy\Database\Models;
|
use Stancl\Tenancy\Database\Models;
|
||||||
use Stancl\Tenancy\Database\Models\Concerns\HasDomains;
|
use Stancl\Tenancy\Database\Concerns\HasDomains;
|
||||||
use Stancl\Tenancy\Exceptions\DomainOccupiedByOtherTenantException;
|
use Stancl\Tenancy\Exceptions\DomainOccupiedByOtherTenantException;
|
||||||
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
|
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
||||||
|
|
@ -25,13 +25,13 @@ class DomainTest extends TestCase
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
config(['tenancy.tenant_model' => Tenant::class]);
|
config(['tenancy.tenant_model' => DomainTenant::class]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function tenant_can_be_identified_using_hostname()
|
public function tenant_can_be_identified_using_hostname()
|
||||||
{
|
{
|
||||||
$tenant = Tenant::create();
|
$tenant = DomainTenant::create();
|
||||||
|
|
||||||
$id = $tenant->id;
|
$id = $tenant->id;
|
||||||
|
|
||||||
|
|
@ -48,13 +48,13 @@ class DomainTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function a_domain_can_belong_to_only_one_tenant()
|
public function a_domain_can_belong_to_only_one_tenant()
|
||||||
{
|
{
|
||||||
$tenant = Tenant::create();
|
$tenant = DomainTenant::create();
|
||||||
|
|
||||||
$tenant->domains()->create([
|
$tenant->domains()->create([
|
||||||
'domain' => 'foo.localhost',
|
'domain' => 'foo.localhost',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tenant2 = Tenant::create();
|
$tenant2 = DomainTenant::create();
|
||||||
|
|
||||||
$this->expectException(DomainOccupiedByOtherTenantException::class);
|
$this->expectException(DomainOccupiedByOtherTenantException::class);
|
||||||
$tenant2->domains()->create([
|
$tenant2->domains()->create([
|
||||||
|
|
@ -73,7 +73,7 @@ class DomainTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function tenant_can_be_identified_by_domain()
|
public function tenant_can_be_identified_by_domain()
|
||||||
{
|
{
|
||||||
$tenant = Tenant::create([
|
$tenant = DomainTenant::create([
|
||||||
'id' => 'acme',
|
'id' => 'acme',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ class DomainTest extends TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tenant extends Models\Tenant
|
class DomainTenant extends Models\Tenant
|
||||||
{
|
{
|
||||||
use HasDomains;
|
use HasDomains;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
class CreateUsersTable extends Migration
|
class TestCreateUsersTable extends Migration
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Run the migrations.
|
* Run the migrations.
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{"foo":"bar"}
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Events\CallQueuedListener;
|
use Illuminate\Events\CallQueuedListener;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\QueueableListener;
|
use Stancl\Tenancy\Listeners\QueueableListener;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
||||||
|
|
@ -41,8 +41,6 @@ class EventListenerTest extends TestCase
|
||||||
|
|
||||||
$this->assertFalse(app()->bound('foo'));
|
$this->assertFalse(app()->bound('foo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo test that the way the published SP registers events works
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FooListener extends QueueableListener
|
class FooListener extends QueueableListener
|
||||||
|
|
|
||||||
|
|
@ -4,32 +4,39 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\Features;
|
namespace Stancl\Tenancy\Tests\Features;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Features\TenantConfig;
|
use Stancl\Tenancy\Features\TenantConfig;
|
||||||
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
||||||
class TenantConfigTest extends TestCase
|
class TenantConfigTest extends TestCase
|
||||||
{
|
{
|
||||||
public $autoInitTenancy = false;
|
|
||||||
public $autoCreateTenant = false;
|
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function config_is_merged_and_removed()
|
public function config_is_merged_and_removed()
|
||||||
{
|
{
|
||||||
$this->assertSame(null, config('services.paypal'));
|
$this->assertSame(null, config('services.paypal'));
|
||||||
config([
|
config([
|
||||||
'tenancy.features' => [TenantConfig::class],
|
'tenancy.features' => [TenantConfig::class],
|
||||||
|
'tenancy.bootstrappers' => [],
|
||||||
]);
|
]);
|
||||||
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
|
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
|
||||||
|
|
||||||
TenantConfig::$storageToConfigMap = [
|
TenantConfig::$storageToConfigMap = [
|
||||||
'paypal_api_public' => 'services.paypal.public',
|
'paypal_api_public' => 'services.paypal.public',
|
||||||
'paypal_api_private' => 'services.paypal.private',
|
'paypal_api_private' => 'services.paypal.private',
|
||||||
];
|
];
|
||||||
|
|
||||||
tenancy()->create('foo.localhost', [
|
$tenant = Tenant::create([
|
||||||
'paypal_api_public' => 'foo',
|
'paypal_api_public' => 'foo',
|
||||||
'paypal_api_private' => 'bar',
|
'paypal_api_private' => 'bar',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
tenancy()->init('foo.localhost');
|
tenancy()->initialize($tenant);
|
||||||
$this->assertSame(['public' => 'foo', 'private' => 'bar'], config('services.paypal'));
|
$this->assertSame(['public' => 'foo', 'private' => 'bar'], config('services.paypal'));
|
||||||
|
|
||||||
tenancy()->end();
|
tenancy()->end();
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\Features;
|
|
||||||
|
|
||||||
use Stancl\Tenancy\Features\Timestamps;
|
|
||||||
use Stancl\Tenancy\Tenant;
|
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
|
||||||
|
|
||||||
class TimestampTest extends TestCase
|
|
||||||
{
|
|
||||||
public $autoCreateTenant = false;
|
|
||||||
public $autoInitTenancy = false;
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
config(['tenancy.features' => [
|
|
||||||
Timestamps::class,
|
|
||||||
]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @test */
|
|
||||||
public function create_and_update_timestamps_are_added_on_create()
|
|
||||||
{
|
|
||||||
$tenant = Tenant::new()->save();
|
|
||||||
$this->assertArrayHasKey('created_at', $tenant->data);
|
|
||||||
$this->assertArrayHasKey('updated_at', $tenant->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @test */
|
|
||||||
public function update_timestamps_are_added()
|
|
||||||
{
|
|
||||||
$tenant = Tenant::new()->save();
|
|
||||||
$this->assertSame($tenant->created_at, $tenant->updated_at);
|
|
||||||
$this->assertSame('string', gettype($tenant->created_at));
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
$tenant->put('abc', 'def');
|
|
||||||
|
|
||||||
$this->assertTrue($tenant->updated_at > $tenant->created_at);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @test */
|
|
||||||
public function softdelete_timestamps_are_added()
|
|
||||||
{
|
|
||||||
$tenant = Tenant::new()->save();
|
|
||||||
$this->assertNull($tenant->deleted_at);
|
|
||||||
|
|
||||||
$tenant->softDelete();
|
|
||||||
$this->assertNotNull($tenant->deleted_at);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Stancl\Tenancy\Facades\GlobalCache;
|
use Stancl\Tenancy\Facades\GlobalCache;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\TenancyBootstrappers\CacheTenancyBootstrapper;
|
use Stancl\Tenancy\TenancyBootstrappers\CacheTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use Spatie\Valuestore\Valuestore;
|
use Spatie\Valuestore\Valuestore;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ class JobPipelineTest extends TestCase
|
||||||
|
|
||||||
config(['queue.default' => 'redis']);
|
config(['queue.default' => 'redis']);
|
||||||
|
|
||||||
$this->valuestore = Valuestore::make(__DIR__ . '/../Etc/tmp/jobpipelinetest.json')->flush();
|
$this->valuestore = Valuestore::make(__DIR__ . '/Etc/tmp/jobpipelinetest.json')->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
@ -51,7 +51,7 @@ class JobPipelineTest extends TestCase
|
||||||
FooJob::class,
|
FooJob::class,
|
||||||
])->send(function () {
|
])->send(function () {
|
||||||
return $this->valuestore;
|
return $this->valuestore;
|
||||||
})->shouldBeQueued(true)->toListener());
|
})->queue(true)->toListener());
|
||||||
|
|
||||||
Queue::assertNothingPushed();
|
Queue::assertNothingPushed();
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ class JobPipelineTest extends TestCase
|
||||||
FooJob::class,
|
FooJob::class,
|
||||||
])->send(function () {
|
])->send(function () {
|
||||||
return $this->valuestore;
|
return $this->valuestore;
|
||||||
})->shouldBeQueued(true)->toListener());
|
})->queue(true)->toListener());
|
||||||
|
|
||||||
$this->assertFalse($this->valuestore->has('foo'));
|
$this->assertFalse($this->valuestore->has('foo'));
|
||||||
Tenant::create();
|
Tenant::create();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
@ -11,7 +11,7 @@ use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Spatie\Valuestore\Valuestore;
|
use Spatie\Valuestore\Valuestore;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\TenancyBootstrappers\QueueTenancyBootstrapper;
|
use Stancl\Tenancy\TenancyBootstrappers\QueueTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
@ -36,17 +36,19 @@ class QueueTest extends TestCase
|
||||||
|
|
||||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
|
|
||||||
$this->valuestore = Valuestore::make(__DIR__ . '/../Etc/tmp/queuetest.json')->flush();
|
$this->valuestore = Valuestore::make(__DIR__ . '/Etc/tmp/queuetest.json')->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function tenant_id_is_passed_to_tenant_queues()
|
public function tenant_id_is_passed_to_tenant_queues()
|
||||||
{
|
{
|
||||||
|
config(['queue.default' => 'sync']);
|
||||||
|
|
||||||
$tenant = Tenant::create();
|
$tenant = Tenant::create();
|
||||||
|
|
||||||
tenancy()->initialize($tenant);
|
tenancy()->initialize($tenant);
|
||||||
|
|
||||||
Event::fake();
|
Event::fake([JobProcessing::class]);
|
||||||
|
|
||||||
dispatch(new TestJob($this->valuestore));
|
dispatch(new TestJob($this->valuestore));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use Stancl\Tenancy\Contracts\Syncable;
|
use Stancl\Tenancy\Contracts\Syncable;
|
||||||
use Stancl\Tenancy\Contracts\SyncMaster;
|
use Stancl\Tenancy\Contracts\SyncMaster;
|
||||||
use Stancl\Tenancy\Database\Models\Concerns\CentralConnection;
|
use Stancl\Tenancy\Database\Concerns\CentralConnection;
|
||||||
use Stancl\Tenancy\Database\Models\Concerns\ResourceSyncing;
|
use Stancl\Tenancy\Database\Concerns\ResourceSyncing;
|
||||||
use Stancl\Tenancy\Database\Models;
|
use Stancl\Tenancy\Database\Models;
|
||||||
use Stancl\Tenancy\Database\Models\TenantPivot;
|
use Stancl\Tenancy\Database\Models\TenantPivot;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\Listeners\RevertToCentralContext;
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
use Stancl\Tenancy\Events\Listeners\UpdateSyncedResource;
|
use Stancl\Tenancy\Listeners\UpdateSyncedResource;
|
||||||
use Stancl\Tenancy\Events\SyncedResourceChangedInForeignDatabase;
|
use Stancl\Tenancy\Events\SyncedResourceChangedInForeignDatabase;
|
||||||
use Stancl\Tenancy\Events\SyncedResourceSaved;
|
use Stancl\Tenancy\Events\SyncedResourceSaved;
|
||||||
use Stancl\Tenancy\Events\TenancyEnded;
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
|
|
@ -49,8 +49,8 @@ class ResourceSyncingTest extends TestCase
|
||||||
|
|
||||||
$this->artisan('migrate', [
|
$this->artisan('migrate', [
|
||||||
'--path' => [
|
'--path' => [
|
||||||
__DIR__ . '/../Etc/synced_resource_migrations',
|
__DIR__ . '/Etc/synced_resource_migrations',
|
||||||
__DIR__ . '/../Etc/synced_resource_migrations/users'
|
__DIR__ . '/Etc/synced_resource_migrations/users'
|
||||||
],
|
],
|
||||||
'--realpath' => true,
|
'--realpath' => true,
|
||||||
])->assertExitCode(0);
|
])->assertExitCode(0);
|
||||||
|
|
@ -59,7 +59,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
protected function migrateTenants()
|
protected function migrateTenants()
|
||||||
{
|
{
|
||||||
$this->artisan('tenants:migrate', [
|
$this->artisan('tenants:migrate', [
|
||||||
'--path' => __DIR__ . '/../Etc/synced_resource_migrations/users',
|
'--path' => __DIR__ . '/Etc/synced_resource_migrations/users',
|
||||||
'--realpath' => true,
|
'--realpath' => true,
|
||||||
])->assertExitCode(0);
|
])->assertExitCode(0);
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
{
|
{
|
||||||
Event::fake([SyncedResourceSaved::class]);
|
Event::fake([SyncedResourceSaved::class]);
|
||||||
|
|
||||||
$user = User::create([
|
$user = ResourceUser::create([
|
||||||
'name' => 'Foo',
|
'name' => 'Foo',
|
||||||
'email' => 'foo@email.com',
|
'email' => 'foo@email.com',
|
||||||
'password' => 'secret',
|
'password' => 'secret',
|
||||||
|
|
@ -94,13 +94,13 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'superadmin', // unsynced
|
'role' => 'superadmin', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tenant = Tenant::create();
|
$tenant = ResourceTenant::create();
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
||||||
tenancy()->initialize($tenant);
|
tenancy()->initialize($tenant);
|
||||||
|
|
||||||
// Create the same user in tenant DB
|
// Create the same user in tenant DB
|
||||||
$user = User::create([
|
$user = ResourceUser::create([
|
||||||
'global_id' => 'acme',
|
'global_id' => 'acme',
|
||||||
'name' => 'John Doe',
|
'name' => 'John Doe',
|
||||||
'email' => 'john@localhost',
|
'email' => 'john@localhost',
|
||||||
|
|
@ -135,22 +135,22 @@ class ResourceSyncingTest extends TestCase
|
||||||
'email' => 'john@foreignhost', // synced
|
'email' => 'john@foreignhost', // synced
|
||||||
'password' => 'secret', // no changes
|
'password' => 'secret', // no changes
|
||||||
'role' => 'superadmin', // unsynced
|
'role' => 'superadmin', // unsynced
|
||||||
], User::first()->getAttributes());
|
], ResourceUser::first()->getAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function creating_the_resource_in_tenant_database_creates_it_in_central_database_and_creates_the_mapping()
|
public function creating_the_resource_in_tenant_database_creates_it_in_central_database_and_creates_the_mapping()
|
||||||
{
|
{
|
||||||
// Assert no user in central DB
|
// Assert no user in central DB
|
||||||
$this->assertCount(0, User::all());
|
$this->assertCount(0, ResourceUser::all());
|
||||||
|
|
||||||
$tenant = Tenant::create();
|
$tenant = ResourceTenant::create();
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
||||||
tenancy()->initialize($tenant);
|
tenancy()->initialize($tenant);
|
||||||
|
|
||||||
// Create the same user in tenant DB
|
// Create the same user in tenant DB
|
||||||
User::create([
|
ResourceUser::create([
|
||||||
'global_id' => 'acme',
|
'global_id' => 'acme',
|
||||||
'name' => 'John Doe',
|
'name' => 'John Doe',
|
||||||
'email' => 'john@localhost',
|
'email' => 'john@localhost',
|
||||||
|
|
@ -170,7 +170,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
// Assert role change doesn't cascade
|
// Assert role change doesn't cascade
|
||||||
CentralUser::first()->update(['role' => 'central superadmin']);
|
CentralUser::first()->update(['role' => 'central superadmin']);
|
||||||
tenancy()->initialize($tenant);
|
tenancy()->initialize($tenant);
|
||||||
$this->assertSame('commenter', User::first()->role);
|
$this->assertSame('commenter', ResourceUser::first()->role);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
@ -182,7 +182,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
$this->assertFalse(tenancy()->initialized);
|
$this->assertFalse(tenancy()->initialized);
|
||||||
|
|
||||||
$this->expectException(ModelNotSyncMaster::class);
|
$this->expectException(ModelNotSyncMaster::class);
|
||||||
User::first()->update(['role' => 'foobar']);
|
ResourceUser::first()->update(['role' => 'foobar']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
@ -196,19 +196,19 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'commenter', // unsynced
|
'role' => 'commenter', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tenant = Tenant::create([
|
$tenant = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
||||||
$tenant->run(function () {
|
$tenant->run(function () {
|
||||||
$this->assertCount(0, User::all());
|
$this->assertCount(0, ResourceUser::all());
|
||||||
});
|
});
|
||||||
|
|
||||||
$centralUser->tenants()->attach('t1');
|
$centralUser->tenants()->attach('t1');
|
||||||
|
|
||||||
$tenant->run(function () {
|
$tenant->run(function () {
|
||||||
$this->assertCount(1, User::all());
|
$this->assertCount(1, ResourceUser::all());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,13 +223,13 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'commenter', // unsynced
|
'role' => 'commenter', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tenant = Tenant::create([
|
$tenant = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
||||||
$tenant->run(function () {
|
$tenant->run(function () {
|
||||||
$this->assertCount(0, User::all());
|
$this->assertCount(0, ResourceUser::all());
|
||||||
});
|
});
|
||||||
|
|
||||||
// The child model is inaccessible in the Pivot Model, so we can't fire any events.
|
// The child model is inaccessible in the Pivot Model, so we can't fire any events.
|
||||||
|
|
@ -237,7 +237,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
|
|
||||||
$tenant->run(function () {
|
$tenant->run(function () {
|
||||||
// Still zero
|
// Still zero
|
||||||
$this->assertCount(0, User::all());
|
$this->assertCount(0, ResourceUser::all());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,15 +252,15 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'commenter', // unsynced
|
'role' => 'commenter', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$t1 = Tenant::create([
|
$t1 = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$t2 = Tenant::create([
|
$t2 = ResourceTenant::create([
|
||||||
'id' => 't2',
|
'id' => 't2',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$t3 = Tenant::create([
|
$t3 = ResourceTenant::create([
|
||||||
'id' => 't3',
|
'id' => 't3',
|
||||||
]);
|
]);
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
@ -271,17 +271,17 @@ class ResourceSyncingTest extends TestCase
|
||||||
|
|
||||||
$t1->run(function () {
|
$t1->run(function () {
|
||||||
// assert user exists
|
// assert user exists
|
||||||
$this->assertCount(1, User::all());
|
$this->assertCount(1, ResourceUser::all());
|
||||||
});
|
});
|
||||||
|
|
||||||
$t2->run(function () {
|
$t2->run(function () {
|
||||||
// assert user exists
|
// assert user exists
|
||||||
$this->assertCount(1, User::all());
|
$this->assertCount(1, ResourceUser::all());
|
||||||
});
|
});
|
||||||
|
|
||||||
$t3->run(function () {
|
$t3->run(function () {
|
||||||
// assert user does NOT exist
|
// assert user does NOT exist
|
||||||
$this->assertCount(0, User::all());
|
$this->assertCount(0, ResourceUser::all());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,10 +297,10 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'commenter', // unsynced
|
'role' => 'commenter', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$t1 = Tenant::create([
|
$t1 = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
$t2 = Tenant::create([
|
$t2 = ResourceTenant::create([
|
||||||
'id' => 't2',
|
'id' => 't2',
|
||||||
]);
|
]);
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
@ -310,7 +310,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
|
|
||||||
$t2->run(function () {
|
$t2->run(function () {
|
||||||
// Create user with the same global ID in t2 database
|
// Create user with the same global ID in t2 database
|
||||||
User::create([
|
ResourceUser::create([
|
||||||
'global_id' => 'acme',
|
'global_id' => 'acme',
|
||||||
'name' => 'John Foo', // changed
|
'name' => 'John Foo', // changed
|
||||||
'email' => 'john@foo', // changed
|
'email' => 'john@foo', // changed
|
||||||
|
|
@ -325,7 +325,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
$this->assertSame('commenter', $centralUser->role); // role didn't change
|
$this->assertSame('commenter', $centralUser->role); // role didn't change
|
||||||
|
|
||||||
$t1->run(function () {
|
$t1->run(function () {
|
||||||
$user = User::first();
|
$user = ResourceUser::first();
|
||||||
$this->assertSame('John Foo', $user->name); // name changed
|
$this->assertSame('John Foo', $user->name); // name changed
|
||||||
$this->assertSame('john@foo', $user->email); // email changed
|
$this->assertSame('john@foo', $user->email); // email changed
|
||||||
$this->assertSame('commenter', $user->role); // role didn't change, i.e. is the same as from the original copy from central
|
$this->assertSame('commenter', $user->role); // role didn't change, i.e. is the same as from the original copy from central
|
||||||
|
|
@ -344,13 +344,13 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'commenter', // unsynced
|
'role' => 'commenter', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$t1 = Tenant::create([
|
$t1 = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
$t2 = Tenant::create([
|
$t2 = ResourceTenant::create([
|
||||||
'id' => 't2',
|
'id' => 't2',
|
||||||
]);
|
]);
|
||||||
$t3 = Tenant::create([
|
$t3 = ResourceTenant::create([
|
||||||
'id' => 't3',
|
'id' => 't3',
|
||||||
]);
|
]);
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
@ -361,17 +361,17 @@ class ResourceSyncingTest extends TestCase
|
||||||
$centralUser->tenants()->attach('t3');
|
$centralUser->tenants()->attach('t3');
|
||||||
|
|
||||||
$t3->run(function () {
|
$t3->run(function () {
|
||||||
User::first()->update([
|
ResourceUser::first()->update([
|
||||||
'name' => 'John 3',
|
'name' => 'John 3',
|
||||||
'role' => 'employee', // unsynced
|
'role' => 'employee', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertSame('employee', User::first()->role);
|
$this->assertSame('employee', ResourceUser::first()->role);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check that change was cascaded to other tenants
|
// Check that change was cascaded to other tenants
|
||||||
$t1->run($check = function () {
|
$t1->run($check = function () {
|
||||||
$user = User::first();
|
$user = ResourceUser::first();
|
||||||
|
|
||||||
$this->assertSame('John 3', $user->name); // synced
|
$this->assertSame('John 3', $user->name); // synced
|
||||||
$this->assertSame('commenter', $user->role); // unsynced
|
$this->assertSame('commenter', $user->role); // unsynced
|
||||||
|
|
@ -408,7 +408,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'employee',
|
'role' => 'employee',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$t1 = Tenant::create([
|
$t1 = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -417,21 +417,21 @@ class ResourceSyncingTest extends TestCase
|
||||||
$centralUser->tenants()->attach('t1');
|
$centralUser->tenants()->attach('t1');
|
||||||
|
|
||||||
$t1->run(function () {
|
$t1->run(function () {
|
||||||
$this->assertSame('employee', User::first()->role);
|
$this->assertSame('employee', ResourceUser::first()->role);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function when_the_resource_doesnt_exist_in_the_central_db_non_synced_columns_will_bubble_up_too()
|
public function when_the_resource_doesnt_exist_in_the_central_db_non_synced_columns_will_bubble_up_too()
|
||||||
{
|
{
|
||||||
$t1 = Tenant::create([
|
$t1 = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
||||||
$t1->run(function () {
|
$t1->run(function () {
|
||||||
User::create([
|
ResourceUser::create([
|
||||||
'name' => 'John Doe',
|
'name' => 'John Doe',
|
||||||
'email' => 'john@doe',
|
'email' => 'john@doe',
|
||||||
'password' => 'secret',
|
'password' => 'secret',
|
||||||
|
|
@ -448,7 +448,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
UpdateSyncedResource::$shouldQueue = true;
|
UpdateSyncedResource::$shouldQueue = true;
|
||||||
|
|
||||||
$t1 = Tenant::create([
|
$t1 = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -457,7 +457,7 @@ class ResourceSyncingTest extends TestCase
|
||||||
Queue::assertNothingPushed();
|
Queue::assertNothingPushed();
|
||||||
|
|
||||||
$t1->run(function () {
|
$t1->run(function () {
|
||||||
User::create([
|
ResourceUser::create([
|
||||||
'name' => 'John Doe',
|
'name' => 'John Doe',
|
||||||
'email' => 'john@doe',
|
'email' => 'john@doe',
|
||||||
'password' => 'secret',
|
'password' => 'secret',
|
||||||
|
|
@ -484,13 +484,13 @@ class ResourceSyncingTest extends TestCase
|
||||||
'role' => 'commenter', // unsynced
|
'role' => 'commenter', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$t1 = Tenant::create([
|
$t1 = ResourceTenant::create([
|
||||||
'id' => 't1',
|
'id' => 't1',
|
||||||
]);
|
]);
|
||||||
$t2 = Tenant::create([
|
$t2 = ResourceTenant::create([
|
||||||
'id' => 't2',
|
'id' => 't2',
|
||||||
]);
|
]);
|
||||||
$t3 = Tenant::create([
|
$t3 = ResourceTenant::create([
|
||||||
'id' => 't3',
|
'id' => 't3',
|
||||||
]);
|
]);
|
||||||
$this->migrateTenants();
|
$this->migrateTenants();
|
||||||
|
|
@ -520,12 +520,12 @@ class ResourceSyncingTest extends TestCase
|
||||||
Event::fake([SyncedResourceChangedInForeignDatabase::class]);
|
Event::fake([SyncedResourceChangedInForeignDatabase::class]);
|
||||||
|
|
||||||
$t3->run(function () {
|
$t3->run(function () {
|
||||||
User::first()->update([
|
ResourceUser::first()->update([
|
||||||
'name' => 'John 3',
|
'name' => 'John 3',
|
||||||
'role' => 'employee', // unsynced
|
'role' => 'employee', // unsynced
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertSame('employee', User::first()->role);
|
$this->assertSame('employee', ResourceUser::first()->role);
|
||||||
});
|
});
|
||||||
|
|
||||||
Event::assertDispatched(SyncedResourceChangedInForeignDatabase::class, function (SyncedResourceChangedInForeignDatabase $event) {
|
Event::assertDispatched(SyncedResourceChangedInForeignDatabase::class, function (SyncedResourceChangedInForeignDatabase $event) {
|
||||||
|
|
@ -545,11 +545,30 @@ class ResourceSyncingTest extends TestCase
|
||||||
return $event->tenant === null;
|
return $event->tenant === null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// todo update in global
|
// Flush
|
||||||
|
Event::fake([SyncedResourceChangedInForeignDatabase::class]);
|
||||||
|
|
||||||
|
$centralUser->update([
|
||||||
|
'name' => 'John Central',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Event::assertDispatched(SyncedResourceChangedInForeignDatabase::class, function (SyncedResourceChangedInForeignDatabase $event) {
|
||||||
|
return optional($event->tenant)->getTenantKey() === 't1';
|
||||||
|
});
|
||||||
|
Event::assertDispatched(SyncedResourceChangedInForeignDatabase::class, function (SyncedResourceChangedInForeignDatabase $event) {
|
||||||
|
return optional($event->tenant)->getTenantKey() === 't2';
|
||||||
|
});
|
||||||
|
Event::assertDispatched(SyncedResourceChangedInForeignDatabase::class, function (SyncedResourceChangedInForeignDatabase $event) {
|
||||||
|
return optional($event->tenant)->getTenantKey() === 't3';
|
||||||
|
});
|
||||||
|
// Assert NOT dispatched in central
|
||||||
|
Event::assertNotDispatched(SyncedResourceChangedInForeignDatabase::class, function (SyncedResourceChangedInForeignDatabase $event) {
|
||||||
|
return $event->tenant === null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tenant extends Models\Tenant
|
class ResourceTenant extends Models\Tenant
|
||||||
{
|
{
|
||||||
public function users()
|
public function users()
|
||||||
{
|
{
|
||||||
|
|
@ -568,13 +587,13 @@ class CentralUser extends Model implements SyncMaster
|
||||||
|
|
||||||
public function tenants(): BelongsToMany
|
public function tenants(): BelongsToMany
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Tenant::class, 'tenant_users', 'global_user_id', 'tenant_id')
|
return $this->belongsToMany(ResourceTenant::class, 'tenant_users', 'global_user_id', 'tenant_id')
|
||||||
->using(TenantPivot::class);
|
->using(TenantPivot::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTenantModelName(): string
|
public function getTenantModelName(): string
|
||||||
{
|
{
|
||||||
return User::class;
|
return ResourceUser::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTenantIdColumnInMapTable(): string
|
public function getTenantIdColumnInMapTable(): string
|
||||||
|
|
@ -607,10 +626,11 @@ class CentralUser extends Model implements SyncMaster
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class User extends Model implements Syncable
|
class ResourceUser extends Model implements Syncable
|
||||||
{
|
{
|
||||||
use ResourceSyncing;
|
use ResourceSyncing;
|
||||||
|
|
||||||
|
protected $table = 'users';
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Stancl\Tenancy\Database\Models;
|
use Stancl\Tenancy\Database\Models;
|
||||||
use Stancl\Tenancy\Database\Models\Concerns\HasDomains;
|
use Stancl\Tenancy\Database\Concerns\HasDomains;
|
||||||
use Stancl\Tenancy\Exceptions\NotASubdomainException;
|
use Stancl\Tenancy\Exceptions\NotASubdomainException;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain;
|
use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
@ -26,13 +26,13 @@ class SubdomainTest extends TestCase
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
config(['tenancy.tenant_model' => Tenant::class]);
|
config(['tenancy.tenant_model' => SubdomainTenant::class]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function tenant_can_be_identified_by_subdomain()
|
public function tenant_can_be_identified_by_subdomain()
|
||||||
{
|
{
|
||||||
$tenant = Tenant::create([
|
$tenant = SubdomainTenant::create([
|
||||||
'id' => 'acme',
|
'id' => 'acme',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ class SubdomainTest extends TestCase
|
||||||
// not 'localhost'
|
// not 'localhost'
|
||||||
]]);
|
]]);
|
||||||
|
|
||||||
$tenant = Tenant::create([
|
$tenant = SubdomainTenant::create([
|
||||||
'id' => 'acme',
|
'id' => 'acme',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ class SubdomainTest extends TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tenant extends Models\Tenant
|
class SubdomainTenant extends Models\Tenant
|
||||||
{
|
{
|
||||||
use HasDomains;
|
use HasDomains;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Stancl\Tenancy\Controllers\TenantAssetsController;
|
use Stancl\Tenancy\Controllers\TenantAssetsController;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
use Stancl\Tenancy\DatabaseManager;
|
use Stancl\Tenancy\DatabaseManager;
|
||||||
use Stancl\Tenancy\Events\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Events\Listeners\JobPipeline;
|
use Stancl\Tenancy\Listeners\JobPipeline;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests\v3;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
@ -39,7 +39,7 @@ class TenantModelTest extends TestCase
|
||||||
|
|
||||||
tenancy()->end();
|
tenancy()->end();
|
||||||
|
|
||||||
$this->assertSame(null, app(Tenant::class));
|
$this->assertSame(null, app(Contracts\Tenant::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
@ -53,7 +53,7 @@ class TenantModelTest extends TestCase
|
||||||
$this->assertSame('bar', $tenant->foo);
|
$this->assertSame('bar', $tenant->foo);
|
||||||
$this->assertSame(null, $tenant->data);
|
$this->assertSame(null, $tenant->data);
|
||||||
|
|
||||||
// Low level test to test database structure
|
// Low level test to assert database structure
|
||||||
$this->assertSame(json_encode(['foo' => 'bar']), DB::table('tenants')->where('id', $tenant->id)->first()->data);
|
$this->assertSame(json_encode(['foo' => 'bar']), DB::table('tenants')->where('id', $tenant->id)->first()->data);
|
||||||
$this->assertSame(null, DB::table('tenants')->where('id', $tenant->id)->first()->foo ?? null);
|
$this->assertSame(null, DB::table('tenants')->where('id', $tenant->id)->first()->foo ?? null);
|
||||||
|
|
||||||
|
|
@ -103,8 +103,8 @@ class TenantModelTest extends TestCase
|
||||||
|
|
||||||
unset(app()[UniqueIdentifierGenerator::class]);
|
unset(app()[UniqueIdentifierGenerator::class]);
|
||||||
|
|
||||||
$tenant1 = MyTenant::create();
|
$tenant1 = Tenant::create();
|
||||||
$tenant2 = MyTenant::create();
|
$tenant2 = Tenant::create();
|
||||||
|
|
||||||
$this->assertSame(1, $tenant1->id);
|
$this->assertSame(1, $tenant1->id);
|
||||||
$this->assertSame(2, $tenant2->id);
|
$this->assertSame(2, $tenant2->id);
|
||||||
|
|
@ -138,7 +138,6 @@ class TenantModelTest extends TestCase
|
||||||
class MyTenant extends Tenant
|
class MyTenant extends Tenant
|
||||||
{
|
{
|
||||||
protected $table = 'tenants';
|
protected $table = 'tenants';
|
||||||
public $increments = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AnotherTenant extends Model implements Contracts\Tenant
|
class AnotherTenant extends Model implements Contracts\Tenant
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue