Skip to content

Commit 660d64d

Browse files
committed
Default value is now escaped properly in Laravel v12.20.0 laravel/framework#56158
1 parent a2f0c45 commit 660d64d

File tree

3 files changed

+184
-1
lines changed

3 files changed

+184
-1
lines changed

src/Database/Models/DatabaseColumn.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace KitLoong\MigrationsGenerator\Database\Models;
44

5+
use Illuminate\Support\Facades\App;
56
use KitLoong\MigrationsGenerator\Enum\Migrations\ColumnName;
67
use KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType;
78
use KitLoong\MigrationsGenerator\Schema\Models\Column;
@@ -293,7 +294,11 @@ protected function escapeDefault(?string $default): ?string
293294
return null;
294295
}
295296

296-
$default = str_replace("'", "''", $default);
297+
// For Laravel versions lower than 12.20.0, escape single quotes
298+
if (version_compare(App::version(), '12.20.0', '<')) {
299+
$default = str_replace("'", "''", $default);
300+
}
301+
297302
return addcslashes($default, '\\');
298303
}
299304

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<?php
2+
3+
namespace KitLoong\MigrationsGenerator\Tests\Unit\Database\Models;
4+
5+
use Illuminate\Support\Facades\App;
6+
use KitLoong\MigrationsGenerator\Tests\TestCase;
7+
use PHPUnit\Framework\Attributes\DataProvider;
8+
9+
class DatabaseColumnTest extends TestCase
10+
{
11+
#[DataProvider('escapeDefaultVersionProvider')]
12+
public function testEscapeDefaultBasedOnLaravelVersion(
13+
string $laravelVersion,
14+
?string $input,
15+
?string $expected,
16+
): void {
17+
// Mock Laravel version
18+
App::shouldReceive('version')
19+
->andReturn($laravelVersion);
20+
21+
$column = new TestDatabaseColumn('test_table', [
22+
'name' => 'test_column',
23+
'type_name' => 'varchar',
24+
'type' => 'varchar(255)',
25+
'collation' => null,
26+
'nullable' => true,
27+
'default' => null,
28+
'auto_increment' => false,
29+
'comment' => null,
30+
'generation' => null,
31+
]);
32+
33+
$result = $column->testEscapeDefault($input);
34+
$this->assertSame($expected, $result);
35+
}
36+
37+
public function testEscapeDefaultWithComplexStrings(): void
38+
{
39+
App::shouldReceive('version')->andReturn('11.0.0'); // Old version
40+
41+
$column = new TestDatabaseColumn('test_table', [
42+
'name' => 'test_column',
43+
'type_name' => 'varchar',
44+
'type' => 'varchar(255)',
45+
'collation' => null,
46+
'nullable' => true,
47+
'default' => null,
48+
'auto_increment' => false,
49+
'comment' => null,
50+
'generation' => null,
51+
]);
52+
53+
// Test complex string with multiple characters to escape
54+
$input = "string !@#$%^^&*()_+-=[]{};:,./<>?~`| \\ \\' \\\\\' \" \\\" \\\\\"";
55+
$result = $column->testEscapeDefault($input);
56+
57+
// Should escape both single quotes and backslashes for old Laravel versions
58+
$expected = "string !@#$%^^&*()_+-=[]{};:,./<>?~`| \\\\ \\\\'' \\\\\\\\\\\\'' \" \\\\\" \\\\\\\\\"";
59+
$this->assertSame($expected, $result);
60+
}
61+
62+
public function testEscapeDefaultWithNewLaravelVersionComplexString(): void
63+
{
64+
App::shouldReceive('version')->andReturn('12.20.0'); // New version
65+
66+
$column = new TestDatabaseColumn('test_table', [
67+
'name' => 'test_column',
68+
'type_name' => 'varchar',
69+
'type' => 'varchar(255)',
70+
'collation' => null,
71+
'nullable' => true,
72+
'default' => null,
73+
'auto_increment' => false,
74+
'comment' => null,
75+
'generation' => null,
76+
]);
77+
78+
// Test complex string - should only escape backslashes, not quotes
79+
$input = "string !@#$%^^&*()_+-=[]{};:,./<>?~`| \\ \\' \\\\\' \" \\\" \\\\\"";
80+
$result = $column->testEscapeDefault($input);
81+
82+
// Should only escape backslashes for new Laravel versions
83+
$expected = "string !@#$%^^&*()_+-=[]{};:,./<>?~`| \\\\ \\\\' \\\\\\\\\\\\' \" \\\\\" \\\\\\\\\"";
84+
$this->assertSame($expected, $result);
85+
}
86+
87+
/**
88+
* @return array<string, array{string, string|null, string|null}>
89+
*/
90+
public static function escapeDefaultVersionProvider(): array
91+
{
92+
return [
93+
// Laravel < 12.20.0 cases - should escape single quotes
94+
'Laravel 11.x.x with single quotes' => [
95+
'11.5.0',
96+
"test'value",
97+
"test''value",
98+
],
99+
'Laravel 12.19.x with single quotes' => [
100+
'12.19.9',
101+
"value with 'quotes' inside",
102+
"value with ''quotes'' inside",
103+
],
104+
'Laravel 12.19.x with backslashes' => [
105+
'12.19.9',
106+
'path\\to\\file',
107+
'path\\\\to\\\\file',
108+
],
109+
'Laravel 12.19.x with both quotes and backslashes' => [
110+
'12.19.9',
111+
"path\\to'file'",
112+
"path\\\\to''file''",
113+
],
114+
'Laravel 12.19.x with null input' => [
115+
'12.19.9',
116+
null,
117+
null,
118+
],
119+
120+
// Laravel >= 12.20.0 cases - should NOT escape single quotes
121+
'Laravel 12.20.0 with single quotes' => [
122+
'12.20.0',
123+
"test'value",
124+
"test'value",
125+
],
126+
'Laravel 12.21.x with single quotes' => [
127+
'12.21.5',
128+
"value with 'quotes' inside",
129+
"value with 'quotes' inside",
130+
],
131+
'Laravel 13.x.x with single quotes' => [
132+
'13.0.0',
133+
"test'value",
134+
"test'value",
135+
],
136+
'Laravel 12.20.0 with backslashes' => [
137+
'12.20.0',
138+
'path\\to\\file',
139+
'path\\\\to\\\\file',
140+
],
141+
'Laravel 12.20.0 with both quotes and backslashes' => [
142+
'12.20.0',
143+
"path\\to'file'",
144+
"path\\\\to'file'",
145+
],
146+
'Laravel 12.20.0 with null input' => [
147+
'12.20.0',
148+
null,
149+
null,
150+
],
151+
];
152+
}
153+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace KitLoong\MigrationsGenerator\Tests\Unit\Database\Models;
4+
5+
use KitLoong\MigrationsGenerator\Database\Models\DatabaseColumn;
6+
use KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType;
7+
8+
/**
9+
* Test implementation of DatabaseColumn for testing purposes
10+
*/
11+
class TestDatabaseColumn extends DatabaseColumn
12+
{
13+
/**
14+
* Expose the protected escapeDefault method for testing
15+
*/
16+
public function testEscapeDefault(?string $default): ?string
17+
{
18+
return $this->escapeDefault($default);
19+
}
20+
21+
protected function getColumnType(string $type): ColumnType
22+
{
23+
return ColumnType::STRING;
24+
}
25+
}

0 commit comments

Comments
 (0)