diff --git a/src/Generators/Webserver/Database/DatabaseDriverFactory.php b/src/Generators/Webserver/Database/DatabaseDriverFactory.php new file mode 100644 index 00000000..dac1a718 --- /dev/null +++ b/src/Generators/Webserver/Database/DatabaseDriverFactory.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @see https://laravel-tenancy.com + * @see https://github.com/hyn/multi-tenant + */ + +namespace Hyn\Tenancy\Generators\Webserver\Database; + +use Hyn\Tenancy\Exceptions\GeneratorFailedException; +use Hyn\Tenancy\Contracts\Webserver\DatabaseGenerator; + +class DatabaseDriverFactory +{ + public function create($driver = 'mysql') : DatabaseGenerator + { + $drivers = app('tenancy.db.drivers'); + + if (!in_array($driver, $drivers->keys()->toArray())) { + throw new GeneratorFailedException("Could not generate database for driver $driver"); + } + + return new $drivers[$driver](); + } +} diff --git a/src/Generators/Webserver/Database/DatabaseGenerator.php b/src/Generators/Webserver/Database/DatabaseGenerator.php index 0c404864..6fb9cecf 100644 --- a/src/Generators/Webserver/Database/DatabaseGenerator.php +++ b/src/Generators/Webserver/Database/DatabaseGenerator.php @@ -35,14 +35,21 @@ class DatabaseGenerator */ protected $mode; + /** + * @var DatabaseDriverFactory + */ + protected $factory; + /** * DatabaseGenerator constructor. * @param Connection $connection + * @param DatabaseDriverFactory $factory */ - public function __construct(Connection $connection) + public function __construct(Connection $connection, DatabaseDriverFactory $factory) { $this->connection = $connection; $this->mode = config('tenancy.db.tenant-division-mode'); + $this->factory = $factory; } /** @@ -55,29 +62,6 @@ public function subscribe(Dispatcher $events) $events->listen(Events\Websites\Deleted::class, [$this, 'deleted']); } - /** - * @param array $config - * @return \Hyn\Tenancy\Contracts\Webserver\DatabaseGenerator - * @throws GeneratorFailedException - */ - protected function driver(array $config) - { - $driver = Arr::get($config, 'driver', 'mysql'); - - switch ($driver) { - case 'pgsql': - return $this->mode === Connection::DIVISION_MODE_SEPARATE_SCHEMA - ? new Drivers\PostgresSchema - : new Drivers\PostgreSQL; - break; - case 'mysql': - return new Drivers\MariaDB; - break; - default: - throw new GeneratorFailedException("Could not generate database for driver $driver"); - } - } - /** * @param Events\Websites\Created $event * @throws GeneratorFailedException @@ -103,7 +87,7 @@ public function created(Events\Websites\Created $event) new Events\Database\Creating($config, $event->website) ); - if (!$this->driver($config)->created($event, $config, $this->connection)) { + if (!$this->factory->create($config['driver'])->created($event, $config, $this->connection)) { throw new GeneratorFailedException("Could not generate database {$config['database']}, one of the statements failed."); } @@ -151,7 +135,7 @@ public function deleted(Events\Websites\Deleted $event) new Events\Database\Deleting($config, $event->website) ); - if (!$this->driver($config)->deleted($event, $config, $this->connection)) { + if (!$this->factory->create($config['driver'])->deleted($event, $config, $this->connection)) { throw new GeneratorFailedException("Could not delete database {$config['database']}, the statement failed."); } @@ -191,7 +175,7 @@ public function updated(Events\Websites\Updated $event) new Events\Database\Renaming($config, $event->website) ); - if (!$this->driver($config)->updated($event, $config, $this->connection)) { + if (!$this->factory->create($config['driver'])->updated($event, $config, $this->connection)) { throw new GeneratorFailedException("Could not rename database {$config['database']}, the statement failed."); } diff --git a/src/Providers/TenancyProvider.php b/src/Providers/TenancyProvider.php index 5adad974..773dd86c 100644 --- a/src/Providers/TenancyProvider.php +++ b/src/Providers/TenancyProvider.php @@ -88,6 +88,7 @@ protected function registerProviders() $this->app->register(Providers\BusProvider::class); $this->app->register(Providers\FilesystemProvider::class); $this->app->register(Providers\HostnameProvider::class); + $this->app->register(Providers\DatabaseDriverProvider::class); // Register last. $this->app->register(Providers\EventProvider::class); diff --git a/src/Providers/Tenants/DatabaseDriverProvider.php b/src/Providers/Tenants/DatabaseDriverProvider.php new file mode 100644 index 00000000..2f6ce0b8 --- /dev/null +++ b/src/Providers/Tenants/DatabaseDriverProvider.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @see https://laravel-tenancy.com + * @see https://github.com/hyn/multi-tenant + */ + +namespace Hyn\Tenancy\Providers\Tenants; + +use Hyn\Tenancy\Database\Connection; +use Hyn\Tenancy\Generators\Webserver\Database\DatabaseDriverFactory; +use Hyn\Tenancy\Generators\Webserver\Database\Drivers\MariaDB; +use Hyn\Tenancy\Generators\Webserver\Database\Drivers\PostgreSQL; +use Hyn\Tenancy\Generators\Webserver\Database\Drivers\PostgresSchema; +use Illuminate\Support\ServiceProvider; + +class DatabaseDriverProvider extends ServiceProvider +{ + public function register() + { + $this->app->singleton('tenancy.db.drivers', function () { + return collect($this->drivers()); + }); + + $this->app->singleton(DatabaseDriverFactory::class); + } + + private function drivers() + { + $isPgsqlSchema = config('tenancy.db.tenant-division-mode') === Connection::DIVISION_MODE_SEPARATE_SCHEMA; + + return [ + 'pgsql' => $isPgsqlSchema ? PostgresSchema::class : PostgreSQL::class, + 'mysql' => MariaDB::class, + ]; + } +} diff --git a/tests/extend/DatabaseDriverExtend.php b/tests/extend/DatabaseDriverExtend.php new file mode 100644 index 00000000..85877b0a --- /dev/null +++ b/tests/extend/DatabaseDriverExtend.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @see https://laravel-tenancy.com + * @see https://github.com/hyn/multi-tenant + */ + +namespace Hyn\Tenancy\Tests\Extend; + +use Hyn\Tenancy\Events\Websites\Created; +use Hyn\Tenancy\Events\Websites\Deleted; +use Hyn\Tenancy\Events\Websites\Updated; +use Hyn\Tenancy\Contracts\Webserver\DatabaseGenerator; +use Hyn\Tenancy\Database\Connection; + +class DatabaseDriverExtend implements DatabaseGenerator +{ + public function created(Created $event, array $config, Connection $connection): bool + { + return true; + } + + public function updated(Updated $event, array $config, Connection $connection): bool + { + return true; + } + + public function deleted(Deleted $event, array $config, Connection $connection): bool + { + return true; + } +} diff --git a/tests/unit-tests/Generators/Webserver/Database/DatabaseDriverFactoryTest.php b/tests/unit-tests/Generators/Webserver/Database/DatabaseDriverFactoryTest.php new file mode 100644 index 00000000..508fbfd0 --- /dev/null +++ b/tests/unit-tests/Generators/Webserver/Database/DatabaseDriverFactoryTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @see https://laravel-tenancy.com + * @see https://github.com/hyn/multi-tenant + */ + +namespace Hyn\Tenancy\Tests\Generators\Webserver\Database; + +use Hyn\Tenancy\Generators\Webserver\Database\DatabaseDriverFactory; +use Hyn\Tenancy\Generators\Webserver\Database\Drivers\MariaDB; +use Hyn\Tenancy\Tests\Test; +use Hyn\Tenancy\Tests\Extend\DatabaseDriverExtend; + +class DatabaseDriverFactoryTest extends Test +{ + /** + * @test + */ + public function creates_mysql_driver_by_default() + { + $driver = (new DatabaseDriverFactory())->create(); + + $this->assertInstanceOf(MariaDB::class, $driver); + } + + /** + * @test + * @expectedException \Hyn\Tenancy\Exceptions\GeneratorFailedException + */ + public function throws_an_exception_if_driver_doesnt_exist() + { + (new DatabaseDriverFactory())->create('non-existing-driver'); + } + + /** + * @test + * @expectedException \TypeError + */ + public function throws_an_exception_if_driver_doesnt_implement_contract() + { + app('tenancy.db.drivers')->put('random', \stdClass::class); + + (new DatabaseDriverFactory())->create('random'); + } + + /** + * @test + */ + public function allows_to_create_custom_driver() + { + app('tenancy.db.drivers')->put('custom', DatabaseDriverExtend::class); + + $this->assertInstanceOf(DatabaseDriverExtend::class, (new DatabaseDriverFactory())->create('custom')); + } +}