-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Feat] Support Integrate Seeder (#217)
* feat: add integrate seeder - add seeder abstract, to run seeder task - `run`, basic method to run seeder - `call`, call another seeder class - `create`, shorthand to create/insert data to database - add path for seeder path - add command to run seeder - add commnad to make seeder * change group test for seeder command * add make seeder command * add null property type * add test * optional force create exist seeder class
- Loading branch information
1 parent
b1fe68d
commit 2563efa
Showing
13 changed files
with
474 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace System\Database\Seeder; | ||
|
||
use System\Database\MyPDO; | ||
use System\Database\MyQuery\Insert; | ||
use System\Integrate\Application; | ||
|
||
abstract class Seeder | ||
{ | ||
protected Application $app; | ||
|
||
public function __construct(Application $app) | ||
{ | ||
$this->app = $app; | ||
} | ||
|
||
/** | ||
* @param class-string $class_name | ||
*/ | ||
public function call(string $class_name): void | ||
{ | ||
$this->app->call([$class_name, 'run']); | ||
} | ||
|
||
public function create(string $table_name): Insert | ||
{ | ||
/** @var MyPDO */ | ||
$pdo = $this->app->get(MyPDO::class); | ||
|
||
return new Insert($table_name, $pdo); | ||
} | ||
|
||
/** | ||
* Run seeder. | ||
*/ | ||
abstract public function run(): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace System\Integrate\Console; | ||
|
||
use System\Console\Command; | ||
use System\Console\Prompt; | ||
use System\Console\Traits\PrintHelpTrait; | ||
use System\Template\Generate; | ||
use System\Template\Method; | ||
use System\Text\Str; | ||
|
||
use function System\Console\fail; | ||
use function System\Console\info; | ||
use function System\Console\ok; | ||
use function System\Console\style; | ||
use function System\Console\warn; | ||
|
||
/** | ||
* @property string|null $class | ||
* @property bool|null $force | ||
*/ | ||
class SeedCommand extends Command | ||
{ | ||
use PrintHelpTrait; | ||
|
||
/** | ||
* Register command. | ||
* | ||
* @var array<int, array<string, mixed>> | ||
*/ | ||
public static array $command = [ | ||
[ | ||
'cmd' => 'db:seed', | ||
'mode' => 'full', | ||
'class' => self::class, | ||
'fn' => 'main', | ||
], | ||
[ | ||
'cmd' => 'make:seed', | ||
'mode' => 'full', | ||
'class' => self::class, | ||
'fn' => 'make', | ||
], | ||
]; | ||
|
||
/** | ||
* @return array<string, array<string, string|string[]>> | ||
*/ | ||
public function printHelp(): array | ||
{ | ||
return [ | ||
'commands' => [ | ||
'db:seed' => 'Run seeding', | ||
'make:seed' => 'Create new seeder class', | ||
], | ||
'options' => [ | ||
'--class' => 'Target class', | ||
], | ||
'relation' => [ | ||
'db:seed' => ['--class'], | ||
], | ||
]; | ||
} | ||
|
||
private function runInDev(): bool | ||
{ | ||
if (app()->isDev() || $this->force) { | ||
return true; | ||
} | ||
|
||
/* @var bool */ | ||
return (new Prompt(style('Runing seeder in production?')->textRed(), [ | ||
'yes' => fn () => true, | ||
'no' => fn () => false, | ||
], 'no')) | ||
->selection([ | ||
style('yes')->textDim(), | ||
' no', | ||
]) | ||
->option(); | ||
} | ||
|
||
public function main(): int | ||
{ | ||
$class = $this->class; | ||
$exit = 0; | ||
|
||
if (false === $this->runInDev()) { | ||
return 2; | ||
} | ||
|
||
if (null === $class) { | ||
warn('command db:seed require --class flag follow by class name.')->out(false); | ||
|
||
return 1; | ||
} | ||
|
||
if (!Str::startsWith($class, 'Database\Seeders')) { | ||
$class = 'Database\\Seeders\\' . $class; | ||
} | ||
|
||
if (false === class_exists($class)) { | ||
warn("Class '{$class}::class' doest exist.")->out(false); | ||
|
||
return 1; | ||
} | ||
|
||
info('Running seeders...')->out(false); | ||
try { | ||
app()->call([$class, 'run']); | ||
|
||
ok('Success run seeder')->out(false); | ||
} catch (\Throwable $th) { | ||
warn($th->getMessage())->out(false); | ||
$exit = 1; | ||
} | ||
|
||
return $exit; | ||
} | ||
|
||
public function make(): int | ||
{ | ||
$class = $this->OPTION[0] ?? null; | ||
|
||
if (null === $class) { | ||
warn('command make:seed require class name')->out(false); | ||
|
||
return 1; | ||
} | ||
|
||
if (file_exists(seeder_path() . $class . '.php') && !$this->force) { | ||
warn("Class '{$class}::class' already exist.")->out(false); | ||
|
||
return 1; | ||
} | ||
|
||
$make = new Generate($class); | ||
$make->tabIndent(' '); | ||
$make->tabSize(4); | ||
$make->namespace('Database\Seeders'); | ||
$make->use('System\Database\Seeder\Seeder'); | ||
$make->extend('Seeder'); | ||
$make->setEndWithNewLine(); | ||
$make->addMethod('run') | ||
->visibility(Method::PUBLIC_) | ||
->setReturnType('void') | ||
->body('// run some insert db'); | ||
|
||
if (file_put_contents(seeder_path() . $class . '.php', $make->__toString())) { | ||
ok('Success create seeder')->out(); | ||
|
||
return 0; | ||
} | ||
|
||
fail('Fail to create seeder')->out(); | ||
|
||
return 1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace System\Test\Integrate\Commands; | ||
|
||
use System\Integrate\Console\SeedCommand; | ||
|
||
final class SeedCommandsTest extends CommandTest | ||
{ | ||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
} | ||
|
||
protected function tearDown(): void | ||
{ | ||
parent::tearDown(); | ||
|
||
$migration = __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'seeders' . DIRECTORY_SEPARATOR; | ||
array_map('unlink', glob("{$migration}/*.php")); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function itCanCallMakeCommandSeederWithSuccess() | ||
{ | ||
$makeCommand = new SeedCommand($this->argv('cli make:seed BaseSeeder')); | ||
ob_start(); | ||
$exit = $makeCommand->make(); | ||
ob_get_clean(); | ||
|
||
$this->assertSuccess($exit); | ||
|
||
$file = __DIR__ . '/assets/seeders/BaseSeeder.php'; | ||
$this->assertTrue(file_exists($file)); | ||
|
||
$class = file_get_contents($file); | ||
$this->assertContain('class BaseSeeder extends Seeder', $class, 'Stub test'); | ||
$this->assertContain('public function run(): void', $class, 'Stub test'); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function itCanCallMakeCommandSeedWithFails() | ||
{ | ||
$makeCommand = new SeedCommand($this->argv('cli make:seed')); | ||
ob_start(); | ||
$exit = $makeCommand->make(); | ||
ob_get_clean(); | ||
|
||
$this->assertFails($exit); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function itCanCallMakeCommandSeedWithFailsFileExist() | ||
{ | ||
app()->setSeederPath(__DIR__ . '//database//seeders//'); | ||
$makeCommand = new SeedCommand($this->argv('cli make:seed BasicSeeder')); | ||
ob_start(); | ||
$exit = $makeCommand->make(); | ||
ob_get_clean(); | ||
|
||
$this->assertFails($exit); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function itCanCallMakeExistCommandSeeder() | ||
{ | ||
app()->setSeederPath(__DIR__ . '//database//seeders//'); | ||
$makeCommand = new SeedCommand($this->argv('cli make:seed ExistSeeder --force')); | ||
ob_start(); | ||
$exit = $makeCommand->make(); | ||
ob_get_clean(); | ||
|
||
$this->assertSuccess($exit); | ||
|
||
$file = __DIR__ . '//database//seeders//ExistSeeder.php'; | ||
$this->assertTrue(file_exists($file)); | ||
|
||
$class = file_get_contents($file); | ||
$this->assertContain('class ExistSeeder extends Seeder', $class, 'Stub test'); | ||
$this->assertContain('public function run(): void', $class, 'Stub test'); | ||
} | ||
} |
Oops, something went wrong.