Skip to content

Commit

Permalink
Merge pull request #189 from kitloong/feature/vendor
Browse files Browse the repository at this point in the history
Ignore vendor migrations
  • Loading branch information
kitloong authored Oct 10, 2023
2 parents 45af5f6 + e601aa1 commit 220b5f1
Show file tree
Hide file tree
Showing 15 changed files with 493 additions and 23 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Add following line into the `Register Service Providers` section.
```php
$app->register(\KitLoong\MigrationsGenerator\MigrationsGeneratorServiceProvider::class);
```

</details>

## Usage
Expand Down Expand Up @@ -105,7 +106,7 @@ php artisan migrate:generate --connection="connection_name"

### Squash Migrations

By default, Generator will generate multiple migration files for each table.
By default, Generator will generate multiple migration files for each table.

You can squash all migrations into a single file with:

Expand Down Expand Up @@ -134,6 +135,7 @@ Run `php artisan help migrate:generate` for a list of options.
| --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-vendor | Don\'t generate vendor migrations |
| --skip-views | Don\'t generate views |
| --skip-proc | Don\'t generate stored procedures |
| --squash | Generate all migrations into a single file |
Expand Down
1 change: 1 addition & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
<!--<rule ref="SlevomatCodingStandard.Functions.DisallowTrailingCommaInClosureUse"/>-->
<!--<rule ref="SlevomatCodingStandard.Functions.DisallowTrailingCommaInDeclaration"/>-->
<!--<rule ref="SlevomatCodingStandard.Functions.FunctionLength"/>-->
<rule ref="SlevomatCodingStandard.Functions.NamedArgumentSpacing"/>
<!--<rule ref="SlevomatCodingStandard.Functions.RequireArrowFunction"/>-->
<!--<rule ref="SlevomatCodingStandard.Functions.RequireMultiLineCall"/>-->
<!--<rule ref="SlevomatCodingStandard.Functions.RequireSingleLineCall"/>-->
Expand Down
26 changes: 14 additions & 12 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
stderr="true"
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
stderr="true"
>
<coverage includeUncoveredFiles="true">
<coverage includeUncoveredFiles="true"/>
<testsuites>
<testsuite name="Application Test Suite">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
<exclude>
<directory>src/KitLoong/MigrationsGenerator/Types</directory>
</exclude>
</coverage>
<testsuites>
<testsuite name="Application Test Suite">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
</source>
</phpunit>
9 changes: 8 additions & 1 deletion src/MigrateGenerateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Illuminate\Support\Facades\DB;
use KitLoong\MigrationsGenerator\Enum\Driver;
use KitLoong\MigrationsGenerator\Migration\ForeignKeyMigration;
use KitLoong\MigrationsGenerator\Migration\Migrator\Migrator;
use KitLoong\MigrationsGenerator\Migration\ProcedureMigration;
use KitLoong\MigrationsGenerator\Migration\Squash;
use KitLoong\MigrationsGenerator\Migration\TableMigration;
Expand Down Expand Up @@ -50,6 +51,7 @@ class MigrateGenerateCommand extends Command
{--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-vendor : Don\'t generate vendor migrations}
{--skip-views : Don\'t generate views}
{--skip-proc : Don\'t generate stored procedures}
{--squash : Generate all migrations into a single file}
Expand Down Expand Up @@ -300,7 +302,12 @@ protected function getExcludedTables(): array
$ignore = (string) $this->option('ignore');

if (!empty($ignore)) {
return array_merge([$migrationTable], explode(',', $ignore));
$excludes = array_merge($excludes, explode(',', $ignore));
}

if ($this->option('skip-vendor')) {
$vendorTables = app(Migrator::class)->getVendorTableNames();
$excludes = array_merge($excludes, $vendorTables);
}

return $excludes;
Expand Down
91 changes: 91 additions & 0 deletions src/Migration/Migrator/Migrator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace KitLoong\MigrationsGenerator\Migration\Migrator;

use Illuminate\Database\Migrations\Migrator as DefaultMigrator;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use KitLoong\MigrationsGenerator\Support\Regex;

class Migrator extends DefaultMigrator
{
/**
* Scan and get vendors' loaded migration table names.
*
* @return string[]
*/
public function getVendorTableNames(): array
{
$tables = [];

// Backup the current DB connection.
$previousConnection = DB::getDefaultConnection();

try {
// Create an in-memory SQLite database for the migrations generator.
// Note that no real migrations will be executed, this is simply a precautionary switch to in-memory SQLite.
Config::set('database.connections.lgm_sqlite', [
'driver' => 'sqlite',
'database' => ':memory:',
]);

DB::setDefaultConnection('lgm_sqlite');

$vendorPaths = app('migrator')->paths();

foreach ($vendorPaths as $path) {
$files = File::files($path);

foreach ($files as $file) {
$queries = $this->getMigrationQueries($file->getPathname());

foreach ($queries as $q) {
$matched = Regex::match('/^create table ["|`](.*?)["|`]/', $q['query']);

if ($matched === '') {
continue;
}

$tables[] = $matched;
}
}
}
} finally {
// Restore backup DB connection.
DB::setDefaultConnection($previousConnection);
}

return $tables;
}

/**
* Resolve migration instance from `$path` and get all of the queries that would be run for a migration.
*
* @return array<int, array{'query': string, 'bindings': array<string, array<mixed>>, 'time': float|null}>
*/
protected function getMigrationQueries(string $path): array
{
$migration = $this->resolveMigration($path);

return $this->getQueries($migration, 'up');
}

/**
* Resolve migration instance with backward compatibility.
*
* @return object
*/
protected function resolveMigration(string $path)
{
if (method_exists(DefaultMigrator::class, 'resolvePath')) {
return $this->resolvePath($path);
}

// @codeCoverageIgnoreStart
return $this->resolve(
$this->getMigrationName($path)
);
// @codeCoverageIgnoreEnd
}
}
19 changes: 12 additions & 7 deletions src/MigrationsGeneratorServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use KitLoong\MigrationsGenerator\Migration\Generator\Columns\PresetValuesColumn;
use KitLoong\MigrationsGenerator\Migration\Generator\Columns\SoftDeleteColumn;
use KitLoong\MigrationsGenerator\Migration\Generator\Columns\StringColumn;
use KitLoong\MigrationsGenerator\Migration\Migrator\Migrator;
use KitLoong\MigrationsGenerator\Repositories\MariaDBRepository;
use KitLoong\MigrationsGenerator\Repositories\MySQLRepository;
use KitLoong\MigrationsGenerator\Repositories\PgSQLRepository;
Expand All @@ -34,9 +35,6 @@ class MigrationsGeneratorServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function register(): void
{
Expand Down Expand Up @@ -69,13 +67,23 @@ public function register(): void
}

// Bind the Repository Interface to $app['migrations.repository']
$this->app->bind(
$this->app->singleton(
MigrationRepositoryInterface::class,
function ($app) {
return $app['migration.repository'];
}
);

// Backward compatible for older Laravel version which failed to resolve Illuminate\Database\ConnectionResolverInterface.
$this->app->singleton(
Migrator::class,
function ($app) {
$repository = $app['migration.repository'];

return new Migrator($repository, $app['db'], $app['files'], $app['events']);
}
);

$this->registerColumnTypeGenerator();
}

Expand All @@ -92,9 +100,6 @@ public function boot(): void

/**
* Register the config path.
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
protected function registerConfig(): void
{
Expand Down
33 changes: 33 additions & 0 deletions tests/Feature/FeatureTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ protected function getStorageFromPath(string $path = ''): string
return storage_path('from') . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}

protected function getStorageFromVendorsPath(string $path = ''): string
{
return storage_path("from/vendors") . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}

protected function getStorageSqlPath(string $path = ''): string
{
return storage_path('sql') . ($path ? DIRECTORY_SEPARATOR . $path : $path);
Expand All @@ -96,6 +101,11 @@ protected function migrateCollation(string $connection): void
$this->migrateFromTemplate($connection, base_path('tests/resources/database/migrations/collation'));
}

protected function migrateVendors(string $connection): void
{
$this->migrateFromVendorsTemplate($connection, base_path('tests/resources/database/migrations/vendors'));
}

protected function migrateFromTemplate(string $connection, string $templatePath): void
{
File::copyDirectory($templatePath, $this->getStorageFromPath());
Expand All @@ -119,6 +129,29 @@ protected function migrateFromTemplate(string $connection, string $templatePath)
$this->runMigrationsFrom($connection, $this->getStorageFromPath());
}

protected function migrateFromVendorsTemplate(string $connection, string $templatePath): void
{
File::copyDirectory($templatePath, $this->getStorageFromVendorsPath());

foreach (File::files($this->getStorageFromVendorsPath()) as $file) {
$content = str_replace([
'[db]',
'_DB_',
], [
$connection,
ucfirst("$connection"),
], $file->getContents());

File::put($this->getStorageFromVendorsPath($file->getBasename()), $content);
File::move(
$this->getStorageFromVendorsPath($file->getBasename()),
$this->getStorageFromVendorsPath(str_replace('_db_', "_{$connection}_", $file->getBasename()))
);
}

$this->runMigrationsFrom($connection, $this->getStorageFromVendorsPath());
}

protected function runMigrationsFrom(string $connection, string $path): void
{
$this->artisan('migrate', [
Expand Down
43 changes: 43 additions & 0 deletions tests/Feature/MySQL57/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace KitLoong\MigrationsGenerator\Tests\Feature\MySQL57;

use Illuminate\Database\Migrations\MigrationRepositoryInterface;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
Expand Down Expand Up @@ -508,6 +509,48 @@ public function testLogWithBatchNaN(): void
);
}

public function testSkipVendor(): void
{
$this->migrateGeneral('mysql57');

$this->migrateVendors('mysql57');

// Load migrations from vendors path to mock vendors migration.
// Loaded migrations should not be generated.
app('migrator')->path($this->getStorageFromVendorsPath());

$tables = $this->getTableNames();

$vendors = [
'personal_access_tokens_mysql57',
'telescope_entries_mysql57',
'telescope_entries_tags_mysql57',
'telescope_monitoring_mysql57',
];

foreach ($vendors as $vendor) {
$this->assertContains($vendor, $tables);
}

$tablesWithoutVendors = (new Collection($tables))->filter(function ($table) use ($vendors) {
return !in_array($table, $vendors);
})
->values()
->all();

$this->truncateMigrationsTable();

$this->generateMigrations(['--skip-vendor' => true]);

$this->refreshDatabase();

$this->runMigrationsFrom('mysql57', $this->getStorageMigrationsPath());

$generatedTables = $this->getTableNames();

$this->assertSame($tablesWithoutVendors, $generatedTables);
}

private function verify(callable $migrateTemplates, callable $generateMigrations): void
{
$migrateTemplates();
Expand Down
Loading

0 comments on commit 220b5f1

Please sign in to comment.