From e91ca2f77de34d252214ec4671221b7af58a8fa5 Mon Sep 17 00:00:00 2001 From: Gianluca Bine Date: Sat, 23 May 2020 02:16:50 -0300 Subject: [PATCH 1/2] Add ability to customize pivot table columns --- src/Generators/MigrationGenerator.php | 14 ++++- src/Generators/ModelGenerator.php | 12 ++-- .../Generator/MigrationGeneratorTest.php | 58 +++++++++++++++++++ .../Feature/Generator/ModelGeneratorTest.php | 33 +++++++++++ .../definitions/custom-pivot-column.bp | 6 ++ .../custom-pivot-column-test-laravel6.php | 31 ++++++++++ .../migrations/custom-pivot-column-test.php | 31 ++++++++++ .../custom-pivot-column-user-laravel6.php | 33 +++++++++++ .../migrations/custom-pivot-column-user.php | 33 +++++++++++ tests/fixtures/models/custom-pivot-column.php | 41 +++++++++++++ 10 files changed, 286 insertions(+), 6 deletions(-) create mode 100644 tests/fixtures/definitions/custom-pivot-column.bp create mode 100644 tests/fixtures/migrations/custom-pivot-column-test-laravel6.php create mode 100644 tests/fixtures/migrations/custom-pivot-column-test.php create mode 100644 tests/fixtures/migrations/custom-pivot-column-user-laravel6.php create mode 100644 tests/fixtures/migrations/custom-pivot-column-user.php create mode 100644 tests/fixtures/models/custom-pivot-column.php diff --git a/src/Generators/MigrationGenerator.php b/src/Generators/MigrationGenerator.php index f0f98bb5..39338fb6 100644 --- a/src/Generators/MigrationGenerator.php +++ b/src/Generators/MigrationGenerator.php @@ -195,7 +195,7 @@ protected function buildPivotTableDefinition(array $segments) $definition = ''; foreach ($segments as $segment) { - $column = Str::lower($segment); + $column = Str::before(Str::lower($segment), ':'); $references = 'id'; $on = Str::plural($column); $foreign = Str::singular($column) . '_' . $references; @@ -276,10 +276,22 @@ protected function getPivotClassName(array $segments) protected function getPivotTableName(array $segments) { + $isCustom = collect($segments) + ->filter(function ($segment) { + return Str::contains($segment, ':'); + })->first(); + + if ($isCustom) { + $table = Str::after($isCustom, ':'); + + return $table; + } + $segments = array_map(function ($name) { return Str::snake($name); }, $segments); sort($segments); + return strtolower(implode('_', $segments)); } diff --git a/src/Generators/ModelGenerator.php b/src/Generators/ModelGenerator.php index eb26eff5..9983b7d0 100644 --- a/src/Generators/ModelGenerator.php +++ b/src/Generators/ModelGenerator.php @@ -160,21 +160,23 @@ private function buildRelationships(Model $model) } } - $class = Str::studly($class ?? $method_name); + $relationshipClass = Str::studly($class ?? $method_name); if ($type === 'morphTo') { $relationship = sprintf('$this->%s()', $type); } elseif ($type === 'morphMany' || $type === 'morphOne') { $relation = Str::lower(Str::singular($column_name)) . 'able'; - $relationship = sprintf('$this->%s(%s::class, \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class, $relation); + $relationship = sprintf('$this->%s(%s::class, \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass, $relation); } elseif (!is_null($key)) { - $relationship = sprintf('$this->%s(%s::class, \'%s\', \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class, $column_name, $key); + $relationship = sprintf('$this->%s(%s::class, \'%s\', \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass, $column_name, $key); + } elseif (!is_null($class) && $type === 'belongsToMany') { + $relationship = sprintf('$this->%s(%s::class, \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass, $method_name); } else { - $relationship = sprintf('$this->%s(%s::class)', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class); + $relationship = sprintf('$this->%s(%s::class)', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass); } if ($type === 'morphTo') { - $method_name = Str::lower($class); + $method_name = Str::lower($relationshipClass); } elseif (in_array($type, ['hasMany', 'belongsToMany', 'morphMany'])) { $method_name = Str::plural($column_name); } diff --git a/tests/Feature/Generator/MigrationGeneratorTest.php b/tests/Feature/Generator/MigrationGeneratorTest.php index 3f515d3f..27bfc128 100644 --- a/tests/Feature/Generator/MigrationGeneratorTest.php +++ b/tests/Feature/Generator/MigrationGeneratorTest.php @@ -390,6 +390,64 @@ public function output_does_not_duplicate_pivot_table_migration_laravel6() $this->assertEquals(['created' => [$company_migration, $people_migration, $pivot_migration]], $this->subject->output($tree)); } + /** + * @test + */ + public function output_also_creates_pivot_table_migration_with_custom_name() + { + $this->files->expects('stub') + ->with('migration.stub') + ->andReturn(file_get_contents('stubs/migration.stub')); + + $now = Carbon::now(); + Carbon::setTestNow($now); + + $model_migration = str_replace('timestamp', $now->format('Y_m_d_His'), 'database/migrations/timestamp_create_users_table.php'); + $pivot_migration = str_replace('timestamp', $now->format('Y_m_d_His'), 'database/migrations/timestamp_create_test_table.php'); + + $this->files->expects('put') + ->with($model_migration, $this->fixture('migrations/custom-pivot-column-user.php')); + $this->files->expects('put') + ->with($pivot_migration, $this->fixture('migrations/custom-pivot-column-test.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-column.bp')); + $tree = $this->blueprint->analyze($tokens); + + $this->assertEquals(['created' => [$model_migration, $pivot_migration]], $this->subject->output($tree)); + } + + /** + * @test + */ + public function output_also_creates_pivot_table_migration_with_custom_name_laravel6() + { + $app = \Mockery::mock(); + $app->shouldReceive('version') + ->withNoArgs() + ->andReturn('6.0.0'); + App::swap($app); + + $this->files->expects('stub') + ->with('migration.stub') + ->andReturn(file_get_contents('stubs/migration.stub')); + + $now = Carbon::now(); + Carbon::setTestNow($now); + + $model_migration = str_replace('timestamp', $now->format('Y_m_d_His'), 'database/migrations/timestamp_create_users_table.php'); + $pivot_migration = str_replace('timestamp', $now->format('Y_m_d_His'), 'database/migrations/timestamp_create_test_table.php'); + + $this->files->expects('put') + ->with($model_migration, $this->fixture('migrations/custom-pivot-column-user-laravel6.php')); + $this->files->expects('put') + ->with($pivot_migration, $this->fixture('migrations/custom-pivot-column-test-laravel6.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-column.bp')); + $tree = $this->blueprint->analyze($tokens); + + $this->assertEquals(['created' => [$model_migration, $pivot_migration]], $this->subject->output($tree)); + } + /** * @test */ diff --git a/tests/Feature/Generator/ModelGeneratorTest.php b/tests/Feature/Generator/ModelGeneratorTest.php index 415844bb..fd62401f 100644 --- a/tests/Feature/Generator/ModelGeneratorTest.php +++ b/tests/Feature/Generator/ModelGeneratorTest.php @@ -406,6 +406,39 @@ public function output_generates_models_with_custom_namespace_correctly() $this->assertEquals(['created' => [$path]], $this->subject->output($tree)); } + /** + * @test + */ + public function output_generates_models_with_custom_pivot_columns() + { + $this->files->expects('stub') + ->with('model/class.stub') + ->andReturn(file_get_contents('stubs/model/class.stub')); + $this->files->expects('stub') + ->with('model/fillable.stub') + ->andReturn(file_get_contents('stubs/model/fillable.stub')); + $this->files->expects('stub') + ->with('model/casts.stub') + ->andReturn(file_get_contents('stubs/model/casts.stub')); + $this->files->expects('stub') + ->with('model/method.stub') + ->andReturn(file_get_contents('stubs/model/method.stub')); + $this->files->expects('stub') + ->with('model/hidden.stub') + ->andReturn(file_get_contents('stubs/model/hidden.stub')); + + $this->files->expects('exists') + ->with('app') + ->andReturnTrue(); + $this->files->expects('put') + ->with('app/User.php', $this->fixture('models/custom-pivot-column.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-column.bp')); + $tree = $this->blueprint->analyze($tokens); + + $this->assertEquals(['created' => ['app/User.php']], $this->subject->output($tree)); + } + public function modelTreeDataProvider() { return [ diff --git a/tests/fixtures/definitions/custom-pivot-column.bp b/tests/fixtures/definitions/custom-pivot-column.bp new file mode 100644 index 00000000..b470bd6b --- /dev/null +++ b/tests/fixtures/definitions/custom-pivot-column.bp @@ -0,0 +1,6 @@ +models: + User: + name: string + remember_token: remembertoken + relationships: + belongsToMany: Account:test diff --git a/tests/fixtures/migrations/custom-pivot-column-test-laravel6.php b/tests/fixtures/migrations/custom-pivot-column-test-laravel6.php new file mode 100644 index 00000000..b2b8dda5 --- /dev/null +++ b/tests/fixtures/migrations/custom-pivot-column-test-laravel6.php @@ -0,0 +1,31 @@ +unsignedBigInteger('account_id'); + $table->unsignedBigInteger('user_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('test'); + } +} diff --git a/tests/fixtures/migrations/custom-pivot-column-test.php b/tests/fixtures/migrations/custom-pivot-column-test.php new file mode 100644 index 00000000..a5293337 --- /dev/null +++ b/tests/fixtures/migrations/custom-pivot-column-test.php @@ -0,0 +1,31 @@ +foreignId('account_id'); + $table->foreignId('user_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('test'); + } +} diff --git a/tests/fixtures/migrations/custom-pivot-column-user-laravel6.php b/tests/fixtures/migrations/custom-pivot-column-user-laravel6.php new file mode 100644 index 00000000..badfc789 --- /dev/null +++ b/tests/fixtures/migrations/custom-pivot-column-user-laravel6.php @@ -0,0 +1,33 @@ +bigIncrements('id'); + $table->string('name'); + $table->rememberToken(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('users'); + } +} diff --git a/tests/fixtures/migrations/custom-pivot-column-user.php b/tests/fixtures/migrations/custom-pivot-column-user.php new file mode 100644 index 00000000..40ae3ec7 --- /dev/null +++ b/tests/fixtures/migrations/custom-pivot-column-user.php @@ -0,0 +1,33 @@ +id(); + $table->string('name'); + $table->rememberToken(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('users'); + } +} diff --git a/tests/fixtures/models/custom-pivot-column.php b/tests/fixtures/models/custom-pivot-column.php new file mode 100644 index 00000000..81f6486a --- /dev/null +++ b/tests/fixtures/models/custom-pivot-column.php @@ -0,0 +1,41 @@ + 'integer', + ]; + + + public function tests() + { + return $this->belongsToMany(\App\Account::class, 'test'); + } +} From ea54ef0b48f1166d74771c941f57b2cd0ff1ca45 Mon Sep 17 00:00:00 2001 From: Jason McCreary Date: Sat, 23 May 2020 09:03:33 -0400 Subject: [PATCH 2/2] Preserve relationship name + clarify change --- src/Generators/ModelGenerator.php | 13 +++++++------ tests/Feature/Generator/MigrationGeneratorTest.php | 12 ++++++------ tests/Feature/Generator/ModelGeneratorTest.php | 4 ++-- ...m-pivot-column.bp => custom-pivot-table-name.bp} | 0 ...hp => custom-pivot-table-name-test-laravel6.php} | 0 ...mn-test.php => custom-pivot-table-name-test.php} | 0 ...hp => custom-pivot-table-name-user-laravel6.php} | 0 ...mn-user.php => custom-pivot-table-name-user.php} | 0 ...pivot-column.php => custom-pivot-table-name.php} | 2 +- 9 files changed, 16 insertions(+), 15 deletions(-) rename tests/fixtures/definitions/{custom-pivot-column.bp => custom-pivot-table-name.bp} (100%) rename tests/fixtures/migrations/{custom-pivot-column-test-laravel6.php => custom-pivot-table-name-test-laravel6.php} (100%) rename tests/fixtures/migrations/{custom-pivot-column-test.php => custom-pivot-table-name-test.php} (100%) rename tests/fixtures/migrations/{custom-pivot-column-user-laravel6.php => custom-pivot-table-name-user-laravel6.php} (100%) rename tests/fixtures/migrations/{custom-pivot-column-user.php => custom-pivot-table-name-user.php} (100%) rename tests/fixtures/models/{custom-pivot-column.php => custom-pivot-table-name.php} (95%) diff --git a/src/Generators/ModelGenerator.php b/src/Generators/ModelGenerator.php index 9983b7d0..dad6bff1 100644 --- a/src/Generators/ModelGenerator.php +++ b/src/Generators/ModelGenerator.php @@ -160,23 +160,24 @@ private function buildRelationships(Model $model) } } - $relationshipClass = Str::studly($class ?? $method_name); + $class_name = Str::studly($class ?? $method_name); if ($type === 'morphTo') { $relationship = sprintf('$this->%s()', $type); } elseif ($type === 'morphMany' || $type === 'morphOne') { $relation = Str::lower(Str::singular($column_name)) . 'able'; - $relationship = sprintf('$this->%s(%s::class, \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass, $relation); + $relationship = sprintf('$this->%s(%s::class, \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class_name, $relation); } elseif (!is_null($key)) { - $relationship = sprintf('$this->%s(%s::class, \'%s\', \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass, $column_name, $key); + $relationship = sprintf('$this->%s(%s::class, \'%s\', \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class_name, $column_name, $key); } elseif (!is_null($class) && $type === 'belongsToMany') { - $relationship = sprintf('$this->%s(%s::class, \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass, $method_name); + $relationship = sprintf('$this->%s(%s::class, \'%s\')', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class_name, $column_name); + $column_name = $class; } else { - $relationship = sprintf('$this->%s(%s::class)', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $relationshipClass); + $relationship = sprintf('$this->%s(%s::class)', $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class_name); } if ($type === 'morphTo') { - $method_name = Str::lower($relationshipClass); + $method_name = Str::lower($class_name); } elseif (in_array($type, ['hasMany', 'belongsToMany', 'morphMany'])) { $method_name = Str::plural($column_name); } diff --git a/tests/Feature/Generator/MigrationGeneratorTest.php b/tests/Feature/Generator/MigrationGeneratorTest.php index 27bfc128..0f3ce6a6 100644 --- a/tests/Feature/Generator/MigrationGeneratorTest.php +++ b/tests/Feature/Generator/MigrationGeneratorTest.php @@ -406,11 +406,11 @@ public function output_also_creates_pivot_table_migration_with_custom_name() $pivot_migration = str_replace('timestamp', $now->format('Y_m_d_His'), 'database/migrations/timestamp_create_test_table.php'); $this->files->expects('put') - ->with($model_migration, $this->fixture('migrations/custom-pivot-column-user.php')); + ->with($model_migration, $this->fixture('migrations/custom-pivot-table-name-user.php')); $this->files->expects('put') - ->with($pivot_migration, $this->fixture('migrations/custom-pivot-column-test.php')); + ->with($pivot_migration, $this->fixture('migrations/custom-pivot-table-name-test.php')); - $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-column.bp')); + $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-table-name.bp')); $tree = $this->blueprint->analyze($tokens); $this->assertEquals(['created' => [$model_migration, $pivot_migration]], $this->subject->output($tree)); @@ -438,11 +438,11 @@ public function output_also_creates_pivot_table_migration_with_custom_name_larav $pivot_migration = str_replace('timestamp', $now->format('Y_m_d_His'), 'database/migrations/timestamp_create_test_table.php'); $this->files->expects('put') - ->with($model_migration, $this->fixture('migrations/custom-pivot-column-user-laravel6.php')); + ->with($model_migration, $this->fixture('migrations/custom-pivot-table-name-user-laravel6.php')); $this->files->expects('put') - ->with($pivot_migration, $this->fixture('migrations/custom-pivot-column-test-laravel6.php')); + ->with($pivot_migration, $this->fixture('migrations/custom-pivot-table-name-test-laravel6.php')); - $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-column.bp')); + $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-table-name.bp')); $tree = $this->blueprint->analyze($tokens); $this->assertEquals(['created' => [$model_migration, $pivot_migration]], $this->subject->output($tree)); diff --git a/tests/Feature/Generator/ModelGeneratorTest.php b/tests/Feature/Generator/ModelGeneratorTest.php index fd62401f..65dba764 100644 --- a/tests/Feature/Generator/ModelGeneratorTest.php +++ b/tests/Feature/Generator/ModelGeneratorTest.php @@ -431,9 +431,9 @@ public function output_generates_models_with_custom_pivot_columns() ->with('app') ->andReturnTrue(); $this->files->expects('put') - ->with('app/User.php', $this->fixture('models/custom-pivot-column.php')); + ->with('app/User.php', $this->fixture('models/custom-pivot-table-name.php')); - $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-column.bp')); + $tokens = $this->blueprint->parse($this->fixture('definitions/custom-pivot-table-name.bp')); $tree = $this->blueprint->analyze($tokens); $this->assertEquals(['created' => ['app/User.php']], $this->subject->output($tree)); diff --git a/tests/fixtures/definitions/custom-pivot-column.bp b/tests/fixtures/definitions/custom-pivot-table-name.bp similarity index 100% rename from tests/fixtures/definitions/custom-pivot-column.bp rename to tests/fixtures/definitions/custom-pivot-table-name.bp diff --git a/tests/fixtures/migrations/custom-pivot-column-test-laravel6.php b/tests/fixtures/migrations/custom-pivot-table-name-test-laravel6.php similarity index 100% rename from tests/fixtures/migrations/custom-pivot-column-test-laravel6.php rename to tests/fixtures/migrations/custom-pivot-table-name-test-laravel6.php diff --git a/tests/fixtures/migrations/custom-pivot-column-test.php b/tests/fixtures/migrations/custom-pivot-table-name-test.php similarity index 100% rename from tests/fixtures/migrations/custom-pivot-column-test.php rename to tests/fixtures/migrations/custom-pivot-table-name-test.php diff --git a/tests/fixtures/migrations/custom-pivot-column-user-laravel6.php b/tests/fixtures/migrations/custom-pivot-table-name-user-laravel6.php similarity index 100% rename from tests/fixtures/migrations/custom-pivot-column-user-laravel6.php rename to tests/fixtures/migrations/custom-pivot-table-name-user-laravel6.php diff --git a/tests/fixtures/migrations/custom-pivot-column-user.php b/tests/fixtures/migrations/custom-pivot-table-name-user.php similarity index 100% rename from tests/fixtures/migrations/custom-pivot-column-user.php rename to tests/fixtures/migrations/custom-pivot-table-name-user.php diff --git a/tests/fixtures/models/custom-pivot-column.php b/tests/fixtures/models/custom-pivot-table-name.php similarity index 95% rename from tests/fixtures/models/custom-pivot-column.php rename to tests/fixtures/models/custom-pivot-table-name.php index 81f6486a..43a9a9e7 100644 --- a/tests/fixtures/models/custom-pivot-column.php +++ b/tests/fixtures/models/custom-pivot-table-name.php @@ -34,7 +34,7 @@ class User extends Model ]; - public function tests() + public function accounts() { return $this->belongsToMany(\App\Account::class, 'test'); }