diff --git a/src/CacheManager.php b/src/CacheManager.php index b0e357cc..29610371 100644 --- a/src/CacheManager.php +++ b/src/CacheManager.php @@ -8,6 +8,13 @@ use Illuminate\Cache\CacheManager as BaseCacheManager; class CacheManager extends BaseCacheManager { + /** + * Add tags and forward the call to the inner cache store. + * + * @param string $method + * @param array $parameters + * @return mixed + */ public function __call($method, $parameters) { $tags = [config('tenancy.cache.tag_base') . tenant('id')]; diff --git a/src/Contracts/TenancyBootstrapper.php b/src/Contracts/TenancyBootstrapper.php index 5d1e2dcf..2e1e6559 100644 --- a/src/Contracts/TenancyBootstrapper.php +++ b/src/Contracts/TenancyBootstrapper.php @@ -6,6 +6,9 @@ namespace Stancl\Tenancy\Contracts; use Stancl\Tenancy\Tenant; +/** + * TenancyBootstrappers are classes that make existing code tenant-aware. + */ interface TenancyBootstrapper { public function start(Tenant $tenant); diff --git a/src/DatabaseManager.php b/src/DatabaseManager.php index ce8cd99a..8bb3647c 100644 --- a/src/DatabaseManager.php +++ b/src/DatabaseManager.php @@ -81,7 +81,13 @@ class DatabaseManager return $this->app['config']["database.connections.$connectionName.driver"]; } - public function switchConnection($connection) + /** + * Switch the application's connection. + * + * @param string $connection + * @return void + */ + public function switchConnection(string $connection) { $this->app['config']['database.default'] = $connection; $this->database->purge(); @@ -103,6 +109,12 @@ class DatabaseManager } } + /** + * Create a database for a tenant. + * + * @param Tenant $tenant + * @return void + */ public function createDatabase(Tenant $tenant) { $database = $tenant->getDatabaseName(); @@ -115,6 +127,12 @@ class DatabaseManager } } + /** + * Delete a tenant's database. + * + * @param Tenant $tenant + * @return void + */ public function deleteDatabase(Tenant $tenant) { $database = $tenant->getDatabaseName(); @@ -127,6 +145,12 @@ class DatabaseManager } } + /** + * Get the TenantDatabaseManager for a tenant's database connection. + * + * @param Tenant $tenant + * @return TenantDatabaseManager + */ protected function getTenantDatabaseManager(Tenant $tenant): TenantDatabaseManager { // todo2 this shouldn't have to create a connection diff --git a/src/Tenant.php b/src/Tenant.php index e4aa3888..bcb4827d 100644 --- a/src/Tenant.php +++ b/src/Tenant.php @@ -7,6 +7,7 @@ namespace Stancl\Tenancy; use ArrayAccess; use Illuminate\Foundation\Application; use Illuminate\Support\Str; +use Illuminate\Support\Traits\ForwardsCalls; use Stancl\Tenancy\Contracts\StorageDriver; use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator; use Stancl\Tenancy\Exceptions\TenantStorageException; @@ -18,7 +19,8 @@ use Stancl\Tenancy\Exceptions\TenantStorageException; */ class Tenant implements ArrayAccess { - use Traits\HasArrayAccess; + use Traits\HasArrayAccess, + ForwardsCalls; /** * Tenant data. A "cache" of tenant storage. @@ -53,6 +55,14 @@ class Tenant implements ArrayAccess */ protected $persisted = false; + /** + * Use new() if you don't want to swap dependencies. + * + * @param Application $app + * @param StorageDriver $storage + * @param TenantManager $tenantManager + * @param UniqueIdentifierGenerator $idGenerator + */ public function __construct(Application $app, StorageDriver $storage, TenantManager $tenantManager, UniqueIdentifierGenerator $idGenerator) { $this->app = $app; @@ -61,6 +71,12 @@ class Tenant implements ArrayAccess $this->idGenerator = $idGenerator; } + /** + * Public constructor. + * + * @param Application $app + * @return self + */ public static function new(Application $app = null): self { $app = $app ?? app(); @@ -73,11 +89,25 @@ class Tenant implements ArrayAccess ); } + /** + * DO NOT CALL THIS METHOD FROM USERLAND. Used by storage + * drivers to create persisted instances of Tenant. + * + * @param array $data + * @return self + */ public static function fromStorage(array $data): self { return static::new()->withData($data)->persisted(true); } + /** + * Create a tenant in a single command. + * + * @param string|string[] $domains + * @param array $data + * @return self + */ public static function create($domains, array $data = []): self { return static::new()->withDomains((array) $domains)->withData($data)->save(); @@ -94,6 +124,11 @@ class Tenant implements ArrayAccess return $this; } + /** + * Does this model exist in the tenant storage. + * + * @return boolean + */ public function isPersisted(): bool { return $this->persisted; @@ -127,6 +162,11 @@ class Tenant implements ArrayAccess return $this; } + /** + * Unassign all domains from the tenant. + * + * @return self + */ public function clearDomains(): self { $this->domains = []; @@ -134,6 +174,12 @@ class Tenant implements ArrayAccess return $this; } + /** + * Set (overwrite) the tenant's domains. + * + * @param string|string[] $domains + * @return self + */ public function withDomains($domains): self { $domains = (array) $domains; @@ -143,6 +189,12 @@ class Tenant implements ArrayAccess return $this; } + /** + * Set (overwrite) tenant data. + * + * @param array $data + * @return self + */ public function withData(array $data): self { $this->data = $data; @@ -150,11 +202,21 @@ class Tenant implements ArrayAccess return $this; } + /** + * Generate a random ID. + * + * @return void + */ public function generateId() { $this->id = $this->idGenerator->generate($this->domains, $this->data); } + /** + * Write the tenant's state to storage. + * + * @return self + */ public function save(): self { if (! isset($this->data['id'])) { @@ -188,7 +250,7 @@ class Tenant implements ArrayAccess } /** - * Unassign all domains from the tenant. + * Unassign all domains from the tenant and write to storage. * * @return self */ @@ -201,12 +263,22 @@ class Tenant implements ArrayAccess return $this; } - public function getDatabaseName() + /** + * Get the tenant's database's name. + * + * @return string + */ + public function getDatabaseName(): string { return $this->data['_tenancy_db_name'] ?? ($this->app['config']['tenancy.database.prefix'] . $this->id . $this->app['config']['tenancy.database.suffix']); } - public function getConnectionName() + /** + * Get the tenant's database connection's name. + * + * @return string + */ + public function getConnectionName(): string { return $this->data['_tenancy_db_connection'] ?? 'tenant'; } @@ -243,6 +315,13 @@ class Tenant implements ArrayAccess return $this->data[$key]; } + /** + * Set a value and write to storage. + * + * @param string|array $key + * @param mixed $value + * @return self + */ public function put($key, $value = null): self { if ($key === 'id') { @@ -268,6 +347,13 @@ class Tenant implements ArrayAccess return $this->put($key, $value); } + /** + * Set a value. + * + * @param string $key + * @param mixed $value + * @return self + */ public function with(string $key, $value): self { $this->data[$key] = $value; @@ -285,6 +371,7 @@ class Tenant implements ArrayAccess if ($key === 'id' && isset($this->data['id'])) { throw new TenantStorageException("Tenant ids can't be changed."); } + $this->data[$key] = $value; } @@ -294,6 +381,6 @@ class Tenant implements ArrayAccess return $this->with(Str::snake(substr($method, 4)), $parameters[0]); } - // todo throw some exception? + static::throwBadMethodCallException($method); } } diff --git a/src/TenantManager.php b/src/TenantManager.php index 5522ceb3..669c6468 100644 --- a/src/TenantManager.php +++ b/src/TenantManager.php @@ -50,6 +50,12 @@ class TenantManager $this->bootstrapFeatures(); } + /** + * Write a new tenant to storage. + * + * @param Tenant $tenant + * @return self + */ public function createTenant(Tenant $tenant): self { $this->ensureTenantCanBeCreated($tenant); @@ -66,6 +72,12 @@ class TenantManager return $this; } + /** + * Delete a tenant from storage. + * + * @param Tenant $tenant + * @return self + */ public function deleteTenant(Tenant $tenant): self { $this->storage->deleteTenant($tenant); @@ -77,6 +89,13 @@ class TenantManager return $this; } + /** + * Alias for Stancl\Tenancy\Tenant::create. + * + * @param string|string[] $domains + * @param array $data + * @return Tenant + */ public static function create($domains, array $data = []): Tenant { return Tenant::create($domains, $data); @@ -95,6 +114,12 @@ class TenantManager $this->database->ensureTenantCanBeCreated($tenant); } + /** + * Update an existing tenant in storage. + * + * @param Tenant $tenant + * @return self + */ public function updateTenant(Tenant $tenant): self { $this->storage->updateTenant($tenant); @@ -102,6 +127,12 @@ class TenantManager return $this; } + /** + * Find tenant by domain & initialize tenancy. + * + * @param string $domain + * @return self + */ public function init(string $domain = null): self { $domain = $domain ?? request()->getHost(); @@ -110,6 +141,12 @@ class TenantManager return $this; } + /** + * Find tenant by ID & initialize tenancy. + * + * @param string $id + * @return self + */ public function initById(string $id): self { $this->initializeTenancy($this->find($id)); @@ -156,6 +193,12 @@ class TenantManager return collect($this->storage->all($only)); } + /** + * Initialize tenancy. + * + * @param Tenant $tenant + * @return self + */ public function initializeTenancy(Tenant $tenant): self { $this->setTenant($tenant); @@ -171,6 +214,12 @@ class TenantManager return $this->initializeTenancy($tenant); } + /** + * Execute TenancyBootstrappers. + * + * @param Tenant $tenant + * @return self + */ public function bootstrapTenancy(Tenant $tenant): self { $prevented = $this->event('bootstrapping'); diff --git a/tests/TenantClassTest.php b/tests/TenantClassTest.php index 4a11dc32..7cb1c8bb 100644 --- a/tests/TenantClassTest.php +++ b/tests/TenantClassTest.php @@ -86,4 +86,12 @@ class TenantClassTest extends TestCase $this->assertSame('xyz', $tenant2->foo_bar); $this->assertArrayHasKey('foo_bar', $tenant2->data); } + + /** @test */ + public function an_exception_is_thrown_when_an_unknown_method_is_called() + { + $tenant = Tenant::new(); + $this->expectException(\BadMethodCallException::class); + $tenant->sdjigndfgnjdfgj(); + } }