Skip to content

Commit 220b5f1

Browse files
authored
Merge pull request #189 from kitloong/feature/vendor
Ignore vendor migrations
2 parents 45af5f6 + e601aa1 commit 220b5f1

15 files changed

+493
-23
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Add following line into the `Register Service Providers` section.
6969
```php
7070
$app->register(\KitLoong\MigrationsGenerator\MigrationsGeneratorServiceProvider::class);
7171
```
72+
7273
</details>
7374

7475
## Usage
@@ -105,7 +106,7 @@ php artisan migrate:generate --connection="connection_name"
105106

106107
### Squash Migrations
107108

108-
By default, Generator will generate multiple migration files for each table.
109+
By default, Generator will generate multiple migration files for each table.
109110

110111
You can squash all migrations into a single file with:
111112

@@ -134,6 +135,7 @@ Run `php artisan help migrate:generate` for a list of options.
134135
| --default-fk-names | Don\'t use DB foreign key names for migrations |
135136
| --use-db-collation | Generate migrations with existing DB collation |
136137
| --skip-log | Don\'t log into migrations table |
138+
| --skip-vendor | Don\'t generate vendor migrations |
137139
| --skip-views | Don\'t generate views |
138140
| --skip-proc | Don\'t generate stored procedures |
139141
| --squash | Generate all migrations into a single file |

phpcs.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
<!--<rule ref="SlevomatCodingStandard.Functions.DisallowTrailingCommaInClosureUse"/>-->
145145
<!--<rule ref="SlevomatCodingStandard.Functions.DisallowTrailingCommaInDeclaration"/>-->
146146
<!--<rule ref="SlevomatCodingStandard.Functions.FunctionLength"/>-->
147+
<rule ref="SlevomatCodingStandard.Functions.NamedArgumentSpacing"/>
147148
<!--<rule ref="SlevomatCodingStandard.Functions.RequireArrowFunction"/>-->
148149
<!--<rule ref="SlevomatCodingStandard.Functions.RequireMultiLineCall"/>-->
149150
<!--<rule ref="SlevomatCodingStandard.Functions.RequireSingleLineCall"/>-->

phpunit.xml.dist

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3-
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
4-
bootstrap="vendor/autoload.php"
5-
colors="true"
6-
stderr="true"
2+
<phpunit
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
5+
bootstrap="vendor/autoload.php"
6+
colors="true"
7+
stderr="true"
78
>
8-
<coverage includeUncoveredFiles="true">
9+
<coverage includeUncoveredFiles="true"/>
10+
<testsuites>
11+
<testsuite name="Application Test Suite">
12+
<directory suffix="Test.php">tests</directory>
13+
</testsuite>
14+
</testsuites>
15+
<source>
916
<include>
1017
<directory suffix=".php">src</directory>
1118
</include>
1219
<exclude>
1320
<directory>src/KitLoong/MigrationsGenerator/Types</directory>
1421
</exclude>
15-
</coverage>
16-
<testsuites>
17-
<testsuite name="Application Test Suite">
18-
<directory suffix="Test.php">tests</directory>
19-
</testsuite>
20-
</testsuites>
22+
</source>
2123
</phpunit>

src/MigrateGenerateCommand.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Illuminate\Support\Facades\DB;
1212
use KitLoong\MigrationsGenerator\Enum\Driver;
1313
use KitLoong\MigrationsGenerator\Migration\ForeignKeyMigration;
14+
use KitLoong\MigrationsGenerator\Migration\Migrator\Migrator;
1415
use KitLoong\MigrationsGenerator\Migration\ProcedureMigration;
1516
use KitLoong\MigrationsGenerator\Migration\Squash;
1617
use KitLoong\MigrationsGenerator\Migration\TableMigration;
@@ -50,6 +51,7 @@ class MigrateGenerateCommand extends Command
5051
{--default-fk-names : Don\'t use DB foreign key names for migrations}
5152
{--use-db-collation : Generate migrations with existing DB collation}
5253
{--skip-log : Don\'t log into migrations table}
54+
{--skip-vendor : Don\'t generate vendor migrations}
5355
{--skip-views : Don\'t generate views}
5456
{--skip-proc : Don\'t generate stored procedures}
5557
{--squash : Generate all migrations into a single file}
@@ -300,7 +302,12 @@ protected function getExcludedTables(): array
300302
$ignore = (string) $this->option('ignore');
301303

302304
if (!empty($ignore)) {
303-
return array_merge([$migrationTable], explode(',', $ignore));
305+
$excludes = array_merge($excludes, explode(',', $ignore));
306+
}
307+
308+
if ($this->option('skip-vendor')) {
309+
$vendorTables = app(Migrator::class)->getVendorTableNames();
310+
$excludes = array_merge($excludes, $vendorTables);
304311
}
305312

306313
return $excludes;

src/Migration/Migrator/Migrator.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
namespace KitLoong\MigrationsGenerator\Migration\Migrator;
4+
5+
use Illuminate\Database\Migrations\Migrator as DefaultMigrator;
6+
use Illuminate\Support\Facades\Config;
7+
use Illuminate\Support\Facades\DB;
8+
use Illuminate\Support\Facades\File;
9+
use KitLoong\MigrationsGenerator\Support\Regex;
10+
11+
class Migrator extends DefaultMigrator
12+
{
13+
/**
14+
* Scan and get vendors' loaded migration table names.
15+
*
16+
* @return string[]
17+
*/
18+
public function getVendorTableNames(): array
19+
{
20+
$tables = [];
21+
22+
// Backup the current DB connection.
23+
$previousConnection = DB::getDefaultConnection();
24+
25+
try {
26+
// Create an in-memory SQLite database for the migrations generator.
27+
// Note that no real migrations will be executed, this is simply a precautionary switch to in-memory SQLite.
28+
Config::set('database.connections.lgm_sqlite', [
29+
'driver' => 'sqlite',
30+
'database' => ':memory:',
31+
]);
32+
33+
DB::setDefaultConnection('lgm_sqlite');
34+
35+
$vendorPaths = app('migrator')->paths();
36+
37+
foreach ($vendorPaths as $path) {
38+
$files = File::files($path);
39+
40+
foreach ($files as $file) {
41+
$queries = $this->getMigrationQueries($file->getPathname());
42+
43+
foreach ($queries as $q) {
44+
$matched = Regex::match('/^create table ["|`](.*?)["|`]/', $q['query']);
45+
46+
if ($matched === '') {
47+
continue;
48+
}
49+
50+
$tables[] = $matched;
51+
}
52+
}
53+
}
54+
} finally {
55+
// Restore backup DB connection.
56+
DB::setDefaultConnection($previousConnection);
57+
}
58+
59+
return $tables;
60+
}
61+
62+
/**
63+
* Resolve migration instance from `$path` and get all of the queries that would be run for a migration.
64+
*
65+
* @return array<int, array{'query': string, 'bindings': array<string, array<mixed>>, 'time': float|null}>
66+
*/
67+
protected function getMigrationQueries(string $path): array
68+
{
69+
$migration = $this->resolveMigration($path);
70+
71+
return $this->getQueries($migration, 'up');
72+
}
73+
74+
/**
75+
* Resolve migration instance with backward compatibility.
76+
*
77+
* @return object
78+
*/
79+
protected function resolveMigration(string $path)
80+
{
81+
if (method_exists(DefaultMigrator::class, 'resolvePath')) {
82+
return $this->resolvePath($path);
83+
}
84+
85+
// @codeCoverageIgnoreStart
86+
return $this->resolve(
87+
$this->getMigrationName($path)
88+
);
89+
// @codeCoverageIgnoreEnd
90+
}
91+
}

src/MigrationsGeneratorServiceProvider.php

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use KitLoong\MigrationsGenerator\Migration\Generator\Columns\PresetValuesColumn;
2121
use KitLoong\MigrationsGenerator\Migration\Generator\Columns\SoftDeleteColumn;
2222
use KitLoong\MigrationsGenerator\Migration\Generator\Columns\StringColumn;
23+
use KitLoong\MigrationsGenerator\Migration\Migrator\Migrator;
2324
use KitLoong\MigrationsGenerator\Repositories\MariaDBRepository;
2425
use KitLoong\MigrationsGenerator\Repositories\MySQLRepository;
2526
use KitLoong\MigrationsGenerator\Repositories\PgSQLRepository;
@@ -34,9 +35,6 @@ class MigrationsGeneratorServiceProvider extends ServiceProvider
3435
{
3536
/**
3637
* Register the service provider.
37-
*
38-
* @throws \Illuminate\Contracts\Container\BindingResolutionException
39-
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
4038
*/
4139
public function register(): void
4240
{
@@ -69,13 +67,23 @@ public function register(): void
6967
}
7068

7169
// Bind the Repository Interface to $app['migrations.repository']
72-
$this->app->bind(
70+
$this->app->singleton(
7371
MigrationRepositoryInterface::class,
7472
function ($app) {
7573
return $app['migration.repository'];
7674
}
7775
);
7876

77+
// Backward compatible for older Laravel version which failed to resolve Illuminate\Database\ConnectionResolverInterface.
78+
$this->app->singleton(
79+
Migrator::class,
80+
function ($app) {
81+
$repository = $app['migration.repository'];
82+
83+
return new Migrator($repository, $app['db'], $app['files'], $app['events']);
84+
}
85+
);
86+
7987
$this->registerColumnTypeGenerator();
8088
}
8189

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

93101
/**
94102
* Register the config path.
95-
*
96-
* @throws \Illuminate\Contracts\Container\BindingResolutionException
97-
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
98103
*/
99104
protected function registerConfig(): void
100105
{

tests/Feature/FeatureTestCase.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ protected function getStorageFromPath(string $path = ''): string
8181
return storage_path('from') . ($path ? DIRECTORY_SEPARATOR . $path : $path);
8282
}
8383

84+
protected function getStorageFromVendorsPath(string $path = ''): string
85+
{
86+
return storage_path("from/vendors") . ($path ? DIRECTORY_SEPARATOR . $path : $path);
87+
}
88+
8489
protected function getStorageSqlPath(string $path = ''): string
8590
{
8691
return storage_path('sql') . ($path ? DIRECTORY_SEPARATOR . $path : $path);
@@ -96,6 +101,11 @@ protected function migrateCollation(string $connection): void
96101
$this->migrateFromTemplate($connection, base_path('tests/resources/database/migrations/collation'));
97102
}
98103

104+
protected function migrateVendors(string $connection): void
105+
{
106+
$this->migrateFromVendorsTemplate($connection, base_path('tests/resources/database/migrations/vendors'));
107+
}
108+
99109
protected function migrateFromTemplate(string $connection, string $templatePath): void
100110
{
101111
File::copyDirectory($templatePath, $this->getStorageFromPath());
@@ -119,6 +129,29 @@ protected function migrateFromTemplate(string $connection, string $templatePath)
119129
$this->runMigrationsFrom($connection, $this->getStorageFromPath());
120130
}
121131

132+
protected function migrateFromVendorsTemplate(string $connection, string $templatePath): void
133+
{
134+
File::copyDirectory($templatePath, $this->getStorageFromVendorsPath());
135+
136+
foreach (File::files($this->getStorageFromVendorsPath()) as $file) {
137+
$content = str_replace([
138+
'[db]',
139+
'_DB_',
140+
], [
141+
$connection,
142+
ucfirst("$connection"),
143+
], $file->getContents());
144+
145+
File::put($this->getStorageFromVendorsPath($file->getBasename()), $content);
146+
File::move(
147+
$this->getStorageFromVendorsPath($file->getBasename()),
148+
$this->getStorageFromVendorsPath(str_replace('_db_', "_{$connection}_", $file->getBasename()))
149+
);
150+
}
151+
152+
$this->runMigrationsFrom($connection, $this->getStorageFromVendorsPath());
153+
}
154+
122155
protected function runMigrationsFrom(string $connection, string $path): void
123156
{
124157
$this->artisan('migrate', [

tests/Feature/MySQL57/CommandTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace KitLoong\MigrationsGenerator\Tests\Feature\MySQL57;
44

55
use Illuminate\Database\Migrations\MigrationRepositoryInterface;
6+
use Illuminate\Support\Collection;
67
use Illuminate\Support\Facades\DB;
78
use Illuminate\Support\Facades\File;
89
use Illuminate\Support\Facades\Schema;
@@ -508,6 +509,48 @@ public function testLogWithBatchNaN(): void
508509
);
509510
}
510511

512+
public function testSkipVendor(): void
513+
{
514+
$this->migrateGeneral('mysql57');
515+
516+
$this->migrateVendors('mysql57');
517+
518+
// Load migrations from vendors path to mock vendors migration.
519+
// Loaded migrations should not be generated.
520+
app('migrator')->path($this->getStorageFromVendorsPath());
521+
522+
$tables = $this->getTableNames();
523+
524+
$vendors = [
525+
'personal_access_tokens_mysql57',
526+
'telescope_entries_mysql57',
527+
'telescope_entries_tags_mysql57',
528+
'telescope_monitoring_mysql57',
529+
];
530+
531+
foreach ($vendors as $vendor) {
532+
$this->assertContains($vendor, $tables);
533+
}
534+
535+
$tablesWithoutVendors = (new Collection($tables))->filter(function ($table) use ($vendors) {
536+
return !in_array($table, $vendors);
537+
})
538+
->values()
539+
->all();
540+
541+
$this->truncateMigrationsTable();
542+
543+
$this->generateMigrations(['--skip-vendor' => true]);
544+
545+
$this->refreshDatabase();
546+
547+
$this->runMigrationsFrom('mysql57', $this->getStorageMigrationsPath());
548+
549+
$generatedTables = $this->getTableNames();
550+
551+
$this->assertSame($tablesWithoutVendors, $generatedTables);
552+
}
553+
511554
private function verify(callable $migrateTemplates, callable $generateMigrations): void
512555
{
513556
$migrateTemplates();

0 commit comments

Comments
 (0)