Skip to content

Commit

Permalink
Merge pull request #146 from kitloong/feature/has-table
Browse files Browse the repository at this point in the history
Add `Schema::hasTable` option
  • Loading branch information
kitloong authored Dec 26, 2022
2 parents be7b69e + 08ff816 commit ea33a94
Show file tree
Hide file tree
Showing 10 changed files with 339 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .phpmd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</rule>
<rule ref="rulesets/codesize.xml/ExcessiveClassComplexity">
<properties>
<property name="maximum" value="65"/>
<property name="maximum" value="70"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/ExcessiveParameterList">
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,24 @@ Run `php artisan help migrate:generate` for a list of options.
| Options | Description |
|--------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| -c, --connection[=CONNECTION] | The database connection to use |
| -t, --tables[=TABLES] | A list of Tables or Views you wish to Generate Migrations for separated by a comma: users,posts,comments |
| -i, --ignore[=IGNORE] | A list of Tables or Views you wish to ignore, separated by a comma: users,posts,comments |
| -t, --tables[=TABLES] | A list of tables or views you wish to generate migrations for separated by a comma: users,posts,comments |
| -i, --ignore[=IGNORE] | A list of tables or views you wish to ignore, separated by a comma: users,posts,comments |
| -p, --path[=PATH] | Where should the file be created? |
| -tp, --template-path[=TEMPLATE-PATH] | The location of the template for this generator |
| --date[=DATE] | Migrations will be created with specified date. Views and Foreign keys will be created with + 1 second. Date should be in format supported by `Carbon::parse` |
| --date[=DATE] | Migrations will be created with specified date. Views and foreign keys will be created with + 1 second. Date should be in format supported by `Carbon::parse` |
| --table-filename[=TABLE-FILENAME] | Define table migration filename, default pattern: `[datetime]\_create_[name]_table.php` |
| --view-filename[=VIEW-FILENAME] | Define view migration filename, default pattern: `[datetime]\_create_[name]_view.php` |
| --proc-filename[=PROC-FILENAME] | Define stored procedure filename, default pattern: `[datetime]\_create_[name]_proc.php` |
| --fk-filename[=FK-FILENAME] | Define foreign key migration filename, default pattern: `[datetime]\_add_foreign_keys_to_[name]_table.php` |
| --log-with-batch[=LOG-WITH-BATCH] | Log migrations with given batch number. We recommend using batch number 0 so that it becomes the first migration |
| --default-index-names | Don\'t use DB index names for migrations |
| --default-fk-names | Don\'t use DB foreign key names for migrations |
| --use-db-collation | Generate migrations with existing DB collation |
| --skip-log | Don\'t log into migrations table |
| --skip-views | Don\'t generate views |
| --skip-proc | Don\'t generate stored procedures |
| --squash | Generate all migrations into a single file |
| --with-has-table | Check for the existence of a table using `hasTable` |

## SQLite Alter Foreign Key

Expand Down
2 changes: 2 additions & 0 deletions src/Enum/Migrations/Method/SchemaBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
* @method static self CONNECTION()
* @method static self CREATE()
* @method static self DROP_IF_EXISTS()
* @method static self HAS_TABLE()
* @method static self TABLE()
*/
final class SchemaBuilder extends Enum
{
private const CONNECTION = 'connection';
private const CREATE = 'create';
private const DROP_IF_EXISTS = 'dropIfExists';
private const HAS_TABLE = 'hasTable';
private const TABLE = 'table';
}
53 changes: 43 additions & 10 deletions src/MigrateGenerateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,26 @@ class MigrateGenerateCommand extends Command
* @var string
*/
protected $signature = 'migrate:generate
{tables? : A list of Tables or Views you wish to Generate Migrations for separated by a comma: users,posts,comments}
{tables? : A list of tables or views you wish to generate migrations for separated by a comma: users,posts,comments}
{--c|connection= : The database connection to use}
{--t|tables= : A list of Tables or Views you wish to Generate Migrations for separated by a comma: users,posts,comments}
{--i|ignore= : A list of Tables or Views you wish to ignore, separated by a comma: users,posts,comments}
{--t|tables= : A list of tables or views you wish to generate migrations for separated by a comma: users,posts,comments}
{--i|ignore= : A list of tables or views you wish to ignore, separated by a comma: users,posts,comments}
{--p|path= : Where should the file be created?}
{--tp|template-path= : The location of the template for this generator}
{--date= : Migrations will be created with specified date. Views and Foreign keys will be created with + 1 second. Date should be in format supported by Carbon::parse}
{--date= : Migrations will be created with specified date. Views and foreign keys will be created with + 1 second. Date should be in format supported by Carbon::parse}
{--table-filename= : Define table migration filename, default pattern: [datetime]_create_[name]_table.php}
{--view-filename= : Define view migration filename, default pattern: [datetime]_create_[name]_view.php}
{--proc-filename= : Define stored procedure migration filename, default pattern: [datetime]_create_[name]_proc.php}
{--fk-filename= : Define foreign key migration filename, default pattern: [datetime]_add_foreign_keys_to_[name]_table.php}
{--log-with-batch= : Log migrations with given batch number. We recommend using batch number 0 so that it becomes the first migration}
{--default-index-names : Don\'t use DB index names for migrations}
{--default-fk-names : Don\'t use DB foreign key names for migrations}
{--use-db-collation : Generate migrations with existing DB collation}
{--skip-log : Don\'t log into migrations table}
{--skip-views : Don\'t generate views}
{--skip-proc : Don\'t generate stored procedures}
{--squash : Generate all migrations into a single file}';
{--squash : Generate all migrations into a single file}
{--with-has-table : Check for the existence of a table using `hasTable`}';

/**
* The console command description.
Expand Down Expand Up @@ -142,10 +145,11 @@ protected function setup(string $connection): void
{
$setting = app(Setting::class);
$setting->setDefaultConnection($connection);
$setting->setUseDBCollation($this->option('use-db-collation'));
$setting->setIgnoreIndexNames($this->option('default-index-names'));
$setting->setIgnoreForeignKeyNames($this->option('default-fk-names'));
$setting->setUseDBCollation((bool) $this->option('use-db-collation'));
$setting->setIgnoreIndexNames((bool) $this->option('default-index-names'));
$setting->setIgnoreForeignKeyNames((bool) $this->option('default-fk-names'));
$setting->setSquash((bool) $this->option('squash'));
$setting->setWithHasTable((bool) $this->option('with-has-table'));

$setting->setPath(
$this->option('path') ?? Config::get('migrations-generator.migration_target_path')
Expand Down Expand Up @@ -277,13 +281,16 @@ protected function getExcludedTables(): array
*
* @param string $defaultConnection
* @return void
* @throws \Exception
*/
protected function askIfLogMigrationTable(string $defaultConnection): void
{
if (!$this->option('no-interaction')) {
$this->shouldLog = $this->confirm('Do you want to log these migrations in the migrations table?', true);
if ($this->skipInput()) {
return;
}

$this->shouldLog = $this->confirm('Do you want to log these migrations in the migrations table?', true);

if (!$this->shouldLog) {
return;
}
Expand Down Expand Up @@ -311,6 +318,32 @@ protected function askIfLogMigrationTable(string $defaultConnection): void
);
}

/**
* Checks if should skip gather input from the user.
*
* @return bool
* @throws \Exception
*/
protected function skipInput(): bool
{
if ($this->option('no-interaction') || $this->option('skip-log')) {
return true;
}

if ($this->option('log-with-batch') === null) {
return false;
}

if (!ctype_digit($this->option('log-with-batch'))) {
throw new Exception('--log-with-batch must be a valid integer.');
}

$this->shouldLog = true;
$this->nextBatchNumber = (int) $this->option('log-with-batch');

return true;
}

/**
* Ask user for a Numeric Value, or blank for default.
*
Expand Down
82 changes: 73 additions & 9 deletions src/Migration/Blueprint/SchemaBlueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use KitLoong\MigrationsGenerator\Migration\Blueprint\Support\MethodStringHelper;
use KitLoong\MigrationsGenerator\Migration\Blueprint\Support\Stringable;
use KitLoong\MigrationsGenerator\Migration\Enum\Space;
use KitLoong\MigrationsGenerator\Setting;
use KitLoong\MigrationsGenerator\Support\TableName;

/**
Expand Down Expand Up @@ -37,6 +38,8 @@ class SchemaBlueprint implements WritableBlueprint
use TableName;

/**
* The table name without prefix. {@see \Illuminate\Support\Facades\DB::getTablePrefix()}
*
* @var string
*/
private $table;
Expand All @@ -57,7 +60,7 @@ class SchemaBlueprint implements WritableBlueprint
*/
public function __construct(string $table, SchemaBuilder $schemaBuilder)
{
$this->table = $table;
$this->table = $this->stripTablePrefix($table);
$this->schemaBuilder = $schemaBuilder;
$this->blueprint = null;
}
Expand Down Expand Up @@ -86,19 +89,80 @@ private function getLines(): array
{
$schema = $this->connection('Schema', $this->schemaBuilder);

$tableWithoutPrefix = $this->stripTablePrefix($this->table);
if ($this->schemaBuilder->equals(SchemaBuilder::DROP_IF_EXISTS())) {
return $this->getDropLines($schema);
}

$tableLines = $this->getTableLines($schema);

if (!app(Setting::class)->isWithHasTable()) {
return $tableLines;
}

$schemaHasTable = $this->connection('Schema', SchemaBuilder::HAS_TABLE());

$lines = [];

if ($this->blueprint !== null) {
$lines[] = "$schema('$tableWithoutPrefix', function (Blueprint \$table) {";
// Add 1 tabulation to indent(prettify) blueprint definition.
$lines[] = Space::TAB() . $this->blueprint->toString();
$lines[] = "});";
return $lines;
$lines[] = $this->getIfCondition($schemaHasTable, $this->table);

foreach ($tableLines as $tableLine) {
// Add another tabulation to indent(prettify) blueprint definition.
$lines[] = Space::TAB() . $tableLine;
}

$lines[] = "}";

return $lines;
}

/**
* Get drop commands in array.
*
* @param string $schema The stringify `Schema::something` or `Schema::connection('db')->something`.
* @return string[]
*/
private function getDropLines(string $schema): array
{
return [
"$schema('$this->table');",
];
}

/**
* Get table commands in array.
*
* @param string $schema The stringify `Schema::something` or `Schema::connection('db')->something`.
* @return array
*/
private function getTableLines(string $schema): array
{
$lines = [];
$lines[] = "$schema('$this->table', function (Blueprint \$table) {";

if (app(Setting::class)->isWithHasTable()) {
$this->blueprint->increaseNumberOfPrefixTab();
}

$lines[] = "$schema('$tableWithoutPrefix');";
// Add 1 tabulation to indent(prettify) blueprint definition.
$lines[] = Space::TAB() . $this->blueprint->toString();
$lines[] = "});";

return $lines;
}

/**
* Generate `if` condition string.
*
* @param string $schemaHasTable The stringify `Schema::hasTable` or `Schema::connection('db')->hasTable`.
* @param string $tableWithoutPrefix
* @return string
*/
private function getIfCondition(string $schemaHasTable, string $tableWithoutPrefix): string
{
if ($this->schemaBuilder->equals(SchemaBuilder::TABLE())) {
return "if ($schemaHasTable('$tableWithoutPrefix')) {";
}

return "if (!$schemaHasTable('$tableWithoutPrefix')) {";
}
}
19 changes: 18 additions & 1 deletion src/Migration/Blueprint/TableBlueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ class TableBlueprint implements WritableBlueprint
/** @var \KitLoong\MigrationsGenerator\Migration\Blueprint\Property[]|\KitLoong\MigrationsGenerator\Migration\Blueprint\Method[]|string[] */
private $lines;

/**
* By default, generate 3 tabs for each line.
*
* @var int
*/
private $numberOfPrefixTab = 3;

public function __construct()
{
$this->lines = [];
Expand Down Expand Up @@ -105,6 +112,16 @@ public function mergeTimestamps(): void
$this->lines = $this->merge($this->lines, true);
}

/**
* Increase number of prefix tab by 1.
*
* @return void
*/
public function increaseNumberOfPrefixTab(): void
{
$this->numberOfPrefixTab++;
}

/**
* @inheritDoc
*/
Expand All @@ -127,7 +144,7 @@ public function toString(): string
}
}

return $this->flattenLines($lines, 3);
return $this->flattenLines($lines, $this->numberOfPrefixTab);
}

/**
Expand Down
19 changes: 19 additions & 0 deletions src/Setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ class Setting
/** @var string */
private $fkFilename;

/** @var bool */
private $withHasTable;

/**
* @return string
*/
Expand Down Expand Up @@ -238,4 +241,20 @@ public function setDate(Carbon $date): void
{
$this->date = $date;
}

/**
* @return bool
*/
public function isWithHasTable(): bool
{
return $this->withHasTable;
}

/**
* @param bool $withHasTable
*/
public function setWithHasTable(bool $withHasTable): void
{
$this->withHasTable = $withHasTable;
}
}
Loading

0 comments on commit ea33a94

Please sign in to comment.