diff --git a/assets/config.php b/assets/config.php index ce1727db..a785bf58 100644 --- a/assets/config.php +++ b/assets/config.php @@ -26,11 +26,10 @@ return [ 'suffix' => '', ], 'redis' => [ - 'tenancy' => false, // to enable Redis tenancy, you must use phpredis 'prefix_base' => 'tenant', 'prefixed_connections' => [ - 'default', - 'cache', + // 'default', + // 'cache', ], ], 'cache' => [ @@ -51,10 +50,14 @@ return [ ], ], 'database_managers' => [ + // Tenant database managers handle the creation & deletion of tenant databases. 'sqlite' => 'Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager', 'mysql' => 'Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager', 'pgsql' => 'Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager', ], + 'tenancy_bootstrappers' => [ + '' + ], 'queue_database_creation' => false, 'queue_database_deletion' => false, 'unique_id_generator' => 'Stancl\Tenancy\UUIDGenerator', diff --git a/composer.json b/composer.json index 3ca36b70..6348a703 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,7 @@ ], "require": { "illuminate/support": "5.8.*", - "webpatser/laravel-uuid": "^3.0", - "predis/predis": "^1.1" + "webpatser/laravel-uuid": "^3.0" }, "require-dev": { "vlucas/phpdotenv": "^3.3", diff --git a/src/Contracts/Tenant.php b/src/Contracts/Tenant.php new file mode 100644 index 00000000..85b2cbb3 --- /dev/null +++ b/src/Contracts/Tenant.php @@ -0,0 +1,6 @@ +originalCache = $this->originalCache ?? $this->app['cache']; + $this->app->extend('cache', function () { + return new CacheManager($this->app); + }); + } + + public function end() + { + $this->app->extend('cache', function () { + return $this->originalCache; + }); + } +} \ No newline at end of file diff --git a/src/TenancyBootstrappers/FilesystemTenancyBootstrapper.php b/src/TenancyBootstrappers/FilesystemTenancyBootstrapper.php new file mode 100644 index 00000000..6c911eec --- /dev/null +++ b/src/TenancyBootstrappers/FilesystemTenancyBootstrapper.php @@ -0,0 +1,57 @@ +app = $app; + $this->originalPaths = [ + 'disks' => [], + 'path' => $this->app->storagePath(), + ]; + } + + public function start() + { + // todo revisit this + $suffix = $this->app['config']['tenancy.filesystem.suffix_base'] . tenant('uuid'); + + // storage_path() + $this->app->useStoragePath($this->originalPaths['path'] . "/{$suffix}"); + + // Storage facade + foreach ($this->app['config']['tenancy.filesystem.disks'] as $disk) { + $this->originalPaths['disks'][$disk] = Storage::disk($disk)->getAdapter()->getPathPrefix(); + + if ($root = \str_replace('%storage_path%', storage_path(), $this->app['config']["tenancy.filesystem.root_override.{$disk}"])) { + Storage::disk($disk)->getAdapter()->setPathPrefix($root); + } else { + $root = $this->app['config']["filesystems.disks.{$disk}.root"]; + + Storage::disk($disk)->getAdapter()->setPathPrefix($root . "/{$suffix}"); + } + } + } + + public function end() + { + // storage_path() + $this->app->useStoragePath($this->originalPaths['path']); + + // Storage facade + foreach ($this->app['config']['tenancy.filesystem.disks'] as $disk) { + Storage::disk($disk)->getAdapter()->setPathPrefix($this->originalPaths['disks'][$disk]); + } + } +} \ No newline at end of file diff --git a/src/TenancyBootstrappers/RedisTenancyBootstrapper.php b/src/TenancyBootstrappers/RedisTenancyBootstrapper.php new file mode 100644 index 00000000..a16ee64c --- /dev/null +++ b/src/TenancyBootstrappers/RedisTenancyBootstrapper.php @@ -0,0 +1,44 @@ +app = $app; + } + + public function start() + { + foreach ($this->prefixedConnections() as $connection) { + $prefix = $this->app['config']['tenancy.redis.prefix_base'] . $this->tenant['uuid']; + $client = Redis::connection($connection)->client(); + + $this->originalPrefixes[$connection] = $client->getOption($client::OPT_PREFIX); + $client->setOption($client::OPT_PREFIX, $prefix); + } + } + + public function end() + { + foreach ($this->prefixedConnections() as $connection) { + $client = Redis::connection($connection)->client(); + + $client->setOption($client::OPT_PREFIX, $this->originalPrefixes[$connection]); + } + } + + protected function prefixedConnections() + { + return config('tenancy.redis.prefixed_connections'); + } +} \ No newline at end of file diff --git a/src/TenancyServiceProvider.php b/src/TenancyServiceProvider.php index 8d60d09e..849c071f 100644 --- a/src/TenancyServiceProvider.php +++ b/src/TenancyServiceProvider.php @@ -132,6 +132,8 @@ class TenancyServiceProvider extends ServiceProvider ); }); + // todo foreach bootstrappers, singleton + $this->app->singleton(Migrate::class, function ($app) { return new Migrate($app['migrator'], $app[DatabaseManager::class]); }); diff --git a/src/Tenant.php b/src/Tenant.php index 636efc0d..f5447378 100644 --- a/src/Tenant.php +++ b/src/Tenant.php @@ -6,12 +6,10 @@ namespace Stancl\Tenancy; use ArrayAccess; -// todo laravel events instead of custom events? - /** * @internal Class is subject to breaking changes in minor and patch versions. */ -class Tenant implements ArrayAccess +class Tenant implements ArrayAccess, Contracts\Tenant { use Traits\HasArrayAccess; @@ -56,7 +54,7 @@ class Tenant implements ArrayAccess return app(static::class)->withData($data)->persisted(); } - public function persisted() + protected function persisted() { $this->persisted = true; diff --git a/src/TenantManagerv2.php b/src/TenantManagerv2.php index 47e75896..7036c965 100644 --- a/src/TenantManagerv2.php +++ b/src/TenantManagerv2.php @@ -55,7 +55,16 @@ class TenantManagerv2 public function bootstrapTenancy(Tenant $tenant): self { foreach($this->tenancyBootstrappers() as $bootstrapper) { - $bootstrapper::start($tenant); + $this->app[$bootstrapper]->start($tenant); + } + + return $this; + } + + public function endTenancy(): self + { + foreach($this->tenancyBootstrappers() as $bootstrapper) { + $this->app[$bootstrapper]->end(); } return $this; diff --git a/src/TenantModel.php b/src/TenantModel.php index bf598450..49e94047 100644 --- a/src/TenantModel.php +++ b/src/TenantModel.php @@ -6,6 +6,8 @@ namespace Stancl\Tenancy; use Illuminate\Database\Eloquent\Model; +// todo move this to a database driver domain? + /** * @final Class is subject to breaking changes in minor and patch versions. */ diff --git a/test b/test index 822b6d4b..52437596 100755 --- a/test +++ b/test @@ -4,9 +4,7 @@ set -e # for development docker-compose up -d printf "Variant 1\n\n" -docker-compose exec test env TENANCY_TEST_REDIS_TENANCY=1 TENANCY_TEST_REDIS_CLIENT=phpredis TENANCY_TEST_STORAGE_DRIVER=redis vendor/bin/phpunit --coverage-php coverage/1.cov "$@" +docker-compose exec test env TENANCY_TEST_STORAGE_DRIVER=redis vendor/bin/phpunit --coverage-php coverage/1.cov "$@" printf "Variant 2\n\n" -docker-compose exec test env TENANCY_TEST_REDIS_TENANCY=0 TENANCY_TEST_REDIS_CLIENT=predis TENANCY_TEST_STORAGE_DRIVER=redis vendor/bin/phpunit --coverage-php coverage/2.cov "$@" -printf "Variant 3\n\n" -docker-compose exec test env TENANCY_TEST_REDIS_TENANCY=1 TENANCY_TEST_REDIS_CLIENT=phpredis TENANCY_TEST_STORAGE_DRIVER=db vendor/bin/phpunit --coverage-php coverage/3.cov "$@" +docker-compose exec test env TENANCY_TEST_STORAGE_DRIVER=db vendor/bin/phpunit --coverage-php coverage/3.cov "$@" docker-compose exec test vendor/bin/phpcov merge --clover clover.xml coverage/ diff --git a/tests/BootstrapsTenancyTest.php b/tests/BootstrapsTenancyTest.php index f83f4dea..fae9e1f2 100644 --- a/tests/BootstrapsTenancyTest.php +++ b/tests/BootstrapsTenancyTest.php @@ -6,7 +6,6 @@ namespace Stancl\Tenancy\Tests; use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Config; -use Stancl\Tenancy\Exceptions\PhpRedisNotInstalledException; class BootstrapsTenancyTest extends TestCase { @@ -38,28 +37,6 @@ class BootstrapsTenancyTest extends TestCase } } - /** @test */ - public function predis_is_supported() - { - Config::set('database.redis.client', 'predis'); - Redis::setDriver('predis'); - Config::set('tenancy.redis.tenancy', false); - - // assert no exception is thrown from initializing tenancy - $this->assertNotNull($this->initTenancy()); - } - - /** @test */ - public function predis_is_not_supported_without_disabling_redis_multitenancy() - { - Config::set('database.redis.client', 'predis'); - Redis::setDriver('predis'); - Config::set('tenancy.redis.tenancy', true); - - $this->expectException(PhpRedisNotInstalledException::class); - $this->initTenancy(); - } - /** @test */ public function filesystem_is_suffixed() {