1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 12:54:05 +00:00

[1.7.0] Add tenants:run (#81)

* wip

* Apply fixes from StyleCI

* first implementation

* Apply fixes from StyleCI

* Add support for arguments and options

* Apply fixes from StyleCI

* Write docs, add support for = in arg/opt value

* Apply fixes from StyleCI

* add $ [ci skip]
This commit is contained in:
Samuel Štancl 2019-08-09 19:06:00 +02:00 committed by GitHub
parent 85b2274d1d
commit 15f09e59df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 169 additions and 4 deletions

View file

@ -53,6 +53,7 @@ You won't have to change a thing in your application's code.\*
* [Artisan commands](#artisan-commands) * [Artisan commands](#artisan-commands)
- [`tenants:list`](#-tenants-list-) - [`tenants:list`](#-tenants-list-)
- [`tenants:migrate`, `tenants:rollback`, `tenants:seed`](#-tenants-migrate----tenants-rollback----tenants-seed-) - [`tenants:migrate`, `tenants:rollback`, `tenants:seed`](#-tenants-migrate----tenants-rollback----tenants-seed-)
- [Running your commands for tenants](#running-your-commands-for-tenants)
+ [Tenant migrations](#tenant-migrations) + [Tenant migrations](#tenant-migrations)
* [Testing](#testing) * [Testing](#testing)
- [Tips](#tips) - [Tips](#tips)
@ -487,6 +488,7 @@ Available commands for the "tenants" namespace:
tenants:list List tenants. tenants:list List tenants.
tenants:migrate Run migrations for tenant(s) tenants:migrate Run migrations for tenant(s)
tenants:rollback Rollback migrations for tenant(s). tenants:rollback Rollback migrations for tenant(s).
tenants:run Run a command for tenant(s).
tenants:seed Seed tenant database(s). tenants:seed Seed tenant database(s).
``` ```
@ -509,6 +511,18 @@ Tenant: 8075a580-1cb8-11e9-8822-49c5d8f8ff23 (laravel.localhost)
Database seeding completed successfully. Database seeding completed successfully.
``` ```
### Running your commands for tenants
You can use the `tenants:run` command to run your own commands for tenants.
If your command's signature were `email:send {user} {--queue} {--subject} {body}`, you would run this command like this:
```
$ artisan tenants:run email:send --tenants=8075a580-1cb8-11e9-8822-49c5d8f8ff23 --option="queue=1" --option="subject=New Feature" --argument="body=We have launched a new feature. ..."
```
The `=` separates the argument/option name from its value, but you can still use `=` in the argument's value.
### Tenant migrations ### Tenant migrations
Tenant migrations are located in `database/migrations/tenant`, so you should move your tenant migrations there. Tenant migrations are located in `database/migrations/tenant`, so you should move your tenant migrations there.

66
src/Commands/Run.php Normal file
View file

@ -0,0 +1,66 @@
<?php
namespace Stancl\Tenancy\Commands;
use Illuminate\Console\Command;
class Run extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Run a command for tenant(s)';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = "tenants:run {commandname : The command's name.}
{--tenants= : The tenant(s) to run the command for. Default: all}
{--argument=* : The arguments to pass to the command. Default: none}
{--option=* : The options to pass to the command. Default: none}";
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if ($tenancy_was_initialized = tenancy()->initialized) {
$previous_tenants_domain = tenant('domain');
}
tenant()->all($this->option('tenants'))->each(function ($tenant) {
$this->line("Tenant: {$tenant['uuid']} ({$tenant['domain']})");
tenancy()->init($tenant['domain']);
$callback = function ($prefix = '') {
return function ($arguments, $argument) use ($prefix) {
[$key, $value] = explode('=', $argument, 2);
$arguments[$prefix . $key] = $value;
return $arguments;
};
};
// Turns ['foo=bar', 'abc=xyz=zzz'] into ['foo' => 'bar', 'abc' => 'xyz=zzz']
$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('--'), []);
// Run command
$this->call($this->argument('commandname'), array_merge($arguments, $options));
tenancy()->end();
});
if ($tenancy_was_initialized) {
tenancy()->init($previous_tenants_domain);
}
}
}

View file

@ -2,6 +2,7 @@
namespace Stancl\Tenancy; namespace Stancl\Tenancy;
use Stancl\Tenancy\Commands\Run;
use Stancl\Tenancy\Commands\Seed; use Stancl\Tenancy\Commands\Seed;
use Illuminate\Cache\CacheManager; use Illuminate\Cache\CacheManager;
use Stancl\Tenancy\Commands\Migrate; use Stancl\Tenancy\Commands\Migrate;
@ -23,9 +24,10 @@ class TenancyServiceProvider extends ServiceProvider
{ {
if ($this->app->runningInConsole()) { if ($this->app->runningInConsole()) {
$this->commands([ $this->commands([
Run::class,
Seed::class,
Migrate::class, Migrate::class,
Rollback::class, Rollback::class,
Seed::class,
TenantList::class, TenantList::class,
]); ]);
} }

View file

@ -76,7 +76,7 @@ class CommandsTest extends TestCase
} }
/** @test */ /** @test */
public function database_connection_is_switched_to_default_after_migrating_or_seeding_or_rolling_back() public function database_connection_is_switched_to_default()
{ {
$originalDBName = DB::connection()->getDatabaseName(); $originalDBName = DB::connection()->getDatabaseName();
@ -88,13 +88,29 @@ class CommandsTest extends TestCase
Artisan::call('tenants:rollback'); Artisan::call('tenants:rollback');
$this->assertSame($originalDBName, DB::connection()->getDatabaseName()); $this->assertSame($originalDBName, DB::connection()->getDatabaseName());
$this->run_commands_works();
$this->assertSame($originalDBName, DB::connection()->getDatabaseName());
} }
/** @test */ /** @test */
public function database_connection_is_switched_to_default_after_migrating_or_seeding_or_rolling_back_when_tenancy_has_been_initialized() public function database_connection_is_switched_to_default_when_tenancy_has_been_initialized()
{ {
tenancy()->init('localhost'); tenancy()->init('localhost');
$this->database_connection_is_switched_to_default_after_migrating_or_seeding_or_rolling_back(); $this->database_connection_is_switched_to_default();
}
/** @test */
public function run_commands_works()
{
$uuid = tenant()->create('run.localhost')['uuid'];
Artisan::call('tenants:migrate', ['--tenants' => $uuid]);
$this->artisan("tenants:run foo --tenants=$uuid --argument='a=foo' --option='b=bar' --option='c=xyz'")
->expectsOutput("User's name is Test command")
->expectsOutput('foo')
->expectsOutput('xyz');
} }
} }

View file

@ -0,0 +1,17 @@
<?php
namespace Stancl\Tenancy\Tests\Etc;
use Orchestra\Testbench\Console\Kernel;
class ConsoleKernel extends Kernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
ExampleCommand::class,
];
}

View file

@ -0,0 +1,39 @@
<?php
namespace Stancl\Tenancy\Tests\Etc;
use Illuminate\Console\Command;
class ExampleCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'foo {a} {--b=} {--c=}';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
User::create([
'id' => 999,
'name' => 'Test command',
'email' => 'test@command.com',
'password' => bcrypt('password'),
]);
$this->line("User's name is " . User::find(999)->name);
$this->line($this->argument('a'));
$this->line($this->option('c'));
}
}
class User extends \Illuminate\Database\Eloquent\Model
{
protected $guarded = [];
}

View file

@ -130,6 +130,17 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
$app->singleton('Illuminate\Contracts\Http\Kernel', Etc\HttpKernel::class); $app->singleton('Illuminate\Contracts\Http\Kernel', Etc\HttpKernel::class);
} }
/**
* Resolve application Console Kernel implementation.
*
* @param \Illuminate\Foundation\Application $app
* @return void
*/
protected function resolveApplicationConsoleKernel($app)
{
$app->singleton('Illuminate\Contracts\Console\Kernel', Etc\ConsoleKernel::class);
}
public function randomString(int $length = 10) public function randomString(int $length = 10)
{ {
return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length); return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);