diff --git a/.env.example b/.env.example
new file mode 100644
index 00000000..55e2e43d
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,3 @@
+# DB_DATABASE=travis_tenancy
+# DB_USERNAME=foo
+# DB_PASSWORD=bar
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index d8a7996a..6733b4e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
+.env
composer.lock
vendor/
diff --git a/.travis.yml b/.travis.yml
index 88e84dda..1e2657b0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,6 @@
+env:
+ - DB_USERNAME=root DB_PASSWORD="" DB_DATABASE=travis_tenancy CODECOV_TOKEN="24382d15-84e7-4a55-bea4-c4df96a24a9b"
+
language: php
php:
- '7.2'
@@ -8,6 +11,7 @@ branches:
- master
services:
+ - mysql
- redis-server
before_install:
@@ -16,8 +20,10 @@ before_install:
install:
- travis_retry composer install --no-interaction
-script: vendor/bin/phpunit --coverage-clover=coverage.xml
+before_script:
+ - mysql -e 'CREATE DATABASE travis_tenancy;'
+
+script: vendor/bin/phpunit -v --coverage-clover=coverage.xml
after_success:
- - export CODECOV_TOKEN="24382d15-84e7-4a55-bea4-c4df96a24a9b"
- bash <(curl -s https://codecov.io/bash)
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 3ee667cf..ca99db8e 100644
--- a/composer.json
+++ b/composer.json
@@ -15,7 +15,8 @@
},
"require-dev": {
"orchestra/testbench": "~3.0",
- "laravel/framework": "5.7.*"
+ "laravel/framework": "5.7.*",
+ "vlucas/phpdotenv": "^2.2"
},
"autoload": {
"psr-4": {
diff --git a/phpunit.xml b/phpunit.xml
index da25c19f..75cb7545 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -29,6 +29,5 @@
-
\ No newline at end of file
diff --git a/src/DatabaseCreators/MySQLDatabaseCreator.php b/src/DatabaseCreators/MySQLDatabaseCreator.php
new file mode 100644
index 00000000..745143d5
--- /dev/null
+++ b/src/DatabaseCreators/MySQLDatabaseCreator.php
@@ -0,0 +1,14 @@
+createTenantConnection($name);
$driver = $driver ?: $this->getDriver();
- if ($driver === "sqlite") {
- $f = fopen(database_path($name), 'w');
- fclose($f);
-
- return;
+
+ $databaseCreators = config('tenancy.database_creators');
+
+ if (! array_key_exists($driver, $databaseCreators)) {
+ throw new \Exception("Database could not be created: no database creator for driver $driver is registered.");
}
- return DB::statement("CREATE DATABASE `$name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
+ if (config('tenancy.queue_database_creation', false)) {
+ QueuedDatabaseCreator::dispatch(app($databaseCreators[$driver]), $name);
+ } else {
+ app($databaseCreators[$driver])->createDatabase($name);
+ }
}
public function delete()
diff --git a/src/Interfaces/DatabaseCreator.php b/src/Interfaces/DatabaseCreator.php
new file mode 100644
index 00000000..9b6fd52a
--- /dev/null
+++ b/src/Interfaces/DatabaseCreator.php
@@ -0,0 +1,14 @@
+databaseCreator = $databaseCreator;
+ $this->databaseName = $databaseName;
+ }
+
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $this->databaseCreator->createDatabase($databaseName);
+ }
+}
diff --git a/src/config/tenancy.php b/src/config/tenancy.php
index 50b6ad75..876c5b65 100644
--- a/src/config/tenancy.php
+++ b/src/config/tenancy.php
@@ -21,7 +21,6 @@ return [
'cache' => [
'prefix_base' => 'tenant',
],
-
'filesystem' => [
'suffix_base' => 'tenant',
// Disks which should be suffixed with the suffix_base + tenant UUID.
@@ -30,4 +29,9 @@ return [
// 's3',
],
],
+ 'database_creators' => [
+ 'sqlite' => 'Stancl\Tenancy\DatabaseCreators\SQLiteDatabaseCreator',
+ 'mysql' => 'Stancl\Tenancy\DatabaseCreators\MySQLDatabaseCreator',
+ ],
+ 'queue_database_creation' => false,
];
diff --git a/tests/DatabaseCreationTest.php b/tests/DatabaseCreationTest.php
new file mode 100644
index 00000000..9b1428d0
--- /dev/null
+++ b/tests/DatabaseCreationTest.php
@@ -0,0 +1,45 @@
+randomString(10) . '.sqlite';
+ app(DatabaseManager::class)->create($db_name, 'sqlite');
+ $this->assertFileExists(database_path($db_name));
+ }
+
+ /** @test */
+ public function mysql_database_is_created()
+ {
+ if (! $this->isTravis()) {
+ $this->markTestSkipped('As to not bloat your MySQL instance with test databases, this test is not run by default.');
+ }
+
+ config()->set('database.default', 'mysql');
+
+ $db_name = 'testdatabase' . $this->randomString(10);
+ app(DatabaseManager::class)->create($db_name, 'mysql');
+ $this->assertNotEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'"));
+ }
+
+ /** @test */
+ public function database_creation_can_be_queued()
+ {
+ Queue::fake();
+
+ config()->set('tenancy.queue_database_creation', true);
+ $db_name = 'testdatabase' . $this->randomString(10) . '.sqlite';
+ app(DatabaseManager::class)->create($db_name, 'sqlite');
+
+ Queue::assertPushed(QueuedDatabaseCreator::class);
+ }
+}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 793eb166..4cc9bdb5 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -30,19 +30,26 @@ class TestCase extends \Orchestra\Testbench\TestCase
*/
protected function getEnvironmentSetUp($app)
{
- $app['config']->set('database.redis.client', 'phpredis');
- $app['config']->set('database.redis.tenancy', [
- 'host' => env('TENANCY_TEST_REDIS_HOST', '127.0.0.1'),
- 'password' => env('TENANCY_TEST_REDIS_PASSWORD', null),
- 'port' => env('TENANCY_TEST_REDIS_PORT', 6379),
- // Use the #14 Redis database unless specified otherwise.
- // Make sure you don't store anything in this db!
- 'database' => env('TENANCY_TEST_REDIS_DB', 14),
- ]);
- $app['config']->set('tenancy.database', [
- 'based_on' => 'sqlite',
- 'prefix' => 'tenant',
- 'suffix' => '.sqlite',
+ if (file_exists(__DIR__ . '/../.env')) {
+ (new \Dotenv\Dotenv(__DIR__ . '/..'))->load();
+ }
+
+ $app['config']->set([
+ 'database.redis.client' => 'phpredis',
+ 'database.redis.tenancy' => [
+ 'host' => env('TENANCY_TEST_REDIS_HOST', '127.0.0.1'),
+ 'password' => env('TENANCY_TEST_REDIS_PASSWORD', null),
+ 'port' => env('TENANCY_TEST_REDIS_PORT', 6379),
+ // Use the #14 Redis database unless specified otherwise.
+ // Make sure you don't store anything in this db!
+ 'database' => env('TENANCY_TEST_REDIS_DB', 14),
+ ],
+ 'tenancy.database' => [
+ 'based_on' => 'sqlite',
+ 'prefix' => 'tenant',
+ 'suffix' => '.sqlite',
+ ],
+ 'database.connections.sqlite.database' => ':memory:',
]);
}
@@ -61,4 +68,16 @@ class TestCase extends \Orchestra\Testbench\TestCase
{
$app->singleton('Illuminate\Contracts\Http\Kernel', HttpKernel::class);
}
+
+ public function randomString(int $length = 10)
+ {
+ return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);
+ }
+
+ public function isTravis()
+ {
+ // Multiple, just to make sure. Someone might accidentally
+ // set one of these environment vars on their computer.
+ return env('CI') && env('TRAVIS') && env('CONTINUOUS_INTEGRATION');
+ }
}