mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 22:14:03 +00:00
Merge branch 'master' into cache-prefix
This commit is contained in:
commit
249fc545d2
22 changed files with 564 additions and 38 deletions
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
|
@ -15,7 +15,11 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
laravel: ['dev-cache-methods as 9.47']
|
include:
|
||||||
|
- laravel: 9
|
||||||
|
php: "8.0"
|
||||||
|
- laravel: 10
|
||||||
|
php: "8.1"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|
@ -23,7 +27,7 @@ jobs:
|
||||||
|
|
||||||
- name: Install Composer dependencies
|
- name: Install Composer dependencies
|
||||||
run: |
|
run: |
|
||||||
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
|
composer require "laravel/framework:^${{ matrix.laravel }}.0" --no-interaction --no-update
|
||||||
composer update --prefer-dist --no-interaction
|
composer update --prefer-dist --no-interaction
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: ./vendor/bin/pest
|
run: ./vendor/bin/pest
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ RUN apt-get update \
|
||||||
&& curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \
|
&& curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \
|
||||||
&& curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list \
|
&& curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& ACCEPT_EULA=Y apt-get install -y unixodbc-dev msodbcsql17
|
&& ACCEPT_EULA=Y apt-get install -y unixodbc-dev=2.3.7 unixodbc=2.3.7 odbcinst1debian2=2.3.7 odbcinst=2.3.7 msodbcsql17
|
||||||
|
|
||||||
# set PHP version
|
# set PHP version
|
||||||
RUN update-alternatives --set php /usr/bin/php$PHP_VERSION \
|
RUN update-alternatives --set php /usr/bin/php$PHP_VERSION \
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Jobs;
|
||||||
|
use Stancl\Tenancy\Events;
|
||||||
|
use Stancl\Tenancy\Listeners;
|
||||||
|
use Stancl\Tenancy\Middleware;
|
||||||
|
use Stancl\JobPipeline\JobPipeline;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Stancl\JobPipeline\JobPipeline;
|
|
||||||
use Stancl\Tenancy\Events;
|
|
||||||
use Stancl\Tenancy\Jobs;
|
|
||||||
use Stancl\Tenancy\Listeners;
|
|
||||||
use Stancl\Tenancy\Middleware;
|
|
||||||
|
|
||||||
class TenancyServiceProvider extends ServiceProvider
|
class TenancyServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
@ -118,6 +118,21 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function overrideUrlInTenantContext(): void
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Example of CLI tenant URL root override:
|
||||||
|
*
|
||||||
|
* UrlTenancyBootstrapper::$rootUrlOverride = function (Tenant $tenant) {
|
||||||
|
* $baseUrl = url('/');
|
||||||
|
* $scheme = str($baseUrl)->before('://');
|
||||||
|
* $hostname = str($baseUrl)->after($scheme . '://');
|
||||||
|
*
|
||||||
|
* return $scheme . '://' . $tenant->getTenantKey() . '.' . $hostname;
|
||||||
|
*};
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
|
@ -129,6 +144,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
$this->mapRoutes();
|
$this->mapRoutes();
|
||||||
|
|
||||||
$this->makeTenancyMiddlewareHighestPriority();
|
$this->makeTenancyMiddlewareHighestPriority();
|
||||||
|
$this->overrideUrlInTenantContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function bootEvents()
|
protected function bootEvents()
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ return [
|
||||||
Stancl\Tenancy\Bootstrappers\QueueTenancyBootstrapper::class,
|
Stancl\Tenancy\Bootstrappers\QueueTenancyBootstrapper::class,
|
||||||
Stancl\Tenancy\Bootstrappers\BatchTenancyBootstrapper::class,
|
Stancl\Tenancy\Bootstrappers\BatchTenancyBootstrapper::class,
|
||||||
// Stancl\Tenancy\Bootstrappers\PrefixCacheTenancyBootstrapper::class,
|
// Stancl\Tenancy\Bootstrappers\PrefixCacheTenancyBootstrapper::class,
|
||||||
|
// Stancl\Tenancy\Bootstrappers\UrlTenancyBootstrapper::class,
|
||||||
// Stancl\Tenancy\Bootstrappers\SessionTenancyBootstrapper::class,
|
// Stancl\Tenancy\Bootstrappers\SessionTenancyBootstrapper::class,
|
||||||
// Stancl\Tenancy\Bootstrappers\MailTenancyBootstrapper::class, // Queueing mail requires using QueueTenancyBootstrapper with $forceRefresh set to true
|
// Stancl\Tenancy\Bootstrappers\MailTenancyBootstrapper::class, // Queueing mail requires using QueueTenancyBootstrapper with $forceRefresh set to true
|
||||||
// Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper::class, // Note: phpredis is needed
|
// Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper::class, // Note: phpredis is needed
|
||||||
|
|
@ -259,7 +260,7 @@ return [
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis tenancy config. Used by RedisTenancyBoostrapper.
|
* Redis tenancy config. Used by RedisTenancyBootstrapper.
|
||||||
*
|
*
|
||||||
* Note: You need phpredis to use Redis tenancy.
|
* Note: You need phpredis to use Redis tenancy.
|
||||||
*
|
*
|
||||||
|
|
@ -287,6 +288,7 @@ return [
|
||||||
// Stancl\Tenancy\Features\TelescopeTags::class,
|
// Stancl\Tenancy\Features\TelescopeTags::class,
|
||||||
// Stancl\Tenancy\Features\TenantConfig::class, // https://tenancyforlaravel.com/docs/v3/features/tenant-config
|
// Stancl\Tenancy\Features\TenantConfig::class, // https://tenancyforlaravel.com/docs/v3/features/tenant-config
|
||||||
// Stancl\Tenancy\Features\CrossDomainRedirect::class, // https://tenancyforlaravel.com/docs/v3/features/cross-domain-redirect
|
// Stancl\Tenancy\Features\CrossDomainRedirect::class, // https://tenancyforlaravel.com/docs/v3/features/cross-domain-redirect
|
||||||
|
// Stancl\Tenancy\Features\ViteBundler::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -17,17 +17,19 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"illuminate/support": "^9.38",
|
"illuminate/support": "^9.38|^10.0",
|
||||||
|
"facade/ignition-contracts": "^1.0.2",
|
||||||
"spatie/ignition": "^1.4",
|
"spatie/ignition": "^1.4",
|
||||||
"ramsey/uuid": "^4.0",
|
"ramsey/uuid": "^4.7.3",
|
||||||
"stancl/jobpipeline": "^1.0",
|
"stancl/jobpipeline": "^1.6.2",
|
||||||
"stancl/virtualcolumn": "^1.3"
|
"stancl/virtualcolumn": "^1.3.1",
|
||||||
|
"spatie/invade": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"laravel/framework": "dev-cache-methods as 9.47",
|
"laravel/framework": "^9.38|^10.0",
|
||||||
"orchestra/testbench": "^7.0",
|
"orchestra/testbench": "^7.0|^8.0",
|
||||||
"league/flysystem-aws-s3-v3": "^3.0",
|
"league/flysystem-aws-s3-v3": "^3.12.2",
|
||||||
"doctrine/dbal": "^2.10",
|
"doctrine/dbal": "^3.6.0",
|
||||||
"spatie/valuestore": "^1.2.5",
|
"spatie/valuestore": "^1.2.5",
|
||||||
"pestphp/pest": "^1.21",
|
"pestphp/pest": "^1.21",
|
||||||
"nunomaduro/larastan": "^2.4",
|
"nunomaduro/larastan": "^2.4",
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,6 @@ parameters:
|
||||||
message: '#Illuminate\\Routing\\UrlGenerator#'
|
message: '#Illuminate\\Routing\\UrlGenerator#'
|
||||||
paths:
|
paths:
|
||||||
- src/Bootstrappers/FilesystemTenancyBootstrapper.php
|
- src/Bootstrappers/FilesystemTenancyBootstrapper.php
|
||||||
-
|
|
||||||
message: '#select\(\) expects string, Illuminate\\Database\\Query\\Expression given#'
|
|
||||||
paths:
|
|
||||||
- src/Database/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php
|
|
||||||
-
|
-
|
||||||
message: '#Trying to invoke Closure\|null but it might not be a callable#'
|
message: '#Trying to invoke Closure\|null but it might not be a callable#'
|
||||||
paths:
|
paths:
|
||||||
|
|
|
||||||
95
src/Bootstrappers/BroadcastTenancyBootstrapper.php
Normal file
95
src/Bootstrappers/BroadcastTenancyBootstrapper.php
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Bootstrappers;
|
||||||
|
|
||||||
|
use Illuminate\Broadcasting\BroadcastManager;
|
||||||
|
use Illuminate\Config\Repository;
|
||||||
|
use Illuminate\Contracts\Broadcasting\Broadcaster;
|
||||||
|
use Illuminate\Foundation\Application;
|
||||||
|
use Stancl\Tenancy\Contracts\TenancyBootstrapper;
|
||||||
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
|
use Stancl\Tenancy\TenancyBroadcastManager;
|
||||||
|
|
||||||
|
class BroadcastTenancyBootstrapper implements TenancyBootstrapper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Tenant properties to be mapped to config (similarly to the TenantConfig feature).
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* [
|
||||||
|
* 'config.key.name' => 'tenant_property',
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
public static array $credentialsMap = [];
|
||||||
|
|
||||||
|
public static string|null $broadcaster = null;
|
||||||
|
|
||||||
|
protected array $originalConfig = [];
|
||||||
|
protected BroadcastManager|null $originalBroadcastManager = null;
|
||||||
|
protected Broadcaster|null $originalBroadcaster = null;
|
||||||
|
|
||||||
|
public static array $mapPresets = [
|
||||||
|
'pusher' => [
|
||||||
|
'broadcasting.connections.pusher.key' => 'pusher_key',
|
||||||
|
'broadcasting.connections.pusher.secret' => 'pusher_secret',
|
||||||
|
'broadcasting.connections.pusher.app_id' => 'pusher_app_id',
|
||||||
|
'broadcasting.connections.pusher.options.cluster' => 'pusher_cluster',
|
||||||
|
],
|
||||||
|
'ably' => [
|
||||||
|
'broadcasting.connections.ably.key' => 'ably_key',
|
||||||
|
'broadcasting.connections.ably.public' => 'ably_public',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
protected Repository $config,
|
||||||
|
protected Application $app
|
||||||
|
) {
|
||||||
|
static::$broadcaster ??= $config->get('broadcasting.default');
|
||||||
|
static::$credentialsMap = array_merge(static::$credentialsMap, static::$mapPresets[static::$broadcaster] ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bootstrap(Tenant $tenant): void
|
||||||
|
{
|
||||||
|
$this->originalBroadcastManager = $this->app->make(BroadcastManager::class);
|
||||||
|
$this->originalBroadcaster = $this->app->make(Broadcaster::class);
|
||||||
|
|
||||||
|
$this->setConfig($tenant);
|
||||||
|
|
||||||
|
// Make BroadcastManager resolve to a custom BroadcastManager which makes the broadcasters use the tenant credentials
|
||||||
|
$this->app->extend(BroadcastManager::class, function (BroadcastManager $broadcastManager) {
|
||||||
|
return new TenancyBroadcastManager($this->app);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function revert(): void
|
||||||
|
{
|
||||||
|
// Change the BroadcastManager and Broadcaster singletons back to what they were before initializing tenancy
|
||||||
|
$this->app->singleton(BroadcastManager::class, fn (Application $app) => $this->originalBroadcastManager);
|
||||||
|
$this->app->singleton(Broadcaster::class, fn (Application $app) => $this->originalBroadcaster);
|
||||||
|
|
||||||
|
$this->unsetConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setConfig(Tenant $tenant): void
|
||||||
|
{
|
||||||
|
foreach (static::$credentialsMap as $configKey => $storageKey) {
|
||||||
|
$override = $tenant->$storageKey;
|
||||||
|
|
||||||
|
if (array_key_exists($storageKey, $tenant->getAttributes())) {
|
||||||
|
$this->originalConfig[$configKey] ??= $this->config->get($configKey);
|
||||||
|
|
||||||
|
$this->config->set($configKey, $override);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function unsetConfig(): void
|
||||||
|
{
|
||||||
|
foreach ($this->originalConfig as $key => $value) {
|
||||||
|
$this->config->set($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/Bootstrappers/UrlTenancyBootstrapper.php
Normal file
41
src/Bootstrappers/UrlTenancyBootstrapper.php
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Bootstrappers;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Config\Repository;
|
||||||
|
use Illuminate\Contracts\Routing\UrlGenerator;
|
||||||
|
use Stancl\Tenancy\Contracts\TenancyBootstrapper;
|
||||||
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
|
|
||||||
|
class UrlTenancyBootstrapper implements TenancyBootstrapper
|
||||||
|
{
|
||||||
|
public static Closure|null $rootUrlOverride = null;
|
||||||
|
protected string|null $originalRootUrl = null;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
protected UrlGenerator $urlGenerator,
|
||||||
|
protected Repository $config,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bootstrap(Tenant $tenant): void
|
||||||
|
{
|
||||||
|
$this->originalRootUrl = $this->urlGenerator->to('/');
|
||||||
|
|
||||||
|
if (static::$rootUrlOverride) {
|
||||||
|
$newRootUrl = (static::$rootUrlOverride)($tenant);
|
||||||
|
|
||||||
|
$this->urlGenerator->forceRootUrl($newRootUrl);
|
||||||
|
$this->config->set('app.url', $newRootUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function revert(): void
|
||||||
|
{
|
||||||
|
$this->urlGenerator->forceRootUrl($this->originalRootUrl);
|
||||||
|
$this->config->set('app.url', $this->originalRootUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -33,9 +33,8 @@ class ImpersonationToken extends Model
|
||||||
public $incrementing = false;
|
public $incrementing = false;
|
||||||
|
|
||||||
protected $table = 'tenant_user_impersonation_tokens';
|
protected $table = 'tenant_user_impersonation_tokens';
|
||||||
|
protected $casts = [
|
||||||
protected $dates = [
|
'created_at' => 'datetime',
|
||||||
'created_at',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function booted(): void
|
public static function booted(): void
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ class Tenant extends Model implements Contracts\Tenant
|
||||||
Concerns\InitializationHelpers,
|
Concerns\InitializationHelpers,
|
||||||
Concerns\InvalidatesResolverCache;
|
Concerns\InvalidatesResolverCache;
|
||||||
|
|
||||||
|
protected static $modelsShouldPreventAccessingMissingAttributes = false;
|
||||||
|
|
||||||
protected $table = 'tenants';
|
protected $table = 'tenants';
|
||||||
protected $primaryKey = 'id';
|
protected $primaryKey = 'id';
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,8 @@ class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager impl
|
||||||
|
|
||||||
protected function isVersion8(): bool
|
protected function isVersion8(): bool
|
||||||
{
|
{
|
||||||
$version = $this->database()->select($this->database()->raw('select version()'))[0]->{'version()'};
|
$versionSelect = (string) $this->database()->raw('select version()')->getValue($this->database()->getQueryGrammar());
|
||||||
|
$version = $this->database()->select($versionSelect)[0]->{'version()'};
|
||||||
|
|
||||||
return version_compare($version, '8.0.0') >= 0;
|
return version_compare($version, '8.0.0') >= 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
26
src/Features/ViteBundler.php
Normal file
26
src/Features/ViteBundler.php
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Features;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Application;
|
||||||
|
use Stancl\Tenancy\Contracts\Feature;
|
||||||
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
use Stancl\Tenancy\Vite;
|
||||||
|
|
||||||
|
class ViteBundler implements Feature
|
||||||
|
{
|
||||||
|
/** @var Application */
|
||||||
|
protected $app;
|
||||||
|
|
||||||
|
public function __construct(Application $app)
|
||||||
|
{
|
||||||
|
$this->app = $app;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bootstrap(Tenancy $tenancy): void
|
||||||
|
{
|
||||||
|
$this->app->singleton(\Illuminate\Foundation\Vite::class, Vite::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/TenancyBroadcastManager.php
Normal file
65
src/TenancyBroadcastManager.php
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy; // todo new Overrides namespace?
|
||||||
|
|
||||||
|
use Illuminate\Broadcasting\Broadcasters\Broadcaster;
|
||||||
|
use Illuminate\Broadcasting\BroadcastManager;
|
||||||
|
use Illuminate\Contracts\Broadcasting\Broadcaster as BroadcasterContract;
|
||||||
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
|
|
||||||
|
class TenancyBroadcastManager extends BroadcastManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Names of broadcasters to always recreate using $this->resolve() (even when they're
|
||||||
|
* cached and available in the $broadcasters property).
|
||||||
|
*
|
||||||
|
* The reason for recreating the broadcasters is
|
||||||
|
* to make your app use the correct broadcaster credentials when tenancy is initialized.
|
||||||
|
*/
|
||||||
|
public static array $tenantBroadcasters = ['pusher', 'ably'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the get method so that the broadcasters in $tenantBroadcasters
|
||||||
|
* always get freshly resolved even when they're cached and available in the $broadcasters property,
|
||||||
|
* and that the resolved broadcaster will override the BroadcasterContract::class singleton.
|
||||||
|
*
|
||||||
|
* If there's a cached broadcaster with the same name as $name,
|
||||||
|
* give its channels to the newly resolved bootstrapper.
|
||||||
|
*/
|
||||||
|
protected function get($name)
|
||||||
|
{
|
||||||
|
if (in_array($name, static::$tenantBroadcasters)) {
|
||||||
|
/** @var Broadcaster|null $originalBroadcaster */
|
||||||
|
$originalBroadcaster = $this->app->make(BroadcasterContract::class);
|
||||||
|
$newBroadcaster = $this->resolve($name);
|
||||||
|
|
||||||
|
// If there is a current broadcaster, give its channels to the newly resolved one
|
||||||
|
// Broadcasters only have to implement the Illuminate\Contracts\Broadcasting\Broadcaster contract
|
||||||
|
// Which doesn't require the channels property
|
||||||
|
// So passing the channels is only needed for Illuminate\Broadcasting\Broadcasters\Broadcaster instances
|
||||||
|
if ($originalBroadcaster instanceof Broadcaster && $newBroadcaster instanceof Broadcaster) {
|
||||||
|
$this->passChannelsFromOriginalBroadcaster($originalBroadcaster, $newBroadcaster);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->app->singleton(BroadcasterContract::class, fn (Application $app) => $newBroadcaster);
|
||||||
|
|
||||||
|
return $newBroadcaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::get($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because, unlike the original broadcaster, the newly resolved broadcaster won't have the channels registered using routes/channels.php
|
||||||
|
// Using it for broadcasting won't work, unless we make it have the original broadcaster's channels
|
||||||
|
protected function passChannelsFromOriginalBroadcaster(Broadcaster $originalBroadcaster, Broadcaster $newBroadcaster): void
|
||||||
|
{
|
||||||
|
// invade() because channels can't be retrieved through any of the broadcaster's public methods
|
||||||
|
$originalBroadcaster = invade($originalBroadcaster);
|
||||||
|
|
||||||
|
foreach ($originalBroadcaster->channels as $channel => $callback) {
|
||||||
|
$newBroadcaster->channel($channel, $callback, $originalBroadcaster->retrieveChannelOptions($channel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,6 +63,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
$this->app->singleton(Commands\Rollback::class, function ($app) {
|
$this->app->singleton(Commands\Rollback::class, function ($app) {
|
||||||
return new Commands\Rollback($app['migrator']);
|
return new Commands\Rollback($app['migrator']);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->singleton(Commands\Seed::class, function ($app) {
|
$this->app->singleton(Commands\Seed::class, function ($app) {
|
||||||
return new Commands\Seed($app['db']);
|
return new Commands\Seed($app['db']);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
22
src/Vite.php
Normal file
22
src/Vite.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Vite as BaseVite;
|
||||||
|
|
||||||
|
class Vite extends BaseVite // todo move to a different directory in v4
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Generate an asset path for the application.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param bool|null $secure
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function assetPath($path, $secure = null)
|
||||||
|
{
|
||||||
|
return global_asset($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Mail\MailManager;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\URL;
|
||||||
use Stancl\JobPipeline\JobPipeline;
|
use Stancl\JobPipeline\JobPipeline;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
use Stancl\Tenancy\Bootstrappers\PrefixCacheTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\PrefixCacheTenancyBootstrapper;
|
||||||
|
|
@ -12,23 +12,30 @@ use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Stancl\Tenancy\Events\TenancyEnded;
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
use Stancl\Tenancy\Events\TenantDeleted;
|
use Stancl\Tenancy\Events\TenantDeleted;
|
||||||
use Stancl\Tenancy\Events\DeletingTenant;
|
use Stancl\Tenancy\Events\DeletingTenant;
|
||||||
|
use Stancl\Tenancy\TenancyBroadcastManager;
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
use Illuminate\Filesystem\FilesystemAdapter;
|
||||||
|
use Illuminate\Broadcasting\BroadcastManager;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Jobs\CreateStorageSymlinks;
|
use Stancl\Tenancy\Jobs\CreateStorageSymlinks;
|
||||||
use Stancl\Tenancy\Jobs\RemoveStorageSymlinks;
|
use Stancl\Tenancy\Jobs\RemoveStorageSymlinks;
|
||||||
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
|
use Stancl\Tenancy\Tests\Etc\TestingBroadcaster;
|
||||||
use Stancl\Tenancy\Listeners\DeleteTenantStorage;
|
use Stancl\Tenancy\Listeners\DeleteTenantStorage;
|
||||||
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
|
use Stancl\Tenancy\Bootstrappers\UrlTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Bootstrappers\MailTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\MailTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Bootstrappers\CacheTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\CacheTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper;
|
||||||
|
use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain;
|
||||||
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
|
||||||
|
use Stancl\Tenancy\Bootstrappers\BroadcastTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\CacheManager;
|
use Stancl\Tenancy\CacheManager;
|
||||||
|
|
||||||
|
|
@ -333,6 +340,82 @@ test('local storage public urls are generated correctly', function() {
|
||||||
expect(File::isDirectory($tenantStoragePath))->toBeFalse();
|
expect(File::isDirectory($tenantStoragePath))->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('BroadcastTenancyBootstrapper binds TenancyBroadcastManager to BroadcastManager and reverts the binding when tenancy is ended', function() {
|
||||||
|
expect(app(BroadcastManager::class))->toBeInstanceOf(BroadcastManager::class);
|
||||||
|
|
||||||
|
tenancy()->initialize(Tenant::create());
|
||||||
|
|
||||||
|
expect(app(BroadcastManager::class))->toBeInstanceOf(TenancyBroadcastManager::class);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
|
||||||
|
expect(app(BroadcastManager::class))->toBeInstanceOf(BroadcastManager::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('BroadcastTenancyBootstrapper maps tenant broadcaster credentials to config as specified in the $credentialsMap property and reverts the config after ending tenancy', function() {
|
||||||
|
config([
|
||||||
|
'broadcasting.connections.testing.driver' => 'testing',
|
||||||
|
'broadcasting.connections.testing.message' => $defaultMessage = 'default',
|
||||||
|
]);
|
||||||
|
|
||||||
|
BroadcastTenancyBootstrapper::$credentialsMap = [
|
||||||
|
'broadcasting.connections.testing.message' => 'testing_broadcaster_message',
|
||||||
|
];
|
||||||
|
|
||||||
|
$tenant = Tenant::create(['testing_broadcaster_message' => $tenantMessage = 'first testing']);
|
||||||
|
$tenant2 = Tenant::create(['testing_broadcaster_message' => $secondTenantMessage = 'second testing']);
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant);
|
||||||
|
|
||||||
|
expect(array_key_exists('testing_broadcaster_message', tenant()->getAttributes()))->toBeTrue();
|
||||||
|
expect(config('broadcasting.connections.testing.message'))->toBe($tenantMessage);
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant2);
|
||||||
|
|
||||||
|
expect(config('broadcasting.connections.testing.message'))->toBe($secondTenantMessage);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
|
||||||
|
expect(config('broadcasting.connections.testing.message'))->toBe($defaultMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('BroadcastTenancyBootstrapper makes the app use broadcasters with the correct credentials', function() {
|
||||||
|
config([
|
||||||
|
'broadcasting.default' => 'testing',
|
||||||
|
'broadcasting.connections.testing.driver' => 'testing',
|
||||||
|
'broadcasting.connections.testing.message' => $defaultMessage = 'default',
|
||||||
|
]);
|
||||||
|
|
||||||
|
TenancyBroadcastManager::$tenantBroadcasters[] = 'testing';
|
||||||
|
BroadcastTenancyBootstrapper::$credentialsMap = [
|
||||||
|
'broadcasting.connections.testing.message' => 'testing_broadcaster_message',
|
||||||
|
];
|
||||||
|
|
||||||
|
$registerTestingBroadcaster = fn() => app(BroadcastManager::class)->extend('testing', fn($app, $config) => new TestingBroadcaster($config['message']));
|
||||||
|
|
||||||
|
$registerTestingBroadcaster();
|
||||||
|
|
||||||
|
expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($defaultMessage);
|
||||||
|
|
||||||
|
$tenant = Tenant::create(['testing_broadcaster_message' => $tenantMessage = 'first testing']);
|
||||||
|
$tenant2 = Tenant::create(['testing_broadcaster_message' => $secondTenantMessage = 'second testing']);
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant);
|
||||||
|
$registerTestingBroadcaster();
|
||||||
|
|
||||||
|
expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($tenantMessage);
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant2);
|
||||||
|
$registerTestingBroadcaster();
|
||||||
|
|
||||||
|
expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($secondTenantMessage);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
$registerTestingBroadcaster();
|
||||||
|
|
||||||
|
expect(invade(app(BroadcastManager::class)->driver())->message)->toBe($defaultMessage);
|
||||||
|
});
|
||||||
|
|
||||||
test('MailTenancyBootstrapper maps tenant mail credentials to config as specified in the $credentialsMap property and makes the mailer use tenant credentials', function() {
|
test('MailTenancyBootstrapper maps tenant mail credentials to config as specified in the $credentialsMap property and makes the mailer use tenant credentials', function() {
|
||||||
MailTenancyBootstrapper::$credentialsMap = [
|
MailTenancyBootstrapper::$credentialsMap = [
|
||||||
'mail.mailers.smtp.username' => 'smtp_username',
|
'mail.mailers.smtp.username' => 'smtp_username',
|
||||||
|
|
@ -385,3 +468,48 @@ function getDiskPrefix(string $disk): string
|
||||||
|
|
||||||
return $prefix;
|
return $prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test('url bootstrapper overrides the root url when tenancy gets initialized and reverts the url to the central one after tenancy ends', function() {
|
||||||
|
config(['tenancy.bootstrappers.url' => UrlTenancyBootstrapper::class]);
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'middleware' => InitializeTenancyBySubdomain::class,
|
||||||
|
], function () {
|
||||||
|
Route::get('/', function () {
|
||||||
|
return true;
|
||||||
|
})->name('home');
|
||||||
|
});
|
||||||
|
|
||||||
|
$baseUrl = url(route('home'));
|
||||||
|
config(['app.url' => $baseUrl]);
|
||||||
|
|
||||||
|
$rootUrlOverride = function (Tenant $tenant) use ($baseUrl) {
|
||||||
|
$scheme = str($baseUrl)->before('://');
|
||||||
|
$hostname = str($baseUrl)->after($scheme . '://');
|
||||||
|
|
||||||
|
return $scheme . '://' . $tenant->getTenantKey() . '.' . $hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
UrlTenancyBootstrapper::$rootUrlOverride = $rootUrlOverride;
|
||||||
|
|
||||||
|
$tenant = Tenant::create();
|
||||||
|
$tenantUrl = $rootUrlOverride($tenant);
|
||||||
|
|
||||||
|
expect($tenantUrl)->not()->toBe($baseUrl);
|
||||||
|
|
||||||
|
expect(url(route('home')))->toBe($baseUrl);
|
||||||
|
expect(URL::to('/'))->toBe($baseUrl);
|
||||||
|
expect(config('app.url'))->toBe($baseUrl);
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant);
|
||||||
|
|
||||||
|
expect(url(route('home')))->toBe($tenantUrl);
|
||||||
|
expect(URL::to('/'))->toBe($tenantUrl);
|
||||||
|
expect(config('app.url'))->toBe($tenantUrl);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
|
||||||
|
expect(url(route('home')))->toBe($baseUrl);
|
||||||
|
expect(URL::to('/'))->toBe($baseUrl);
|
||||||
|
expect(config('app.url'))->toBe($baseUrl);
|
||||||
|
});
|
||||||
|
|
|
||||||
65
tests/BroadcastingTest.php
Normal file
65
tests/BroadcastingTest.php
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
|
use Illuminate\Support\Facades\Broadcast;
|
||||||
|
use Stancl\Tenancy\TenancyBroadcastManager;
|
||||||
|
use Illuminate\Broadcasting\BroadcastManager;
|
||||||
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
|
use Stancl\Tenancy\Tests\Etc\TestingBroadcaster;
|
||||||
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
|
use Illuminate\Contracts\Broadcasting\Broadcaster as BroadcasterContract;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
withTenantDatabases();
|
||||||
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
|
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('bound broadcaster instance is the same before initializing tenancy and after ending it', function() {
|
||||||
|
config(['broadcasting.default' => 'null']);
|
||||||
|
TenancyBroadcastManager::$tenantBroadcasters[] = 'null';
|
||||||
|
|
||||||
|
$originalBroadcaster = app(BroadcasterContract::class);
|
||||||
|
|
||||||
|
tenancy()->initialize(Tenant::create());
|
||||||
|
|
||||||
|
// TenancyBroadcastManager binds new broadcaster
|
||||||
|
$tenantBroadcaster = app(BroadcastManager::class)->driver();
|
||||||
|
|
||||||
|
expect($tenantBroadcaster)->not()->toBe($originalBroadcaster);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
|
||||||
|
expect($originalBroadcaster)->toBe(app(BroadcasterContract::class));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('new broadcasters get the channels from the previously bound broadcaster', function() {
|
||||||
|
config([
|
||||||
|
'broadcasting.default' => $driver = 'testing',
|
||||||
|
'broadcasting.connections.testing.driver' => $driver,
|
||||||
|
]);
|
||||||
|
|
||||||
|
TenancyBroadcastManager::$tenantBroadcasters[] = $driver;
|
||||||
|
|
||||||
|
$registerTestingBroadcaster = fn() => app(BroadcastManager::class)->extend('testing', fn($app, $config) => new TestingBroadcaster('testing'));
|
||||||
|
$getCurrentChannels = fn() => array_keys(invade(app(BroadcastManager::class)->driver())->channels);
|
||||||
|
|
||||||
|
$registerTestingBroadcaster();
|
||||||
|
Broadcast::channel($channel = 'testing-channel', fn() => true);
|
||||||
|
|
||||||
|
expect($channel)->toBeIn($getCurrentChannels());
|
||||||
|
|
||||||
|
tenancy()->initialize(Tenant::create());
|
||||||
|
$registerTestingBroadcaster();
|
||||||
|
|
||||||
|
expect($channel)->toBeIn($getCurrentChannels());
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
$registerTestingBroadcaster();
|
||||||
|
|
||||||
|
expect($channel)->toBeIn($getCurrentChannels());
|
||||||
|
});
|
||||||
25
tests/Etc/TestingBroadcaster.php
Normal file
25
tests/Etc/TestingBroadcaster.php
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Tests\Etc;
|
||||||
|
|
||||||
|
use Illuminate\Broadcasting\Broadcasters\Broadcaster;
|
||||||
|
|
||||||
|
class TestingBroadcaster extends Broadcaster {
|
||||||
|
public function __construct(
|
||||||
|
public string $message
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function auth($request)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validAuthenticationResponse($request, $result)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function broadcast(array $channels, $event, array $payload = [])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -79,7 +79,7 @@ test('ing events can be used to cancel db creation', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
$tenant = Tenant::create();
|
$tenant = Tenant::create();
|
||||||
dispatch_now(new CreateDatabase($tenant));
|
dispatch_sync(new CreateDatabase($tenant));
|
||||||
|
|
||||||
pest()->assertFalse($tenant->database()->manager()->databaseExists(
|
pest()->assertFalse($tenant->database()->manager()->databaseExists(
|
||||||
$tenant->database()->getName()
|
$tenant->database()->getName()
|
||||||
|
|
@ -171,12 +171,13 @@ test('database is not migrated if creation is disabled', function () {
|
||||||
})->toListener()
|
})->toListener()
|
||||||
);
|
);
|
||||||
|
|
||||||
Tenant::create([
|
$tenant = Tenant::create([
|
||||||
'tenancy_create_database' => false,
|
'tenancy_create_database' => false,
|
||||||
'tenancy_db_name' => 'already_created',
|
'tenancy_db_name' => 'already_created',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(pest()->hasFailed())->toBeFalse();
|
// assert test didn't fail
|
||||||
|
$this->assertTrue($tenant->exists());
|
||||||
});
|
});
|
||||||
|
|
||||||
class FooListener extends QueueableListener
|
class FooListener extends QueueableListener
|
||||||
|
|
|
||||||
29
tests/Features/ViteBundlerTest.php
Normal file
29
tests/Features/ViteBundlerTest.php
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Vite;
|
||||||
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
use Stancl\Tenancy\Vite as StanclVite;
|
||||||
|
use Stancl\Tenancy\Features\ViteBundler;
|
||||||
|
|
||||||
|
test('vite helper uses our custom class', function() {
|
||||||
|
$vite = app(Vite::class);
|
||||||
|
|
||||||
|
expect($vite)->toBeInstanceOf(Vite::class);
|
||||||
|
expect($vite)->not()->toBeInstanceOf(StanclVite::class);
|
||||||
|
|
||||||
|
config([
|
||||||
|
'tenancy.features' => [ViteBundler::class],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tenant = Tenant::create();
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant);
|
||||||
|
|
||||||
|
app()->forgetInstance(Vite::class);
|
||||||
|
|
||||||
|
$vite = app(Vite::class);
|
||||||
|
|
||||||
|
expect($vite)->toBeInstanceOf(StanclVite::class);
|
||||||
|
});
|
||||||
|
|
@ -4,16 +4,18 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Dotenv\Dotenv;
|
|
||||||
use Illuminate\Foundation\Application;
|
|
||||||
use Illuminate\Support\Facades\Redis;
|
|
||||||
use PDO;
|
use PDO;
|
||||||
use Stancl\Tenancy\Bootstrappers\PrefixCacheTenancyBootstrapper;
|
use Dotenv\Dotenv;
|
||||||
use Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper;
|
|
||||||
use Stancl\Tenancy\Facades\GlobalCache;
|
|
||||||
use Stancl\Tenancy\Facades\Tenancy;
|
use Stancl\Tenancy\Facades\Tenancy;
|
||||||
use Stancl\Tenancy\TenancyServiceProvider;
|
|
||||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
use Stancl\Tenancy\Bootstrappers\PrefixCacheTenancyBootstrapper;
|
||||||
|
use Illuminate\Foundation\Application;
|
||||||
|
use Stancl\Tenancy\Facades\GlobalCache;
|
||||||
|
use Stancl\Tenancy\TenancyServiceProvider;
|
||||||
|
use Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper;
|
||||||
|
use Stancl\Tenancy\Bootstrappers\BroadcastTenancyBootstrapper;
|
||||||
|
use Stancl\Tenancy\Bootstrappers\UrlTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Bootstrappers\MailTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\MailTenancyBootstrapper;
|
||||||
|
|
||||||
abstract class TestCase extends \Orchestra\Testbench\TestCase
|
abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
|
|
@ -105,7 +107,9 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
'--force' => true,
|
'--force' => true,
|
||||||
],
|
],
|
||||||
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo1 change this to []? two tests in TenantDatabaseManagerTest are failing with that
|
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo1 change this to []? two tests in TenantDatabaseManagerTest are failing with that
|
||||||
|
'tenancy.bootstrappers.broadcast' => BroadcastTenancyBootstrapper::class, // todo1 change this to []? two tests in TenantDatabaseManagerTest are failing with that
|
||||||
'tenancy.bootstrappers.mail' => MailTenancyBootstrapper::class,
|
'tenancy.bootstrappers.mail' => MailTenancyBootstrapper::class,
|
||||||
|
'tenancy.bootstrappers.url' => UrlTenancyBootstrapper::class,
|
||||||
'queue.connections.central' => [
|
'queue.connections.central' => [
|
||||||
'driver' => 'sync',
|
'driver' => 'sync',
|
||||||
'central' => true,
|
'central' => true,
|
||||||
|
|
@ -116,7 +120,9 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
|
|
||||||
$app->singleton(RedisTenancyBootstrapper::class); // todo (Samuel) use proper approach eg config for singleton registration
|
$app->singleton(RedisTenancyBootstrapper::class); // todo (Samuel) use proper approach eg config for singleton registration
|
||||||
$app->singleton(PrefixCacheTenancyBootstrapper::class); // todo (Samuel) use proper approach eg config for singleton registration
|
$app->singleton(PrefixCacheTenancyBootstrapper::class); // todo (Samuel) use proper approach eg config for singleton registration
|
||||||
|
$app->singleton(BroadcastTenancyBootstrapper::class);
|
||||||
$app->singleton(MailTenancyBootstrapper::class);
|
$app->singleton(MailTenancyBootstrapper::class);
|
||||||
|
$app->singleton(UrlTenancyBootstrapper::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getPackageProviders($app)
|
protected function getPackageProviders($app)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue