mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 18:54:03 +00:00
Merge branch '1.x' into telescope-tags
This commit is contained in:
commit
a00113b3d1
36 changed files with 558 additions and 707 deletions
|
|
@ -18,7 +18,7 @@ class CacheManager extends BaseCacheManager
|
|||
$names = $parameters[0];
|
||||
$names = (array) $names; // cache()->tags('foo') https://laravel.com/docs/5.7/cache#removing-tagged-cache-items
|
||||
|
||||
return $this->store()->tags(array_merge($tags, $names));
|
||||
return $this->store()->tags(\array_merge($tags, $names));
|
||||
}
|
||||
|
||||
return $this->store()->tags($tags)->$method(...$parameters);
|
||||
|
|
|
|||
|
|
@ -34,15 +34,16 @@ class Install extends Command
|
|||
]);
|
||||
$this->info('✔️ Created config/tenancy.php');
|
||||
|
||||
file_put_contents(app_path('Http/Kernel.php'), str_replace(
|
||||
\file_put_contents(app_path('Http/Kernel.php'), \str_replace(
|
||||
'protected $middlewarePriority = [',
|
||||
"protected \$middlewarePriority = [\n \Stancl\Tenancy\Middleware\InitializeTenancy::class,",
|
||||
file_get_contents(app_path('Http/Kernel.php'))
|
||||
\file_get_contents(app_path('Http/Kernel.php'))
|
||||
));
|
||||
$this->info('✔️ Set middleware priority');
|
||||
|
||||
file_put_contents(base_path('routes/tenant.php'),
|
||||
"<?php
|
||||
\file_put_contents(
|
||||
base_path('routes/tenant.php'),
|
||||
"<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
@ -58,7 +59,8 @@ class Install extends Command
|
|||
Route::get('/your/application/homepage', function () {
|
||||
return 'This is your multi-tenant application. The uuid of the current tenant is ' . tenant('uuid');
|
||||
});
|
||||
");
|
||||
"
|
||||
);
|
||||
$this->info('✔️ Created routes/tenant.php');
|
||||
|
||||
$this->line('');
|
||||
|
|
@ -71,6 +73,11 @@ Route::get('/your/application/homepage', function () {
|
|||
$this->info('✔️ Created migration.');
|
||||
}
|
||||
|
||||
if (! \is_dir(database_path('migrations/tenant'))) {
|
||||
\mkdir(database_path('migrations/tenant'));
|
||||
$this->info('✔️ Created database/migrations/tenant folder.');
|
||||
}
|
||||
|
||||
$this->comment('✨️ stancl/tenancy installed successfully.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,11 +47,14 @@ class Migrate extends MigrateCommand
|
|||
return;
|
||||
}
|
||||
|
||||
$this->input->setOption('database', 'tenant');
|
||||
|
||||
tenant()->all($this->option('tenants'))->each(function ($tenant) {
|
||||
$this->line("Tenant: {$tenant['uuid']} ({$tenant['domain']})");
|
||||
$this->database->connectToTenant($tenant);
|
||||
|
||||
// See Illuminate\Database\Migrations\DatabaseMigrationRepository::getConnection.
|
||||
// Database connections are cached by Illuminate\Database\ConnectionResolver.
|
||||
$connectionName = "tenant{$tenant['uuid']}";
|
||||
$this->input->setOption('database', $connectionName);
|
||||
$this->database->connectToTenant($tenant, $connectionName);
|
||||
|
||||
// Migrate
|
||||
parent::handle();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class Run extends Command
|
|||
|
||||
$callback = function ($prefix = '') {
|
||||
return function ($arguments, $argument) use ($prefix) {
|
||||
[$key, $value] = explode('=', $argument, 2);
|
||||
[$key, $value] = \explode('=', $argument, 2);
|
||||
$arguments[$prefix . $key] = $value;
|
||||
|
||||
return $arguments;
|
||||
|
|
@ -48,13 +48,13 @@ class Run extends Command
|
|||
};
|
||||
|
||||
// Turns ['foo=bar', 'abc=xyz=zzz'] into ['foo' => 'bar', 'abc' => 'xyz=zzz']
|
||||
$arguments = array_reduce($this->option('argument'), $callback(), []);
|
||||
$arguments = \array_reduce($this->option('argument'), $callback(), []);
|
||||
|
||||
// Turns ['foo=bar', 'abc=xyz=zzz'] into ['--foo' => 'bar', '--abc' => 'xyz=zzz']
|
||||
$options = array_reduce($this->option('option'), $callback('--'), []);
|
||||
$options = \array_reduce($this->option('option'), $callback('--'), []);
|
||||
|
||||
// Run command
|
||||
$this->call($this->argument('commandname'), array_merge($arguments, $options));
|
||||
$this->call($this->argument('commandname'), \array_merge($arguments, $options));
|
||||
|
||||
tenancy()->end();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,21 +10,23 @@ final class DatabaseManager
|
|||
{
|
||||
public $originalDefaultConnection;
|
||||
|
||||
protected $defaultTenantConnectionName = 'tenant';
|
||||
|
||||
public function __construct(BaseDatabaseManager $database)
|
||||
{
|
||||
$this->originalDefaultConnection = config('database.default');
|
||||
$this->database = $database;
|
||||
}
|
||||
|
||||
public function connect(string $database)
|
||||
public function connect(string $database, string $connectionName = null)
|
||||
{
|
||||
$this->createTenantConnection($database);
|
||||
$this->useConnection('tenant');
|
||||
$this->createTenantConnection($database, $connectionName);
|
||||
$this->useConnection($connectionName);
|
||||
}
|
||||
|
||||
public function connectToTenant($tenant)
|
||||
public function connectToTenant($tenant, string $connectionName = null)
|
||||
{
|
||||
$this->connect(tenant()->getDatabaseName($tenant));
|
||||
$this->connect(tenant()->getDatabaseName($tenant), $connectionName);
|
||||
}
|
||||
|
||||
public function disconnect()
|
||||
|
|
@ -50,7 +52,7 @@ final class DatabaseManager
|
|||
|
||||
$databaseManagers = config('tenancy.database_managers');
|
||||
|
||||
if (! array_key_exists($driver, $databaseManagers)) {
|
||||
if (! \array_key_exists($driver, $databaseManagers)) {
|
||||
throw new \Exception("Database could not be created: no database manager for driver $driver is registered.");
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +78,7 @@ final class DatabaseManager
|
|||
|
||||
$databaseManagers = config('tenancy.database_managers');
|
||||
|
||||
if (! array_key_exists($driver, $databaseManagers)) {
|
||||
if (! \array_key_exists($driver, $databaseManagers)) {
|
||||
throw new \Exception("Database could not be deleted: no database manager for driver $driver is registered.");
|
||||
}
|
||||
|
||||
|
|
@ -87,26 +89,32 @@ final class DatabaseManager
|
|||
}
|
||||
}
|
||||
|
||||
public function getDriver(): ?string
|
||||
public function getDriver($connectionName = null): ?string
|
||||
{
|
||||
return config('database.connections.tenant.driver');
|
||||
$connectionName = $connectionName ?: $this->defaultTenantConnectionName;
|
||||
|
||||
return config("database.connections.$connectionName.driver");
|
||||
}
|
||||
|
||||
public function createTenantConnection(string $database_name)
|
||||
public function createTenantConnection(string $databaseName, string $connectionName = null)
|
||||
{
|
||||
// Create the `tenancy` database connection.
|
||||
$connectionName = $connectionName ?: $this->defaultTenantConnectionName;
|
||||
|
||||
// Create the database connection.
|
||||
$based_on = config('tenancy.database.based_on') ?: config('database.default');
|
||||
config()->set([
|
||||
'database.connections.tenant' => config('database.connections.' . $based_on),
|
||||
"database.connections.$connectionName" => config('database.connections.' . $based_on),
|
||||
]);
|
||||
|
||||
// Change DB name
|
||||
$database_name = $this->getDriver() === 'sqlite' ? database_path($database_name) : $database_name;
|
||||
config()->set(['database.connections.tenant.database' => $database_name]);
|
||||
$databaseName = $this->getDriver($connectionName) === 'sqlite' ? database_path($databaseName) : $databaseName;
|
||||
config()->set(["database.connections.$connectionName.database" => $databaseName]);
|
||||
}
|
||||
|
||||
public function useConnection(string $connection)
|
||||
public function useConnection(string $connection = null)
|
||||
{
|
||||
$connection = $connection ?: $this->defaultTenantConnectionName;
|
||||
|
||||
$this->database->setDefaultConnection($connection);
|
||||
$this->database->reconnect($connection);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ interface StorageDriver
|
|||
{
|
||||
public function identifyTenant(string $domain): array;
|
||||
|
||||
/** @return array[] */
|
||||
public function getAllTenants(array $uuids = []): array;
|
||||
|
||||
public function getTenantById(string $uuid, array $fields = []): array;
|
||||
|
|
|
|||
87
src/StorageDrivers/DatabaseStorageDriver.php
Normal file
87
src/StorageDrivers/DatabaseStorageDriver.php
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<?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
|
||||
{
|
||||
$tenant = Tenant::create(['uuid' => $uuid, 'domain' => $domain, 'data' => '{}'])->toArray();
|
||||
unset($tenant['data']);
|
||||
|
||||
return $tenant;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
$this->redis = Redis::connection('tenancy');
|
||||
$this->redis = Redis::connection(config('tenancy.redis.connection', 'tenancy'));
|
||||
}
|
||||
|
||||
public function identifyTenant(string $domain): array
|
||||
|
|
@ -33,13 +33,11 @@ class RedisStorageDriver implements StorageDriver
|
|||
*/
|
||||
public function getTenantById(string $uuid, array $fields = []): array
|
||||
{
|
||||
$fields = (array) $fields;
|
||||
|
||||
if (! $fields) {
|
||||
return $this->redis->hgetall("tenants:$uuid");
|
||||
}
|
||||
|
||||
return array_combine($fields, $this->redis->hmget("tenants:$uuid", $fields));
|
||||
return \array_combine($fields, $this->redis->hmget("tenants:$uuid", $fields));
|
||||
}
|
||||
|
||||
public function getTenantIdByDomain(string $domain): ?string
|
||||
|
|
@ -50,7 +48,7 @@ class RedisStorageDriver implements StorageDriver
|
|||
public function createTenant(string $domain, string $uuid): array
|
||||
{
|
||||
$this->redis->hmset("domains:$domain", 'tenant_id', $uuid);
|
||||
$this->redis->hmset("tenants:$uuid", 'uuid', json_encode($uuid), 'domain', json_encode($domain));
|
||||
$this->redis->hmset("tenants:$uuid", 'uuid', \json_encode($uuid), 'domain', \json_encode($domain));
|
||||
|
||||
return $this->redis->hgetall("tenants:$uuid");
|
||||
}
|
||||
|
|
@ -65,7 +63,7 @@ class RedisStorageDriver implements StorageDriver
|
|||
public function deleteTenant(string $id): bool
|
||||
{
|
||||
try {
|
||||
$domain = json_decode($this->getTenantById($id)['domain']);
|
||||
$domain = \json_decode($this->getTenantById($id)['domain']);
|
||||
} catch (\Throwable $th) {
|
||||
throw new \Exception("No tenant with UUID $id exists.");
|
||||
}
|
||||
|
|
@ -77,7 +75,7 @@ class RedisStorageDriver implements StorageDriver
|
|||
|
||||
public function getAllTenants(array $uuids = []): array
|
||||
{
|
||||
$hashes = array_map(function ($hash) {
|
||||
$hashes = \array_map(function ($hash) {
|
||||
return "tenants:{$hash}";
|
||||
}, $uuids);
|
||||
|
||||
|
|
@ -88,18 +86,17 @@ class RedisStorageDriver implements StorageDriver
|
|||
|
||||
if (config('database.redis.client') === 'phpredis') {
|
||||
$redis_prefix = $this->redis->getOption($this->redis->client()::OPT_PREFIX) ?? $redis_prefix;
|
||||
$all_keys = $this->redis->scan(null, $redis_prefix . 'tenants:*');
|
||||
} else {
|
||||
$all_keys = $this->redis->scan(null, 'MATCH', $redis_prefix . 'tenants:*')[1];
|
||||
}
|
||||
|
||||
$hashes = array_map(function ($key) use ($redis_prefix) {
|
||||
$all_keys = $this->redis->keys('tenants:*');
|
||||
|
||||
$hashes = \array_map(function ($key) use ($redis_prefix) {
|
||||
// Left strip $redis_prefix from $key
|
||||
return substr($key, strlen($redis_prefix));
|
||||
return \substr($key, \strlen($redis_prefix));
|
||||
}, $all_keys);
|
||||
}
|
||||
|
||||
return array_map(function ($tenant) {
|
||||
return \array_map(function ($tenant) {
|
||||
return $this->redis->hgetall($tenant);
|
||||
}, $hashes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,9 +34,13 @@ class TenancyServiceProvider extends ServiceProvider
|
|||
]);
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/config/tenancy.php' => config_path('tenancy.php'),
|
||||
__DIR__ . '/../assets/config.php' => config_path('tenancy.php'),
|
||||
], 'config');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../assets/migrations/' => database_path('migrations'),
|
||||
], 'migrations');
|
||||
|
||||
$this->loadRoutesFrom(__DIR__ . '/routes.php');
|
||||
|
||||
Route::middlewareGroup('tenancy', [
|
||||
|
|
@ -75,7 +79,7 @@ class TenancyServiceProvider extends ServiceProvider
|
|||
*/
|
||||
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(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') ?: config('database.default');
|
||||
}
|
||||
|
||||
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->attributes[$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;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
|||
public function createDatabase(string $name): bool
|
||||
{
|
||||
try {
|
||||
return fclose(fopen(database_path($name), 'w'));
|
||||
return \fclose(\fopen(database_path($name), 'w'));
|
||||
} catch (\Throwable $th) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
|||
public function deleteDatabase(string $name): bool
|
||||
{
|
||||
try {
|
||||
return unlink(database_path($name));
|
||||
return \unlink(database_path($name));
|
||||
} catch (\Throwable $th) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ final class TenantManager
|
|||
*
|
||||
* @var StorageDriver
|
||||
*/
|
||||
protected $storage;
|
||||
public $storage;
|
||||
|
||||
/**
|
||||
* Database manager.
|
||||
|
|
@ -37,7 +37,7 @@ final class TenantManager
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public $tenant;
|
||||
public $tenant = [];
|
||||
|
||||
public function __construct(Application $app, StorageDriver $storage, DatabaseManager $database)
|
||||
{
|
||||
|
|
@ -64,7 +64,7 @@ final class TenantManager
|
|||
|
||||
$tenant = $this->storage->identifyTenant($domain);
|
||||
|
||||
if (! $tenant || ! array_key_exists('uuid', $tenant) || ! $tenant['uuid']) {
|
||||
if (! $tenant || ! \array_key_exists('uuid', $tenant) || ! $tenant['uuid']) {
|
||||
throw new \Exception("Tenant could not be identified on domain {$domain}.");
|
||||
}
|
||||
|
||||
|
|
@ -86,12 +86,15 @@ final class TenantManager
|
|||
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) {
|
||||
$this->put($data, null, $tenant['uuid']);
|
||||
|
||||
$tenant = array_merge($tenant, $data);
|
||||
$tenant = \array_merge($tenant, $data);
|
||||
}
|
||||
|
||||
$this->database->create($this->getDatabaseName($tenant));
|
||||
|
|
@ -115,7 +118,12 @@ final class TenantManager
|
|||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -167,7 +175,7 @@ final class TenantManager
|
|||
|
||||
$uuid = $this->getIdByDomain($domain);
|
||||
|
||||
if (is_null($uuid)) {
|
||||
if (\is_null($uuid)) {
|
||||
throw new \Exception("Tenant with domain $domain could not be identified.");
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +208,9 @@ final class TenantManager
|
|||
*/
|
||||
public function setTenant(array $tenant): array
|
||||
{
|
||||
$tenant = $this->jsonDecodeArrayValues($tenant);
|
||||
if ($this->useJson()) {
|
||||
$tenant = $this->jsonDecodeArrayValues($tenant);
|
||||
}
|
||||
|
||||
$this->tenant = $tenant;
|
||||
|
||||
|
|
@ -227,10 +237,15 @@ final class TenantManager
|
|||
public function all($uuids = [])
|
||||
{
|
||||
$uuids = (array) $uuids;
|
||||
$tenants = $this->storage->getAllTenants($uuids);
|
||||
|
||||
return collect(array_map(function ($tenant_array) {
|
||||
return $this->jsonDecodeArrayValues($tenant_array);
|
||||
}, $this->storage->getAllTenants($uuids)));
|
||||
if ($this->useJson()) {
|
||||
$tenants = \array_map(function ($tenant_array) {
|
||||
return $this->jsonDecodeArrayValues($tenant_array);
|
||||
}, $tenants);
|
||||
}
|
||||
|
||||
return collect($tenants);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -258,11 +273,16 @@ final class TenantManager
|
|||
{
|
||||
$uuid = $uuid ?: $this->tenant['uuid'];
|
||||
|
||||
if (\array_key_exists('uuid', $this->tenant) && $uuid === $this->tenant['uuid'] &&
|
||||
! \is_array($key) && \array_key_exists($key, $this->tenant)) {
|
||||
return $this->tenant[$key];
|
||||
}
|
||||
|
||||
if (\is_array($key)) {
|
||||
return $this->jsonDecodeArrayValues($this->storage->getMany($uuid, $key));
|
||||
}
|
||||
|
||||
return json_decode($this->storage->get($uuid, $key), true);
|
||||
return \json_decode($this->storage->get($uuid, $key), true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -275,10 +295,10 @@ final class TenantManager
|
|||
*/
|
||||
public function put($key, $value = null, string $uuid = null)
|
||||
{
|
||||
if (in_array($key, ['uuid', 'domain'], true) || (
|
||||
is_array($key) && (
|
||||
in_array('uuid', array_keys($key), true) ||
|
||||
in_array('domain', array_keys($key), true)
|
||||
if (\in_array($key, ['uuid', 'domain'], true) || (
|
||||
\is_array($key) && (
|
||||
\in_array('uuid', \array_keys($key), true) ||
|
||||
\in_array('domain', \array_keys($key), true)
|
||||
)
|
||||
)) {
|
||||
throw new CannotChangeUuidOrDomainException;
|
||||
|
|
@ -299,7 +319,7 @@ final class TenantManager
|
|||
}
|
||||
|
||||
if (! \is_null($value)) {
|
||||
return $target[$key] = json_decode($this->storage->put($uuid, $key, json_encode($value)), true);
|
||||
return $target[$key] = \json_decode($this->storage->put($uuid, $key, \json_encode($value)), true);
|
||||
}
|
||||
|
||||
if (! \is_array($key)) {
|
||||
|
|
@ -308,7 +328,7 @@ final class TenantManager
|
|||
|
||||
foreach ($key as $k => $v) {
|
||||
$target[$k] = $v;
|
||||
$key[$k] = json_encode($v);
|
||||
$key[$k] = \json_encode($v);
|
||||
}
|
||||
|
||||
return $this->jsonDecodeArrayValues($this->storage->putMany($uuid, $key));
|
||||
|
|
@ -329,18 +349,28 @@ final class TenantManager
|
|||
|
||||
protected function jsonDecodeArrayValues(array $array)
|
||||
{
|
||||
array_walk($array, function (&$value, $key) {
|
||||
$value = json_decode($value, true);
|
||||
\array_walk($array, function (&$value, $key) {
|
||||
$value = \json_decode($value, true);
|
||||
});
|
||||
|
||||
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).
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return mixed
|
||||
* @todo Deprecate this in v2.
|
||||
*/
|
||||
public function __invoke($attribute)
|
||||
{
|
||||
|
|
@ -348,6 +378,6 @@ final class TenantManager
|
|||
return $this->tenant;
|
||||
}
|
||||
|
||||
return $this->tenant[(string) $attribute];
|
||||
return $this->get((string) $attribute);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class TenantRouteServiceProvider extends RouteServiceProvider
|
|||
public function map()
|
||||
{
|
||||
if (! \in_array(request()->getHost(), $this->app['config']['tenancy.exempt_domains'] ?? [])
|
||||
&& file_exists(base_path('routes/tenant.php'))) {
|
||||
&& \file_exists(base_path('routes/tenant.php'))) {
|
||||
Route::middleware(['web', 'tenancy'])
|
||||
->namespace($this->app['config']['tenant_route_namespace'] ?? 'App\Http\Controllers')
|
||||
->group(base_path('routes/tenant.php'));
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ trait BootstrapsTenancy
|
|||
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}"])) {
|
||||
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"];
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ trait HasATenantsOption
|
|||
{
|
||||
protected function getOptions()
|
||||
{
|
||||
return array_merge([
|
||||
return \array_merge([
|
||||
['tenants', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, '', null],
|
||||
], parent::getOptions());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ trait TenantManagerEvents
|
|||
*/
|
||||
public function event(string $name): Collection
|
||||
{
|
||||
return array_reduce($this->listeners[$name], function ($prevents, $listener) {
|
||||
return \array_reduce($this->listeners[$name], function ($prevents, $listener) {
|
||||
return $prevents->merge($listener($this) ?? []);
|
||||
}, collect([]));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'storage_driver' => 'Stancl\Tenancy\StorageDrivers\RedisStorageDriver',
|
||||
'tenant_route_namespace' => 'App\Http\Controllers',
|
||||
'exempt_domains' => [
|
||||
// 'localhost',
|
||||
],
|
||||
'database' => [
|
||||
'based_on' => 'mysql',
|
||||
'prefix' => 'tenant',
|
||||
'suffix' => '',
|
||||
],
|
||||
'redis' => [
|
||||
'tenancy' => false,
|
||||
'prefix_base' => 'tenant',
|
||||
'prefixed_connections' => [
|
||||
'default',
|
||||
'cache',
|
||||
],
|
||||
],
|
||||
'cache' => [
|
||||
'tag_base' => 'tenant',
|
||||
],
|
||||
'filesystem' => [
|
||||
'suffix_base' => 'tenant',
|
||||
// Disks which should be suffixed with the suffix_base + tenant UUID.
|
||||
'disks' => [
|
||||
'local',
|
||||
'public',
|
||||
// 's3',
|
||||
],
|
||||
'root_override' => [
|
||||
// Disks whose roots should be overriden after storage_path() is suffixed.
|
||||
'local' => '%storage_path%/app/',
|
||||
'public' => '%storage_path%/app/public/',
|
||||
],
|
||||
],
|
||||
'database_managers' => [
|
||||
'sqlite' => 'Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager',
|
||||
'mysql' => 'Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager',
|
||||
'pgsql' => 'Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager',
|
||||
],
|
||||
'queue_database_creation' => false,
|
||||
'queue_database_deletion' => false,
|
||||
'database_name_key' => null,
|
||||
];
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use Stancl\Tenancy\TenantManager;
|
||||
|
||||
if (! function_exists('tenancy')) {
|
||||
if (! \function_exists('tenancy')) {
|
||||
function tenancy($key = null)
|
||||
{
|
||||
if ($key) {
|
||||
|
|
@ -13,14 +13,14 @@ if (! function_exists('tenancy')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (! function_exists('tenant')) {
|
||||
if (! \function_exists('tenant')) {
|
||||
function tenant($key = null)
|
||||
{
|
||||
return tenancy($key);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('tenant_asset')) {
|
||||
if (! \function_exists('tenant_asset')) {
|
||||
function tenant_asset($asset)
|
||||
{
|
||||
return route('stancl.tenancy.asset', ['asset' => $asset]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue