Skip to content

Commit 77b7590

Browse files
committed
fix(sqlite): [UPD] default SQLite path to core/database
1 parent 3e56966 commit 77b7590

7 files changed

Lines changed: 161 additions & 10 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ evo install my-project --extras=sTask@main,sSeo # Install extras after setup (o
122122
- `--db-type`: Database type (`mysql`, `pgsql`, `sqlite`, or `sqlsrv`)
123123
- `--db-host`: Database host (default: `localhost`, not used for SQLite)
124124
- `--db-port`: Database port (defaults: 3306 for MySQL, 5432 for PostgreSQL, 1433 for SQL Server)
125-
- `--db-name`: Database name (for SQLite: path to database file, default: `database.sqlite`)
125+
- `--db-name`: Database name (for SQLite: path to database file, default: `core/database/database.sqlite`)
126126
- `--db-user`: Database user (not used for SQLite)
127127
- `--db-password`: Database password (not used for SQLite). If it contains shell special characters (e.g. `;`, `&`, `!`), quote it: `--db-password='p;ass'`.
128128
- `--admin-username`: Admin username
@@ -148,7 +148,7 @@ evo install demo \
148148
--cli \
149149
--branch=3.5.x \
150150
--db-type=sqlite \
151-
--db-name=database.sqlite \
151+
--db-name=core/database/database.sqlite \
152152
--admin-username=admin \
153153
--admin-email=admin@example.com \
154154
--admin-password=123456 \

internal/engine/install/engine.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ func (e *Engine) Run(ctx context.Context, ch chan<- domain.Event, actions <-chan
510510
ID: "db_sqlite_path",
511511
Kind: domain.QuestionInput,
512512
Prompt: "What is the path to your SQLite database file?",
513-
Default: "database.sqlite",
513+
Default: defaultSQLiteDatabasePath(),
514514
})
515515
if !ok {
516516
return
@@ -1763,6 +1763,10 @@ func defaultPort(dbType string) int {
17631763
}
17641764
}
17651765

1766+
func defaultSQLiteDatabasePath() string {
1767+
return filepath.ToSlash(filepath.Join("core", "database", "database.sqlite"))
1768+
}
1769+
17661770
func dbDriverLabel(dbType string) string {
17671771
switch strings.ToLower(strings.TrimSpace(dbType)) {
17681772
case "mysql":

src/Commands/InstallCommand.php

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,14 +396,15 @@ protected function askDatabaseHost(): string
396396
protected function askDatabaseName(?string $type = null): string
397397
{
398398
if ($type === 'sqlite') {
399+
$defaultPath = $this->defaultSqliteDatabasePath();
399400
$answer = $this->tui->ask(
400401
'What is the path to your SQLite database file?',
401-
'database.sqlite'
402+
$defaultPath
402403
);
403404

404405
$this->tui->replaceLastLogs('<fg=green>✔</> Selected database path: ' . $answer . '.', 2);
405406

406-
return $answer ?: 'database.sqlite';
407+
return $this->normalizeSqliteDatabasePath($answer ?: $defaultPath);
407408
}
408409

409410
$answer = $this->tui->ask(
@@ -3323,7 +3324,8 @@ protected function getDatabaseConfigForOperations(string $projectPath, array $db
33233324
return $dbConfig;
33243325
}
33253326

3326-
$name = (string) ($dbConfig['name'] ?? '');
3327+
$name = $this->normalizeSqliteDatabasePath((string) ($dbConfig['name'] ?? ''));
3328+
$dbConfig['name'] = $name;
33273329
if ($name === '' || $name === ':memory:' || str_starts_with($name, 'file:')) {
33283330
return $dbConfig;
33293331
}
@@ -3338,6 +3340,40 @@ protected function getDatabaseConfigForOperations(string $projectPath, array $db
33383340
return $dbConfig;
33393341
}
33403342

3343+
protected function defaultSqliteDatabasePath(): string
3344+
{
3345+
return 'core/database/database.sqlite';
3346+
}
3347+
3348+
protected function normalizeSqliteDatabasePath(string $path): string
3349+
{
3350+
$path = trim($path);
3351+
if ($path === '') {
3352+
return $this->defaultSqliteDatabasePath();
3353+
}
3354+
3355+
if ($path === ':memory:' || str_starts_with($path, 'file:')) {
3356+
return $path;
3357+
}
3358+
3359+
if (str_starts_with($path, '/') || preg_match('/^[A-Za-z]:[\\\\\\/]/', $path) === 1) {
3360+
return $path;
3361+
}
3362+
3363+
$normalized = str_replace('\\', '/', $path);
3364+
$normalized = preg_replace('#^(?:\./)+#', '', $normalized) ?? $normalized;
3365+
$normalized = ltrim($normalized, '/');
3366+
if ($normalized === '') {
3367+
return $this->defaultSqliteDatabasePath();
3368+
}
3369+
3370+
if (!str_contains($normalized, '/')) {
3371+
return 'core/database/' . $normalized;
3372+
}
3373+
3374+
return $normalized;
3375+
}
3376+
33413377
/**
33423378
* Detect base URL for the installed application.
33433379
*

src/Concerns/ConfiguresDatabase.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ protected function buildDsn(string $type, string $host, ?int $port, ?string $dat
8282
{
8383
if ($type === 'sqlite') {
8484
// SQLite: database is the path to the file
85-
$path = $database ?: ':memory:';
85+
$path = $database ?: $this->defaultSqliteDatabasePath();
86+
if ($path !== ':memory:' && !str_starts_with($path, 'file:') && !$this->isAbsolutePath($path)) {
87+
$path = $this->normalizeRelativeSqliteDatabasePath($path);
88+
}
8689
return "sqlite:{$path}";
8790
}
8891

@@ -153,7 +156,10 @@ protected function createDatabase(array $config, string $collation): bool
153156

154157
if ($type === 'sqlite') {
155158
// SQLite: Create database file
156-
$databasePath = $databaseName ?: 'database.sqlite';
159+
$databasePath = $databaseName ?: $this->defaultSqliteDatabasePath();
160+
if ($databasePath !== ':memory:' && !str_starts_with($databasePath, 'file:') && !$this->isAbsolutePath($databasePath)) {
161+
$databasePath = $this->normalizeRelativeSqliteDatabasePath($databasePath);
162+
}
157163
$directory = dirname($databasePath);
158164

159165
if (!empty($directory) && !is_dir($directory)) {
@@ -254,4 +260,32 @@ protected function createDatabase(array $config, string $collation): bool
254260
return false;
255261
}
256262
}
263+
264+
protected function defaultSqliteDatabasePath(): string
265+
{
266+
return 'core/database/database.sqlite';
267+
}
268+
269+
protected function normalizeRelativeSqliteDatabasePath(string $path): string
270+
{
271+
$normalized = trim(str_replace('\\', '/', $path));
272+
$normalized = preg_replace('#^(?:\./)+#', '', $normalized) ?? $normalized;
273+
$normalized = ltrim($normalized, '/');
274+
if ($normalized === '') {
275+
return $this->defaultSqliteDatabasePath();
276+
}
277+
278+
if (!str_contains($normalized, '/')) {
279+
return 'core/database/' . $normalized;
280+
}
281+
282+
return $normalized;
283+
}
284+
285+
protected function isAbsolutePath(string $path): bool
286+
{
287+
return str_starts_with($path, '/')
288+
|| str_starts_with($path, '\\\\')
289+
|| preg_match('/^[A-Za-z]:[\\\\\\/]/', $path) === 1;
290+
}
257291
}

src/Process/CreatesDatabaseConfig.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,13 @@ public function __invoke(string $projectPath, array $config): bool
8989
protected function generateConfigContent(array $params): string
9090
{
9191
$rawDriver = (string) $params['driver'];
92+
$rawDatabase = (string) $params['database'];
93+
if ($rawDriver === 'sqlite') {
94+
$rawDatabase = $this->normalizeSqliteDatabasePath($rawDatabase);
95+
}
9296
$driver = $this->escapePhpString($rawDriver);
9397
$host = $this->escapePhpString((string) $params['host']);
9498
$port = $this->escapePhpString((string) ($params['port'] ?? ''));
95-
$rawDatabase = (string) $params['database'];
9699
$database = $this->escapePhpString($rawDatabase);
97100
$username = $this->escapePhpString((string) $params['username']);
98101
$password = $this->escapePhpString((string) $params['password']);
@@ -133,6 +136,31 @@ protected function generateConfigContent(array $params): string
133136
PHP;
134137
}
135138

139+
protected function normalizeSqliteDatabasePath(string $path): string
140+
{
141+
$path = trim($path);
142+
if ($path === '') {
143+
return 'core/database/database.sqlite';
144+
}
145+
146+
if ($path === ':memory:' || str_starts_with($path, 'file:') || $this->isAbsolutePath($path)) {
147+
return $path;
148+
}
149+
150+
$normalized = str_replace('\\', '/', $path);
151+
$normalized = preg_replace('#^(?:\./)+#', '', $normalized) ?? $normalized;
152+
$normalized = ltrim($normalized, '/');
153+
if ($normalized === '') {
154+
return 'core/database/database.sqlite';
155+
}
156+
157+
if (!str_contains($normalized, '/')) {
158+
return 'core/database/' . $normalized;
159+
}
160+
161+
return $normalized;
162+
}
163+
136164
protected function isAbsolutePath(string $path): bool
137165
{
138166
if ($path === '') {

tests/Unit/CreatesDatabaseConfigTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,34 @@ public function testGenerateConfigContentForPostgreSQL(): void
7373
$this->assertStringContainsString("'engine' => env('DB_ENGINE', '')", $content);
7474
}
7575

76+
public function testGenerateConfigContentForSqliteUsesCoreDatabaseDefaultPath(): void
77+
{
78+
$reflection = new \ReflectionClass($this->processor);
79+
$method = $reflection->getMethod('generateConfigContent');
80+
$method->setAccessible(true);
81+
82+
$params = [
83+
'driver' => 'sqlite',
84+
'host' => '',
85+
'port' => null,
86+
'database' => 'database.sqlite',
87+
'username' => '',
88+
'password' => '',
89+
'charset' => 'utf8',
90+
'collation' => 'utf8',
91+
'prefix' => 'evo_',
92+
'method' => 'SET CHARACTER SET',
93+
'engine' => '',
94+
];
95+
96+
$content = $method->invoke($this->processor, $params);
97+
98+
$this->assertStringContainsString(
99+
"'database' => env('DB_DATABASE', dirname(__DIR__, 4) . '/core/database/database.sqlite')",
100+
$content
101+
);
102+
}
103+
76104
public function testGetDefaultPortForMySQL(): void
77105
{
78106
$reflection = new \ReflectionClass($this->processor);

tests/Unit/InstallCommandAdminDirectoryTest.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,28 @@ public function testWriteCoreCustomEnvDoesNotWriteMgrDirForManager(): void
9999
$this->removeTempDir($projectPath);
100100
}
101101

102+
public function testWriteCoreCustomEnvWritesSqlitePathInsideCoreDatabase(): void
103+
{
104+
$cmd = $this->makeCommand();
105+
106+
$projectPath = $this->makeTempProjectDir();
107+
@mkdir($projectPath . '/core/custom', 0755, true);
108+
109+
$cmd->writeCoreCustomEnvPublic($projectPath, [
110+
'database' => [
111+
'type' => 'sqlite',
112+
'name' => 'database.sqlite',
113+
'prefix' => 'evo_',
114+
],
115+
]);
116+
117+
$env = (string) file_get_contents($projectPath . '/core/custom/.env');
118+
$expected = 'DB_DATABASE="' . $projectPath . '/core/database/database.sqlite"' . "\n";
119+
$this->assertStringContainsString($expected, $env);
120+
121+
$this->removeTempDir($projectPath);
122+
}
123+
102124
public function testApplyManagerDirectoryRenamesManagerFolder(): void
103125
{
104126
$cmd = $this->makeCommand();
@@ -170,4 +192,3 @@ public function applyManagerDirectoryPublic(string $projectPath, array $options)
170192
$this->applyManagerDirectory($projectPath, $options);
171193
}
172194
}
173-

0 commit comments

Comments
 (0)