From 353f7afb82bb66a0b48c9bf001bcb5e550b73cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Sat, 13 Jul 2019 11:38:07 +0200 Subject: [PATCH] Add tenancy()->end() (#68) --- src/TenantManager.php | 1 + src/Traits/BootstrapsTenancy.php | 59 +++++++++++++++++++++--- tests/TenantManagerTest.php | 79 ++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 7 deletions(-) diff --git a/src/TenantManager.php b/src/TenantManager.php index 86ae6ccd..8299ee15 100644 --- a/src/TenantManager.php +++ b/src/TenantManager.php @@ -185,6 +185,7 @@ class TenantManager /** * Reconnects to the default database. + * @todo More descriptive name? * * @return void */ diff --git a/src/Traits/BootstrapsTenancy.php b/src/Traits/BootstrapsTenancy.php index 1121cc73..18e29f79 100644 --- a/src/Traits/BootstrapsTenancy.php +++ b/src/Traits/BootstrapsTenancy.php @@ -21,6 +21,16 @@ trait BootstrapsTenancy $this->suffixFilesystemRootPaths(); } + public function end() + { + $this->disconnectDatabase(); + if ($this->app['config']['tenancy.redis.tenancy']) { + $this->resetPhpRedisPrefix($this->app['config']['tenancy.redis.prefixed_connections']); + } + $this->untagCache(); + $this->resetFileSystemRootPaths(); + } + public function switchDatabaseConnection() { $this->database->connect($this->getDatabaseName()); @@ -28,10 +38,14 @@ trait BootstrapsTenancy public function setPhpRedisPrefix($connections = ['default']) { + $this->originalSettings['redis'] = $this->originalSettings['redis'] ?? []; + foreach ($connections as $connection) { $prefix = $this->app['config']['tenancy.redis.prefix_base'] . $this->tenant['uuid']; $client = Redis::connection($connection)->client(); + try { + $this->originalSettings['redis'][$connection] = $client->getOption($client::OPT_PREFIX); $client->setOption($client::OPT_PREFIX, $prefix); } catch (\Throwable $t) { throw new PhpRedisNotInstalledException(); @@ -39,27 +53,49 @@ trait BootstrapsTenancy } } + public function resetPhpRedisPrefix($connections = ['default']) { + foreach ($connections as $connection) { + $client = Redis::connection($connection)->client(); + + try { + $client->setOption($client::OPT_PREFIX, $this->originalSettings['redis'][$connection]); + } catch (\Throwable $t) { + throw new PhpRedisNotInstalledException(); + } + } + } + public function tagCache() { + $this->originalSettings['cache'] = $this->app['cache']; $this->app->extend('cache', function () { return new CacheManager($this->app); }); } + public function untagCache() + { + $this->app->extend('cache', function () { + return $this->originalSettings['cache']; + }); + } + public function suffixFilesystemRootPaths() { - $old = $this->originalSettings ?: [ - "storage_disks" => [], - "storage_path" => $this->app->storagePath(), + $old = $this->originalSettings['storage'] ?? [ + 'disks' => [], + 'path' => $this->app->storagePath(), ]; $suffix = $this->app['config']['tenancy.filesystem.suffix_base'] . tenant('uuid'); // storage_path() - $this->app->useStoragePath($old['storage_path'] . "/{$suffix}"); + $this->app->useStoragePath($old['path'] . "/{$suffix}"); // Storage facade foreach ($this->app['config']['tenancy.filesystem.disks'] as $disk) { + $old['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 { @@ -67,10 +103,19 @@ trait BootstrapsTenancy Storage::disk($disk)->getAdapter()->setPathPrefix($root . "/{$suffix}"); } - - $old['storage_disks'][$disk] = $root; } - $this->originalSettings = $old; + $this->originalSettings['storage'] = $old; + } + + public function resetFilesystemRootPaths() + { + // storage_path() + $this->app->useStoragePath($this->originalSettings['storage']['path']); + + // Storage facade + foreach ($this->app['config']['tenancy.filesystem.disks'] as $disk) { + Storage::disk($disk)->getAdapter()->setPathPrefix($this->originalSettings['storage']['disks'][$disk]); + } } } diff --git a/tests/TenantManagerTest.php b/tests/TenantManagerTest.php index aa4295dc..45db2b62 100644 --- a/tests/TenantManagerTest.php +++ b/tests/TenantManagerTest.php @@ -2,6 +2,9 @@ namespace Stancl\Tenancy\Tests; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Storage; + class TenantManagerTest extends TestCase { public $autoCreateTenant = false; @@ -98,4 +101,80 @@ class TenantManagerTest extends TestCase $this->expectException(\Exception::class); tenancy()->findByDomain('nonexistent.domain'); } + + /** @test */ + public function tenancy_can_be_ended() + { + $originals = [ + 'databasePDO' => DB::connection()->getPDO(), + 'databaseName' => DB::connection()->getDatabaseName(), + 'storage_path' => storage_path(), + 'storage_root' => Storage::disk('local')->getAdapter()->getPathPrefix(), + 'cache' => app('cache'), + ]; + + // Verify that these assertions are the right way for testing this + $this->assertSame($originals['databaseName'], DB::connection()->getDatabaseName()); + $this->assertSame($originals['storage_path'], storage_path()); + $this->assertSame($originals['storage_root'], Storage::disk('local')->getAdapter()->getPathPrefix()); + $this->assertSame($originals['cache'], app('cache')); + + tenant()->create('foo.localhost'); + tenancy()->init('foo.localhost'); + + $this->assertNotSame($originals['databaseName'], DB::connection()->getDatabaseName()); + $this->assertNotSame($originals['storage_path'], storage_path()); + $this->assertNotSame($originals['storage_root'], Storage::disk('local')->getAdapter()->getPathPrefix()); + $this->assertNotSame($originals['cache'], app('cache')); + + tenancy()->end(); + + $this->assertSame($originals['databaseName'], DB::connection()->getDatabaseName()); + $this->assertSame($originals['storage_path'], storage_path()); + $this->assertSame($originals['storage_root'], Storage::disk('local')->getAdapter()->getPathPrefix()); + $this->assertSame($originals['cache'], app('cache')); + } + + /** @test */ + public function tenancy_can_be_ended_after_reidentification() + { + $originals = [ + 'databasePDO' => DB::connection()->getPDO(), + 'databaseName' => DB::connection()->getDatabaseName(), + 'storage_path' => storage_path(), + 'storage_root' => Storage::disk('local')->getAdapter()->getPathPrefix(), + 'cache' => app('cache'), + ]; + + tenant()->create('foo.localhost'); + tenancy()->init('foo.localhost'); + + $this->assertNotSame($originals['databaseName'], DB::connection()->getDatabaseName()); + $this->assertNotSame($originals['storage_path'], storage_path()); + $this->assertNotSame($originals['storage_root'], Storage::disk('local')->getAdapter()->getPathPrefix()); + $this->assertNotSame($originals['cache'], app('cache')); + + tenancy()->end(); + + $this->assertSame($originals['databaseName'], DB::connection()->getDatabaseName()); + $this->assertSame($originals['storage_path'], storage_path()); + $this->assertSame($originals['storage_root'], Storage::disk('local')->getAdapter()->getPathPrefix()); + $this->assertSame($originals['cache'], app('cache')); + + // Reidentify tenant + tenant()->create('bar.localhost'); + tenancy()->init('bar.localhost'); + + $this->assertNotSame($originals['databaseName'], DB::connection()->getDatabaseName()); + $this->assertNotSame($originals['storage_path'], storage_path()); + $this->assertNotSame($originals['storage_root'], Storage::disk('local')->getAdapter()->getPathPrefix()); + $this->assertNotSame($originals['cache'], app('cache')); + + tenancy()->end(); + + $this->assertSame($originals['databaseName'], DB::connection()->getDatabaseName()); + $this->assertSame($originals['storage_path'], storage_path()); + $this->assertSame($originals['storage_root'], Storage::disk('local')->getAdapter()->getPathPrefix()); + $this->assertSame($originals['cache'], app('cache')); + } }