• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tempestphp / tempest-framework / 14326952180

08 Apr 2025 06:46AM UTC coverage: 81.311%. First build
14326952180

Pull #871

github

web-flow
Merge 33e22d9f8 into 2f0b247aa
Pull Request #871: feat(console): add `make:migration` command

62 of 68 new or added lines in 4 files covered. (91.18%)

11486 of 14126 relevant lines covered (81.31%)

105.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.31
/src/Tempest/Database/src/Commands/MakeMigrationCommand.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Tempest\Database\Commands;
6

7
use InvalidArgumentException;
8
use Tempest\Console\ConsoleArgument;
9
use Tempest\Console\ConsoleCommand;
10
use Tempest\Core\PublishesFiles;
11
use Tempest\Database\Enums\MigrationType;
12
use Tempest\Database\Stubs\MigrationStub;
13
use Tempest\Generation\DataObjects\StubFile;
14
use Tempest\Generation\Exceptions\FileGenerationAbortedException;
15
use Tempest\Generation\Exceptions\FileGenerationFailedException;
16
use Tempest\Validation\Rules\EndsWith;
17
use Tempest\Validation\Rules\NotEmpty;
18

19
use function Tempest\Support\str;
20

21
final class MakeMigrationCommand
22
{
23
    use PublishesFiles;
24

25
    #[ConsoleCommand(
4✔
26
        name: 'make:migration',
27
        description: 'Creates a new migration file',
28
        aliases: ['migration:make', 'migration:create', 'create:migration'],
29
    )]
30
    public function __invoke(
31
        #[ConsoleArgument(
32
            description: 'The file name of the migration',
33
        )]
34
        string $fileName,
35
        #[ConsoleArgument(
36
            name: 'type',
37
            description: 'The type of the migration to create',
38
        )]
39
        MigrationType $migrationType = MigrationType::OBJECT,
40
    ): void {
41
        try {
42
            $stubFile = $this->getStubFileFromMigrationType($migrationType);
4✔
43
            $targetPath = match ($migrationType) {
4✔
44
                MigrationType::RAW => $this->generateRawFile($fileName, $stubFile),
4✔
45
                default => $this->generateClassFile($fileName, $stubFile),
3✔
46
            };
4✔
47

48
            $this->success(sprintf('Migration file successfully created at "%s".', $targetPath));
4✔
NEW
49
        } catch (FileGenerationAbortedException|FileGenerationFailedException|InvalidArgumentException $e) {
×
NEW
50
            $this->error($e->getMessage());
×
51
        }
52
    }
53

54
    /**
55
     * Generates a raw migration file.
56
     * @param string $fileName The name of the file.
57
     * @param StubFile $stubFile The stub file to use.
58
     *
59
     * @return string The path to the generated file.
60
     */
61
    private function generateRawFile(
1✔
62
        string $fileName,
63
        StubFile $stubFile,
64
    ): string {
65
        $now = date('Y-m-d');
1✔
66
        $tableName = str($fileName)->snake()->toString();
1✔
67
        $suggestedPath = str($this->getSuggestedPath('Dummy'))
1✔
68
            ->replace(
1✔
69
                ['Dummy', '.php'],
1✔
70
                [$now . '_' . $tableName, '.sql'],
1✔
71
            )
1✔
72
            ->toString();
1✔
73

74
        $targetPath = $this->promptTargetPath($suggestedPath, rules: [
1✔
75
            new NotEmpty(),
1✔
76
            new EndsWith('.sql'),
1✔
77
        ]);
1✔
78
        $shouldOverride = $this->askForOverride($targetPath);
1✔
79

80
        $this->stubFileGenerator->generateRawFile(
1✔
81
            stubFile: $stubFile,
1✔
82
            targetPath: $targetPath,
1✔
83
            shouldOverride: $shouldOverride,
1✔
84
            replacements: [
1✔
85
                'DummyTableName' => $tableName,
1✔
86
            ],
1✔
87
        );
1✔
88

89
        return $targetPath;
1✔
90
    }
91

92
    /**
93
     * Generates a class migration file.
94
     *
95
     * @param string $fileName The name of the file.
96
     * @param StubFile $stubFile The stub file to use.
97
     *
98
     * @return string The path to the generated file.
99
     */
100
    private function generateClassFile(
3✔
101
        string $fileName,
102
        StubFile $stubFile,
103
    ): string {
104
        $suggestedPath = $this->getSuggestedPath($fileName);
3✔
105
        $targetPath = $this->promptTargetPath($suggestedPath);
3✔
106
        $shouldOverride = $this->askForOverride($targetPath);
3✔
107

108
        $this->stubFileGenerator->generateClassFile(
3✔
109
            stubFile: $stubFile,
3✔
110
            targetPath: $targetPath,
3✔
111
            shouldOverride: $shouldOverride,
3✔
112
            replacements: [
3✔
113
                'dummy-date' => date('Y-m-d'),
3✔
114
                'dummy-table-name' => str($fileName)->snake()->toString(),
3✔
115
            ],
3✔
116
        );
3✔
117

118
        return $targetPath;
3✔
119
    }
120

121
    private function getStubFileFromMigrationType(MigrationType $migrationType): StubFile
4✔
122
    {
123
        try {
124
            return match ($migrationType) {
125
                MigrationType::RAW => StubFile::from(dirname(__DIR__) . '/Stubs/migration.stub.sql'),
4✔
126
                MigrationType::OBJECT => StubFile::from(MigrationStub::class), // @phpstan-ignore match.alwaysTrue (Because this is a guardrail for the future implementations)
3✔
127
                default => throw new InvalidArgumentException(sprintf('The "%s" migration type has no supported stub file.', $migrationType->value)),
4✔
128
            };
NEW
129
        } catch (InvalidArgumentException $invalidArgumentException) {
×
NEW
130
            throw new FileGenerationFailedException(sprintf('Cannot retrieve stub file: %s', $invalidArgumentException->getMessage()));
×
131
        }
132
    }
133
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc