Skip to content

Commit 115c608

Browse files
authored
Merge pull request #594 from wayofdev/feat/updates
2 parents 58375c7 + 8b69fe9 commit 115c608

File tree

12 files changed

+269
-157
lines changed

12 files changed

+269
-157
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"cycle/schema-migrations-generator": "^2.2",
2626
"cycle/schema-renderer": "^1.2",
2727
"illuminate/console": "^10.45",
28-
"cycle/schema-builder": "^2.8.0",
28+
"cycle/schema-builder": "^2.8",
2929
"illuminate/contracts": "^10.45",
3030
"illuminate/support": "^10.45",
3131
"laminas/laminas-hydrator": "^4.15",

composer.lock

Lines changed: 145 additions & 144 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/cycle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@
218218
Schema\Generator\RenderModifiers::class,
219219
// Add @Table column declarations
220220
Annotated\MergeIndexes::class,
221+
// Add foreign keys
222+
Schema\Generator\ForeignKeys::class,
221223
],
222224
GeneratorLoader::GROUP_POSTPROCESS => [
223225
// Typecast non string columns

src/Bridge/Laravel/Console/Commands/Migrations/AbstractCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ protected function verifyEnvironment(?string $confirmationQuestion = null): bool
4444
return true;
4545
}
4646

47-
$this->line($confirmationQuestion, 'fg=red');
47+
$this->error($confirmationQuestion);
4848

4949
if (! $this->askConfirmation()) {
5050
$this->comment('Cancelling operation...');

src/Bridge/Laravel/Console/Commands/ORM/MigrateCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public function handle(
4848

4949
foreach ($this->migrator->getMigrations() as $migration) {
5050
if ($migration->getState()->getStatus() !== State::STATUS_EXECUTED) {
51-
if ($this->isInteractive() && $this->output->confirm('Outstanding migrations found. Do you want to run `cycle:migrate` now?')) {
51+
if ($this->isForced() || ($this->isInteractive() && $this->output->confirm('Outstanding migrations found. Do you want to run `cycle:migrate` now?'))) {
5252
$this->call(DatabaseMigrateCommand::class, ['--force' => true]);
5353
} else {
5454
$this->warn('Outstanding migrations found, run `cycle:migrate` first.');

src/Bridge/Laravel/Providers/Registrators/RegisterORM.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Cycle\ORM\ORM;
1515
use Cycle\ORM\ORMInterface;
1616
use Cycle\ORM\SchemaInterface;
17+
use Cycle\ORM\Transaction\CommandGeneratorInterface;
1718
use Illuminate\Contracts\Foundation\Application;
1819
use WayOfDev\Cycle\Bridge\Laravel\Factories\SpiralFactory;
1920
use WayOfDev\Cycle\Schema\Config\SchemaConfig;
@@ -39,13 +40,16 @@ public function __invoke(Application $app): void
3940
);
4041
});
4142

42-
$app->singleton(ORMInterface::class, function (Application $app): ORMInterface {
43-
$commandGenerator = null;
44-
$loadEntityBehavior = config('cycle.entityBehavior.register', true);
43+
if ($this->shouldLoadEntityBehavior() === true) {
44+
$app->bind(CommandGeneratorInterface::class, function (Application $app): CommandGeneratorInterface {
45+
return new EventDrivenCommandGenerator($app->get(SchemaInterface::class), $app);
46+
});
47+
}
4548

46-
if (true === $loadEntityBehavior) {
47-
$commandGenerator = new EventDrivenCommandGenerator($app->get(SchemaInterface::class), $app);
48-
}
49+
$app->singleton(ORMInterface::class, function (Application $app): ORMInterface {
50+
$commandGenerator = $this->shouldLoadEntityBehavior()
51+
? $app->get(CommandGeneratorInterface::class)
52+
: null;
4953

5054
return new ORM(
5155
factory: $app->get(FactoryInterface::class),
@@ -60,4 +64,9 @@ public function __invoke(Application $app): void
6064
);
6165
});
6266
}
67+
68+
private function shouldLoadEntityBehavior(): bool
69+
{
70+
return config('cycle.entityBehavior.register', true);
71+
}
6372
}

tests/app/Entities/User.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class User
3030
public ?User $friend = null;
3131

3232
#[HasMany(target: User::class, outerKey: 'userId', nullable: true)]
33-
public iterable|null $friends = [];
33+
public ?iterable $friends = [];
3434

3535
#[HasMany(target: User::class, outerKey: 'userId', nullable: true, collection: 'array')]
3636
public ?array $friendsAsArray = [];

tests/src/Bridge/Laravel/Console/Commands/Migrations/MigrateCommandTest.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,33 @@ class MigrateCommandTest extends TestCase
1313
/**
1414
* @test
1515
*/
16-
public function it_runs_handle(): void
16+
public function it_migrates_in_safe_environment(): void
1717
{
1818
/** @var Database $database */
1919
$database = $this->app->make(DatabaseInterface::class);
2020

2121
$this::assertSame([], $database->getTables());
2222

23+
$this->artisanCall('cycle:migrate:init');
24+
$this->artisanCall('cycle:orm:migrate');
25+
26+
// @phpstan-ignore-next-line
27+
$this::assertCount(1, $database->getTables());
28+
}
29+
30+
/**
31+
* @test
32+
*/
33+
public function it_migrates_in_production_with_force_option(): void
34+
{
35+
// Set the application environment to production
36+
config()->set('cycle.migrations.safe', false);
37+
38+
/** @var Database $database */
39+
$database = $this->app->make(DatabaseInterface::class);
40+
41+
$this::assertSame([], $database->getTables());
42+
2343
$this->artisanCall('cycle:migrate:init');
2444
$this->artisanCall('cycle:orm:migrate', ['--force' => true]);
2545

@@ -29,4 +49,22 @@ public function it_runs_handle(): void
2949
$this->artisanCall('cycle:migrate', ['--force' => true]);
3050
$this::assertCount(4, $database->getTables());
3151
}
52+
53+
/**
54+
* @test
55+
*/
56+
public function it_warns_about_unsafe_migrations(): void
57+
{
58+
// Set the application environment to production
59+
config()->set('cycle.migrations.safe', false);
60+
61+
$this->artisanCall('cycle:migrate:init');
62+
63+
// Simulate running the command and answering 'no' to the confirmation question
64+
$this->artisan('cycle:migrate')
65+
->expectsOutput('Confirmation is required to run migrations!')
66+
->expectsQuestion('Would you like to continue?', false)
67+
->expectsOutput('Cancelling operation...')
68+
->assertFailed();
69+
}
3270
}

tests/src/Bridge/Laravel/Console/Commands/ORM/MigrateCommandTest.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
namespace WayOfDev\Tests\Bridge\Laravel\Console\Commands\ORM;
66

7+
use Cycle\ORM\SchemaInterface;
78
use Illuminate\Support\Facades\File;
9+
use Psr\Container\ContainerExceptionInterface;
10+
use Psr\Container\NotFoundExceptionInterface;
11+
use WayOfDev\Cycle\Contracts\CacheManager;
812
use WayOfDev\Tests\TestCase;
913

1014
use function file_put_contents;
@@ -36,7 +40,10 @@ protected function setUp(): void
3640
public function it_runs_migrate(): void
3741
{
3842
$this->assertConsoleCommandOutputContainsStrings('cycle:orm:migrate', ['-n' => true], self::USER_MIGRATION);
39-
$this->assertConsoleCommandOutputContainsStrings('cycle:orm:migrate', ['-n' => true], 'Outstanding migrations found');
43+
44+
$this->assertConsoleCommandOutputContainsStrings('cycle:orm:migrate', ['-n' => true], [
45+
'Outstanding migrations found',
46+
]);
4047
}
4148

4249
/**
@@ -89,4 +96,25 @@ class Tag
8996

9097
File::delete($entity);
9198
}
99+
100+
/**
101+
* @test
102+
*
103+
* @throws ContainerExceptionInterface
104+
* @throws NotFoundExceptionInterface
105+
*/
106+
public function it_passes_schema_defaults_to_compiler(): void
107+
{
108+
config()->set('cycle.schema.defaults', [
109+
SchemaInterface::TYPECAST_HANDLER => ['foo'],
110+
]);
111+
112+
$this->artisanCall('cycle:orm:migrate', ['-n' => true]);
113+
$this->artisanCall('cycle:migrate', ['--force' => true]);
114+
$this->artisanCall('cycle:orm:migrate', ['-n' => true]);
115+
116+
$cacheManager = $this->app->get(CacheManager::class);
117+
118+
$this::assertSame(['foo'], $cacheManager->get()['role'][SchemaInterface::TYPECAST_HANDLER]);
119+
}
92120
}

tests/src/Bridge/Laravel/Console/Commands/ORM/SyncCommandTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,29 @@ public function it_runs_handle_in_debug_mode(): void
4949

5050
$this::assertSame(1, $u->id);
5151
}
52+
53+
/**
54+
* @test
55+
*/
56+
public function it_fails_in_production_without_force(): void
57+
{
58+
// Set the application environment to production
59+
config()->set('cycle.migrations.safe', false);
60+
61+
$warningOutput = 'This operation is not recommended for production environment.';
62+
$confirmationQuestion = 'Would you like to continue?';
63+
64+
// Simulate running the command and answering 'no' to the confirmation question
65+
$this->artisan('cycle:orm:sync')
66+
->expectsOutput($warningOutput)
67+
->expectsQuestion($confirmationQuestion, false)
68+
->expectsOutput('Cancelling operation...')
69+
->assertFailed();
70+
71+
// To test the affirmative path, simulate answering 'yes'
72+
$this->artisan('cycle:orm:sync')
73+
->expectsOutput($warningOutput)
74+
->expectsQuestion($confirmationQuestion, 'yes')
75+
->assertSuccessful();
76+
}
5277
}

0 commit comments

Comments
 (0)