mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 09:54:03 +00:00
[1.7.0] Add DB storage driver (#82)
This commit is contained in:
parent
674f4b3f9a
commit
9df78eb9c2
13 changed files with 375 additions and 25 deletions
30
README.md
30
README.md
|
|
@ -366,7 +366,35 @@ Note that deleting a tenant doesn't delete his database. You can do this manuall
|
||||||
|
|
||||||
## Storage driver
|
## Storage driver
|
||||||
|
|
||||||
Currently, only Redis is supported, but you're free to code your own storage driver which follows the `Stancl\Tenancy\Interfaces\StorageDriver` interface. Just point the `tenancy.storage_driver` setting at your driver.
|
### Database
|
||||||
|
|
||||||
|
The database storage driver lets you store information about tenants in a relational database like MySQL, PostgreSQL and SQLite.
|
||||||
|
|
||||||
|
To use this storage driver, publish the `create_tenants_table` migration:
|
||||||
|
|
||||||
|
```
|
||||||
|
php artisan vendor:publish --provider='Stancl\Tenancy\TenancyServiceProvider' --tag=migrations
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the table contains only `uuid`, `domain` and `data` columns.
|
||||||
|
|
||||||
|
The `data` column is used to store information about a tenant, such as their selected plan, in JSON form. This package does not store anything in the column by default.
|
||||||
|
|
||||||
|
You can store specific keys in your own columns. This is useful if you want to use RDBMS features like indexes.
|
||||||
|
|
||||||
|
If you don't need any custom columns, you can skip the next section and run:
|
||||||
|
|
||||||
|
```
|
||||||
|
php artisan migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Adding your own columns
|
||||||
|
|
||||||
|
To add your own columns, TODO.
|
||||||
|
|
||||||
|
### Redis
|
||||||
|
|
||||||
|
Using Redis as your storage driver is recommended due to its low overhead compared to a relational database like MySQL.
|
||||||
|
|
||||||
**Note that you need to configure persistence on your Redis instance** if you don't want to lose all information about tenants.
|
**Note that you need to configure persistence on your Redis instance** if you don't want to lose all information about tenants.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,25 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'storage_driver' => 'Stancl\Tenancy\StorageDrivers\RedisStorageDriver',
|
'storage_driver' => 'Stancl\Tenancy\StorageDrivers\DatabaseStorageDriver',
|
||||||
|
'storage' => [
|
||||||
|
'db' => [ // Stancl\Tenancy\StorageDrivers\DatabaseStorageDriver
|
||||||
|
'data_column' => 'data',
|
||||||
|
'custom_columns' => [
|
||||||
|
// 'plan',
|
||||||
|
],
|
||||||
|
'connection' => 'central',
|
||||||
|
],
|
||||||
|
'redis' => [ // Stancl\Tenancy\StorageDrivers\RedisStorageDriver
|
||||||
|
'connection' => 'tenancy',
|
||||||
|
],
|
||||||
|
],
|
||||||
'tenant_route_namespace' => 'App\Http\Controllers',
|
'tenant_route_namespace' => 'App\Http\Controllers',
|
||||||
'exempt_domains' => [
|
'exempt_domains' => [
|
||||||
// 'localhost',
|
// 'localhost',
|
||||||
],
|
],
|
||||||
'database' => [
|
'database' => [
|
||||||
'based_on' => 'mysql',
|
'based_on' => 'sqlite',
|
||||||
'prefix' => 'tenant',
|
'prefix' => 'tenant',
|
||||||
'suffix' => '',
|
'suffix' => '',
|
||||||
],
|
],
|
||||||
35
assets/migrations/2019_08_08_000000_create_tenants_table.php
Normal file
35
assets/migrations/2019_08_08_000000_create_tenants_table.php
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateTenantsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('tenants', function (Blueprint $table) {
|
||||||
|
$table->string('uuid', 36)->primary(); // don't change this
|
||||||
|
$table->string('domain', 255)->index(); // don't change this
|
||||||
|
|
||||||
|
// your indexed columns go here
|
||||||
|
|
||||||
|
$table->json('data')->default('{}');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::drop('tenants');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ interface StorageDriver
|
||||||
{
|
{
|
||||||
public function identifyTenant(string $domain): array;
|
public function identifyTenant(string $domain): array;
|
||||||
|
|
||||||
|
/** @return array[] */
|
||||||
public function getAllTenants(array $uuids = []): array;
|
public function getAllTenants(array $uuids = []): array;
|
||||||
|
|
||||||
public function getTenantById(string $uuid, array $fields = []): array;
|
public function getTenantById(string $uuid, array $fields = []): array;
|
||||||
|
|
|
||||||
84
src/StorageDrivers/DatabaseStorageDriver.php
Normal file
84
src/StorageDrivers/DatabaseStorageDriver.php
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\StorageDrivers;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
use Stancl\Tenancy\Interfaces\StorageDriver;
|
||||||
|
|
||||||
|
class DatabaseStorageDriver implements StorageDriver
|
||||||
|
{
|
||||||
|
public $useJson = false;
|
||||||
|
|
||||||
|
// todo use an instance of tenant model?
|
||||||
|
// todo write tests verifying that data is decoded and added to the array
|
||||||
|
|
||||||
|
public function identifyTenant(string $domain): array
|
||||||
|
{
|
||||||
|
$id = $this->getTenantIdByDomain($domain);
|
||||||
|
if (! $id) {
|
||||||
|
throw new \Exception("Tenant could not be identified on domain {$domain}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getTenantById($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about the tenant based on his uuid.
|
||||||
|
*
|
||||||
|
* @param string $uuid
|
||||||
|
* @param array $fields
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTenantById(string $uuid, array $fields = []): array
|
||||||
|
{
|
||||||
|
if ($fields) {
|
||||||
|
return Tenant::decodeData(Tenant::find($uuid)->only($fields));
|
||||||
|
} else {
|
||||||
|
return Tenant::find($uuid)->decoded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTenantIdByDomain(string $domain): ?string
|
||||||
|
{
|
||||||
|
return Tenant::where('domain', $domain)->first()->uuid ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createTenant(string $domain, string $uuid): array
|
||||||
|
{
|
||||||
|
return Tenant::create(['uuid' => $uuid, 'domain' => $domain])->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteTenant(string $id): bool
|
||||||
|
{
|
||||||
|
return Tenant::find($id)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllTenants(array $uuids = []): array
|
||||||
|
{
|
||||||
|
return Tenant::getAllTenants($uuids)->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $uuid, string $key)
|
||||||
|
{
|
||||||
|
return Tenant::find($uuid)->get($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMany(string $uuid, array $keys): array
|
||||||
|
{
|
||||||
|
return Tenant::find($uuid)->getMany($keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function put(string $uuid, string $key, $value)
|
||||||
|
{
|
||||||
|
return Tenant::find($uuid)->put($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function putMany(string $uuid, array $values): array
|
||||||
|
{
|
||||||
|
foreach ($values as $key => $value) {
|
||||||
|
Tenant::find($uuid)->put($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ class RedisStorageDriver implements StorageDriver
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->redis = Redis::connection('tenancy');
|
$this->redis = Redis::connection(config('tenancy.redis.connection', 'tenancy'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function identifyTenant(string $domain): array
|
public function identifyTenant(string $domain): array
|
||||||
|
|
@ -33,8 +33,6 @@ class RedisStorageDriver implements StorageDriver
|
||||||
*/
|
*/
|
||||||
public function getTenantById(string $uuid, array $fields = []): array
|
public function getTenantById(string $uuid, array $fields = []): array
|
||||||
{
|
{
|
||||||
$fields = (array) $fields;
|
|
||||||
|
|
||||||
if (! $fields) {
|
if (! $fields) {
|
||||||
return $this->redis->hgetall("tenants:$uuid");
|
return $this->redis->hgetall("tenants:$uuid");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,13 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->publishes([
|
$this->publishes([
|
||||||
__DIR__ . '/config/tenancy.php' => config_path('tenancy.php'),
|
__DIR__ . '/../assets/config.php' => config_path('tenancy.php'),
|
||||||
], 'config');
|
], 'config');
|
||||||
|
|
||||||
|
$this->publishes([
|
||||||
|
__DIR__ . '/../assets/migrations/' => database_path('migrations'),
|
||||||
|
], 'migrations');
|
||||||
|
|
||||||
$this->loadRoutesFrom(__DIR__ . '/routes.php');
|
$this->loadRoutesFrom(__DIR__ . '/routes.php');
|
||||||
|
|
||||||
Route::middlewareGroup('tenancy', [
|
Route::middlewareGroup('tenancy', [
|
||||||
|
|
@ -52,7 +56,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->mergeConfigFrom(__DIR__ . '/config/tenancy.php', 'tenancy');
|
$this->mergeConfigFrom(__DIR__ . '/../assets/config.php', 'tenancy');
|
||||||
|
|
||||||
$this->app->bind(StorageDriver::class, $this->app['config']['tenancy.storage_driver']);
|
$this->app->bind(StorageDriver::class, $this->app['config']['tenancy.storage_driver']);
|
||||||
$this->app->bind(ServerConfigManager::class, $this->app['config']['tenancy.server.manager']);
|
$this->app->bind(ServerConfigManager::class, $this->app['config']['tenancy.server.manager']);
|
||||||
|
|
|
||||||
102
src/Tenant.php
Normal file
102
src/Tenant.php
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Tenant extends Model
|
||||||
|
{
|
||||||
|
protected $guarded = [];
|
||||||
|
protected $primaryKey = 'uuid';
|
||||||
|
public $incrementing = false;
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decoded data from the data column.
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
private $dataObject;
|
||||||
|
|
||||||
|
public static function dataColumn()
|
||||||
|
{
|
||||||
|
return config('tenancy.storage.db.data_column', 'data');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function customColumns()
|
||||||
|
{
|
||||||
|
return config('tenancy.storage.db.custom_columns', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConnectionName()
|
||||||
|
{
|
||||||
|
return config('tenancy.storage.db.connection', 'central');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getAllTenants(array $uuids)
|
||||||
|
{
|
||||||
|
$tenants = $uuids ? static::findMany($uuids) : static::all();
|
||||||
|
|
||||||
|
return $tenants->map([__CLASS__, 'decodeData'])->toBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function decoded()
|
||||||
|
{
|
||||||
|
return static::decodeData($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a tenant array with data decoded into separate keys.
|
||||||
|
*
|
||||||
|
* @param Tenant|array $tenant
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function decodeData($tenant)
|
||||||
|
{
|
||||||
|
$tenant = $tenant instanceof self ? (array) $tenant->attributes : $tenant;
|
||||||
|
$decoded = json_decode($tenant[$dataColumn = static::dataColumn()], true);
|
||||||
|
|
||||||
|
foreach ($decoded as $key => $value) {
|
||||||
|
$tenant[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If $tenant[$dataColumn] has been overriden by a value, don't delete the key.
|
||||||
|
if (! array_key_exists($dataColumn, $decoded)) {
|
||||||
|
unset($tenant[$dataColumn]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFromData(string $key)
|
||||||
|
{
|
||||||
|
$this->dataArray = $this->dataArray ?? json_decode($this->{$this->dataColumn()}, true);
|
||||||
|
|
||||||
|
return $this->dataArray[$key] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $key)
|
||||||
|
{
|
||||||
|
return $this->$key ?? $this->getFromData($key) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @todo In v2, this should return an associative array. */
|
||||||
|
public function getMany(array $keys): array
|
||||||
|
{
|
||||||
|
return array_map([$this, 'get'], $keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function put(string $key, $value)
|
||||||
|
{
|
||||||
|
if (array_key_exists($key, $this->customColumns())) {
|
||||||
|
$this->update([$key => $value]);
|
||||||
|
} else {
|
||||||
|
$obj = json_decode($this->{$this->dataColumn()});
|
||||||
|
$obj->$key = $value;
|
||||||
|
|
||||||
|
$this->update([$this->dataColumn() => json_encode($obj)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ final class TenantManager
|
||||||
*
|
*
|
||||||
* @var StorageDriver
|
* @var StorageDriver
|
||||||
*/
|
*/
|
||||||
protected $storage;
|
public $storage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database manager.
|
* Database manager.
|
||||||
|
|
@ -86,7 +86,10 @@ final class TenantManager
|
||||||
throw new \Exception("Domain $domain is already occupied by tenant $id.");
|
throw new \Exception("Domain $domain is already occupied by tenant $id.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$tenant = $this->jsonDecodeArrayValues($this->storage->createTenant($domain, (string) \Webpatser\Uuid\Uuid::generate(1, $domain)));
|
$tenant = $this->storage->createTenant($domain, (string) \Webpatser\Uuid\Uuid::generate(1, $domain));
|
||||||
|
if ($this->useJson()) {
|
||||||
|
$tenant = $this->jsonDecodeArrayValues($tenant);
|
||||||
|
}
|
||||||
|
|
||||||
if ($data) {
|
if ($data) {
|
||||||
$this->put($data, null, $tenant['uuid']);
|
$this->put($data, null, $tenant['uuid']);
|
||||||
|
|
@ -115,7 +118,12 @@ final class TenantManager
|
||||||
{
|
{
|
||||||
$fields = (array) $fields;
|
$fields = (array) $fields;
|
||||||
|
|
||||||
return $this->jsonDecodeArrayValues($this->storage->getTenantById($uuid, $fields));
|
$tenant = $this->storage->getTenantById($uuid, $fields);
|
||||||
|
if ($this->useJson()) {
|
||||||
|
$tenant = $this->jsonDecodeArrayValues($tenant);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tenant;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -200,7 +208,9 @@ final class TenantManager
|
||||||
*/
|
*/
|
||||||
public function setTenant(array $tenant): array
|
public function setTenant(array $tenant): array
|
||||||
{
|
{
|
||||||
|
if ($this->useJson()) {
|
||||||
$tenant = $this->jsonDecodeArrayValues($tenant);
|
$tenant = $this->jsonDecodeArrayValues($tenant);
|
||||||
|
}
|
||||||
|
|
||||||
$this->tenant = $tenant;
|
$this->tenant = $tenant;
|
||||||
|
|
||||||
|
|
@ -227,10 +237,15 @@ final class TenantManager
|
||||||
public function all($uuids = [])
|
public function all($uuids = [])
|
||||||
{
|
{
|
||||||
$uuids = (array) $uuids;
|
$uuids = (array) $uuids;
|
||||||
|
$tenants = $this->storage->getAllTenants($uuids);
|
||||||
|
|
||||||
return collect(array_map(function ($tenant_array) {
|
if ($this->useJson()) {
|
||||||
|
$tenants = array_map(function ($tenant_array) {
|
||||||
return $this->jsonDecodeArrayValues($tenant_array);
|
return $this->jsonDecodeArrayValues($tenant_array);
|
||||||
}, $this->storage->getAllTenants($uuids)));
|
}, $tenants);
|
||||||
|
}
|
||||||
|
|
||||||
|
return collect($tenants);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -336,6 +351,15 @@ final class TenantManager
|
||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function useJson()
|
||||||
|
{
|
||||||
|
if (property_exists($this->storage, 'useJson') && $this->storage->useJson === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the identified tenant's attribute(s).
|
* Return the identified tenant's attribute(s).
|
||||||
*
|
*
|
||||||
|
|
|
||||||
6
test
6
test
|
|
@ -4,7 +4,9 @@ set -e
|
||||||
# for development
|
# for development
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
printf "Variant 1\n\n"
|
printf "Variant 1\n\n"
|
||||||
TENANCY_TEST_REDIS_TENANCY=1 TENANCY_TEST_REDIS_CLIENT=phpredis docker-compose exec test vendor/bin/phpunit --coverage-php coverage/1.cov "$@"
|
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 "$@"
|
||||||
printf "Variant 2\n\n"
|
printf "Variant 2\n\n"
|
||||||
TENANCY_TEST_REDIS_TENANCY=0 TENANCY_TEST_REDIS_CLIENT=predis docker-compose exec test vendor/bin/phpunit --coverage-php coverage/2.cov "$@"
|
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 vendor/bin/phpcov merge --clover clover.xml coverage/
|
docker-compose exec test vendor/bin/phpcov merge --clover clover.xml coverage/
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,7 @@ class Kernel extends HttpKernel
|
||||||
->expectsQuestion('Do you want to publish the default database migration?', 'yes');
|
->expectsQuestion('Do you want to publish the default database migration?', 'yes');
|
||||||
$this->assertFileExists(base_path('routes/tenant.php'));
|
$this->assertFileExists(base_path('routes/tenant.php'));
|
||||||
$this->assertFileExists(base_path('config/tenancy.php'));
|
$this->assertFileExists(base_path('config/tenancy.php'));
|
||||||
|
$this->assertFileExists(database_path('migrations/2019_08_08_000000_create_tenants_table.php'));
|
||||||
$this->assertSame("<?php
|
$this->assertSame("<?php
|
||||||
|
|
||||||
namespace App\Http;
|
namespace App\Http;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\StorageDrivers\RedisStorageDriver;
|
||||||
|
use Stancl\Tenancy\StorageDrivers\DatabaseStorageDriver;
|
||||||
|
|
||||||
class TenantStorageTest extends TestCase
|
class TenantStorageTest extends TestCase
|
||||||
{
|
{
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
@ -111,4 +114,30 @@ class TenantStorageTest extends TestCase
|
||||||
|
|
||||||
$this->assertSame($value, tenancy()->put($value));
|
$this->assertSame($value, tenancy()->put($value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function correct_storage_driver_is_used()
|
||||||
|
{
|
||||||
|
if (config('tenancy.storage_driver') == DatabaseStorageDriver::class) {
|
||||||
|
$this->assertSame('DatabaseStorageDriver', class_basename(tenancy()->storage));
|
||||||
|
} elseif (config('tenancy.storage_driver') == RedisStorageDriver::class) {
|
||||||
|
$this->assertSame('RedisStorageDriver', class_basename(tenancy()->storage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function data_is_stored_with_correct_data_types()
|
||||||
|
{
|
||||||
|
tenancy()->put('someBool', false);
|
||||||
|
$this->assertSame('boolean', gettype(tenancy()->get('someBool')));
|
||||||
|
|
||||||
|
tenancy()->put('someInt', 5);
|
||||||
|
$this->assertSame('integer', gettype(tenancy()->get('someInt')));
|
||||||
|
|
||||||
|
tenancy()->put('someDouble', 11.40);
|
||||||
|
$this->assertSame('double', gettype(tenancy()->get('someDouble')));
|
||||||
|
|
||||||
|
tenancy()->put('string', 'foo');
|
||||||
|
$this->assertSame('string', gettype(tenancy()->get('string')));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,14 @@
|
||||||
namespace Stancl\Tenancy\Tests;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
use Stancl\Tenancy\StorageDrivers\RedisStorageDriver;
|
||||||
|
use Stancl\Tenancy\StorageDrivers\DatabaseStorageDriver;
|
||||||
|
|
||||||
abstract class TestCase extends \Orchestra\Testbench\TestCase
|
abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
{
|
{
|
||||||
public $autoCreateTenant = true;
|
public $autoCreateTenant = true;
|
||||||
public $autoInitTenancy = true;
|
public $autoInitTenancy = true;
|
||||||
|
|
||||||
private function checkRequirements(): void
|
|
||||||
{
|
|
||||||
parent::checkRequirements();
|
|
||||||
|
|
||||||
dd($this->getAnnotations());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the test environment.
|
* Setup the test environment.
|
||||||
*
|
*
|
||||||
|
|
@ -28,6 +23,12 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
Redis::connection('tenancy')->flushdb();
|
Redis::connection('tenancy')->flushdb();
|
||||||
Redis::connection('cache')->flushdb();
|
Redis::connection('cache')->flushdb();
|
||||||
|
|
||||||
|
$this->loadMigrationsFrom([
|
||||||
|
'--path' => realpath(__DIR__ . '/../assets/migrations'),
|
||||||
|
'--database' => 'central',
|
||||||
|
]);
|
||||||
|
config(['database.default' => 'sqlite']); // fix issue caused by loadMigrationsFrom
|
||||||
|
|
||||||
if ($this->autoCreateTenant) {
|
if ($this->autoCreateTenant) {
|
||||||
$this->createTenant();
|
$this->createTenant();
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +38,13 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
// config(['database.default' => 'central']);
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
public function createTenant($domain = 'localhost')
|
public function createTenant($domain = 'localhost')
|
||||||
{
|
{
|
||||||
tenant()->create($domain);
|
tenant()->create($domain);
|
||||||
|
|
@ -59,6 +67,8 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
\Dotenv\Dotenv::create(__DIR__ . '/..')->load();
|
\Dotenv\Dotenv::create(__DIR__ . '/..')->load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fclose(fopen(database_path('central.sqlite'), 'w'));
|
||||||
|
|
||||||
$app['config']->set([
|
$app['config']->set([
|
||||||
'database.redis.cache.host' => env('TENANCY_TEST_REDIS_HOST', '127.0.0.1'),
|
'database.redis.cache.host' => env('TENANCY_TEST_REDIS_HOST', '127.0.0.1'),
|
||||||
'database.redis.default.host' => env('TENANCY_TEST_REDIS_HOST', '127.0.0.1'),
|
'database.redis.default.host' => env('TENANCY_TEST_REDIS_HOST', '127.0.0.1'),
|
||||||
|
|
@ -72,6 +82,10 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
'database' => env('TENANCY_TEST_REDIS_DB', 14),
|
'database' => env('TENANCY_TEST_REDIS_DB', 14),
|
||||||
'prefix' => 'abc', // todo unrelated to tenancy, but this doesn't seem to have an effect? try to replicate in a fresh laravel installation
|
'prefix' => 'abc', // todo unrelated to tenancy, but this doesn't seem to have an effect? try to replicate in a fresh laravel installation
|
||||||
],
|
],
|
||||||
|
'database.connections.central' => [
|
||||||
|
'driver' => 'sqlite',
|
||||||
|
'database' => database_path('central.sqlite'),
|
||||||
|
],
|
||||||
'tenancy.database' => [
|
'tenancy.database' => [
|
||||||
'based_on' => 'sqlite',
|
'based_on' => 'sqlite',
|
||||||
'prefix' => 'tenant',
|
'prefix' => 'tenant',
|
||||||
|
|
@ -90,11 +104,27 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
'tenancy.redis.prefixed_connections' => ['default'],
|
'tenancy.redis.prefixed_connections' => ['default'],
|
||||||
'tenancy.migrations_directory' => database_path('../migrations'),
|
'tenancy.migrations_directory' => database_path('../migrations'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (env('TENANCY_TEST_STORAGE_DRIVER', 'redis') === 'redis') {
|
||||||
|
$app['config']->set([
|
||||||
|
'tenancy.storage_driver' => RedisStorageDriver::class,
|
||||||
|
]);
|
||||||
|
|
||||||
|
tenancy()->storage = $app->make(RedisStorageDriver::class);
|
||||||
|
} elseif (env('TENANCY_TEST_STORAGE_DRIVER', 'redis') === 'db') {
|
||||||
|
$app['config']->set([
|
||||||
|
'tenancy.storage_driver' => DatabaseStorageDriver::class,
|
||||||
|
]);
|
||||||
|
|
||||||
|
tenancy()->storage = $app->make(DatabaseStorageDriver::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getPackageProviders($app)
|
protected function getPackageProviders($app)
|
||||||
{
|
{
|
||||||
return [\Stancl\Tenancy\TenancyServiceProvider::class];
|
return [
|
||||||
|
\Stancl\Tenancy\TenancyServiceProvider::class,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getPackageAliases($app)
|
protected function getPackageAliases($app)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue