Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] Support Integrate Seeder #217

Merged
merged 6 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/System/Database/Seeder/Seeder.php
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;
}
28 changes: 27 additions & 1 deletion src/System/Integrate/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ final class Application extends Container
*/
private string $migraton_path;

/**
* Seeder path.
*/
private string $seeder_path;

/**
* Public path.
*/
Expand Down Expand Up @@ -226,6 +231,7 @@ public function loadConfig(string $base_path)
$this->setProviderPath($configs['SERVICE_PROVIDER']);
$this->setMigrationPath($configs['MIGRATION_PATH']);
$this->setPublicPath($configs['PUBLIC_PATH']);
$this->setSeederPath($configs['SEEDER_PATH']);
// pusher config
$this->set('config.pusher_id', $configs['PUSHER_APP_ID']);
$this->set('config.pusher_key', $configs['PUSHER_APP_KEY']);
Expand Down Expand Up @@ -262,8 +268,9 @@ private function defaultConfigs()
'CONFIG' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR,
'MIDDLEWARE' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'middleware' . DIRECTORY_SEPARATOR,
'SERVICE_PROVIDER' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'Providers' . DIRECTORY_SEPARATOR,
'MIGRATION_PATH' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR,
'MIGRATION_PATH' => DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR,
'PUBLIC_PATH' => DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR,
'SEEDER_PATH' => DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'seeders' . DIRECTORY_SEPARATOR,

'PROVIDERS' => [
// provider class name
Expand Down Expand Up @@ -503,6 +510,17 @@ public function setMigrationPath(string $path): self
return $this;
}

/**
* Set seeder path.
*/
public function setSeederPath(string $path): self
{
$this->seeder_path = $this->base_path . $path;
$this->set('path.seeder', $this->seeder_path);

return $this;
}

/**
* Set public path.
*/
Expand Down Expand Up @@ -644,6 +662,14 @@ public function migration_path(): string
return $this->get('path.migration');
}

/**
* Get seeder path.
*/
public function seeder_path(): string
{
return $this->get('path.seeder');
}

/**
* Get public path.
*/
Expand Down
161 changes: 161 additions & 0 deletions src/System/Integrate/Console/SeedCommand.php
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;
}
}
9 changes: 9 additions & 0 deletions src/System/Integrate/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ function migration_path(string $surfix_path = ''): string
}
}

if (!function_exists('seeder_path')) {
function seeder_path(string $surfix_path = ''): string
{
$path = app()->seeder_path() . $surfix_path;

return $path;
}
}

if (!function_exists('base_path')) {
/**
* Get base path.
Expand Down
3 changes: 2 additions & 1 deletion tests/Integrate/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ private function defaultConfigs()
'CONFIG' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR,
'MIDDLEWARE' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'middleware' . DIRECTORY_SEPARATOR,
'SERVICE_PROVIDER' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'Providers' . DIRECTORY_SEPARATOR,
'MIGRATION_PATH' => DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR,
'MIGRATION_PATH' => DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR,
'PUBLIC_PATH' => DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR,
'SEEDER_PATH' => DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'seeders' . DIRECTORY_SEPARATOR,

'PROVIDERS' => [
// provider class name
Expand Down
1 change: 1 addition & 0 deletions tests/Integrate/Commands/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ protected function setUp(): void
$this->app->setCommandPath(__DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR);
$this->app->setConfigPath(__DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR);
$this->app->setMigrationPath(__DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'migration' . DIRECTORY_SEPARATOR);
$this->app->setSeederPath(__DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'seeders' . DIRECTORY_SEPARATOR);
}

protected function tearDown(): void
Expand Down
91 changes: 91 additions & 0 deletions tests/Integrate/Commands/SeedCommandsTest.php
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');
}
}
Loading
Loading