v7.0.0 release

This commit is contained in:
HeuJung
2026-07-01 10:30:32 +09:00
parent 0e7fa04b03
commit c4ea9a6cd1
3582 changed files with 626189 additions and 160151 deletions
@@ -25,7 +25,7 @@ class DatabaseFulltextEngineTest extends TestCase
protected function setUp(): void
{
parent::setUp();
$this->engine = new DatabaseFulltextEngine();
$this->engine = new DatabaseFulltextEngine;
}
/**
@@ -33,7 +33,7 @@ class DatabaseFulltextEngineTest extends TestCase
*/
public function test_update_is_noop(): void
{
$models = new Collection();
$models = new Collection;
// 예외 없이 정상 실행되어야 함
$this->engine->update($models);
@@ -45,7 +45,7 @@ class DatabaseFulltextEngineTest extends TestCase
*/
public function test_delete_is_noop(): void
{
$models = new Collection();
$models = new Collection;
$this->engine->delete($models);
$this->assertTrue(true);
@@ -162,7 +162,7 @@ class DatabaseFulltextEngineTest extends TestCase
*/
public function test_search_returns_empty_for_non_fulltext_searchable_model(): void
{
$model = new NonFulltextModel();
$model = new NonFulltextModel;
$builder = new Builder($model, '검색어');
$results = $this->engine->search($builder);
@@ -317,6 +317,98 @@ class DatabaseFulltextEngineTest extends TestCase
$this->assertTrue(true);
}
/**
* sanitizeBooleanModeKeyword()가 BOOLEAN MODE 연산자를 제거하고 phrase로 변환하는지 테스트합니다.
*/
public function test_sanitize_boolean_mode_keyword_wraps_tokens_in_phrases(): void
{
$this->assertSame('"셔츠"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('셔츠'));
$this->assertSame('"shirt"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('shirt'));
// 다중 토큰 → 각각 phrase
$this->assertSame('"셔츠" "면"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('셔츠 면'));
}
/**
* sanitizeBooleanModeKeyword()가 각 BOOLEAN MODE 연산자를 제거하는지 테스트합니다.
*/
public function test_sanitize_boolean_mode_keyword_strips_operators(): void
{
// 연산자가 제거되고 남은 토큰만 phrase 로 묶임
$this->assertSame('"상품"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('+상품'));
$this->assertSame('"바지"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('-바지'));
$this->assertSame('"상품"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('상품)'));
$this->assertSame('"셔츠"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('(셔츠'));
$this->assertSame('"키워드"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('~키워드'));
$this->assertSame('"상품"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('상품*'));
$this->assertSame('"셔츠"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('"셔츠'));
$this->assertSame('"user"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('@user'));
// <script> → 연산자/태그 제거 후 'script'
$this->assertSame('"script"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('<script>'));
}
/**
* sanitizeBooleanModeKeyword()가 연산자만 입력 시 빈 문자열을 반환하는지 테스트합니다.
*/
public function test_sanitize_boolean_mode_keyword_returns_empty_for_operators_only(): void
{
$this->assertSame('', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('< >'));
$this->assertSame('', DatabaseFulltextEngine::sanitizeBooleanModeKeyword('+-~*'));
$this->assertSame('', DatabaseFulltextEngine::sanitizeBooleanModeKeyword(' '));
$this->assertSame('', DatabaseFulltextEngine::sanitizeBooleanModeKeyword(''));
}
/**
* sanitizeBooleanModeKeyword()가 제어문자를 제거하는지 테스트합니다.
*/
public function test_sanitize_boolean_mode_keyword_removes_control_chars(): void
{
$this->assertSame('"셔츠"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword("셔츠\x00"));
$this->assertSame('"a" "b"', DatabaseFulltextEngine::sanitizeBooleanModeKeyword("a\tb"));
}
/**
* whereFulltext()가 특수문자 입력 시 정제된 안전한 phrase를 바인딩하는지 테스트합니다.
*/
public function test_where_fulltext_binds_sanitized_keyword(): void
{
$driver = DB::getDriverName();
if (! in_array($driver, ['mysql', 'mariadb'])) {
$this->markTestSkipped('FULLTEXT 미지원 DBMS');
}
$model = $this->createSearchableModel();
$query = $model->newQuery();
DatabaseFulltextEngine::whereFulltext($query, 'name', '<script>');
$sql = $query->toSql();
$this->assertStringContainsString('MATCH(`name`) AGAINST(? IN BOOLEAN MODE)', $sql);
// 원본 특수문자가 아닌 정제된 phrase 가 바인딩
$this->assertContains('"script"', $query->getBindings());
}
/**
* whereFulltext()가 연산자만 입력 시 1=0 조건으로 빈 결과를 생성하는지 테스트합니다.
*/
public function test_where_fulltext_uses_false_condition_for_operators_only(): void
{
$driver = DB::getDriverName();
if (! in_array($driver, ['mysql', 'mariadb'])) {
$this->markTestSkipped('FULLTEXT 미지원 DBMS');
}
$model = $this->createSearchableModel();
$query = $model->newQuery();
DatabaseFulltextEngine::whereFulltext($query, 'name', '< >');
$sql = $query->toSql();
$this->assertStringContainsString('1 = 0', $sql);
$this->assertStringNotContainsString('AGAINST', $sql);
}
/**
* Searchable + FulltextSearchable 모델을 생성합니다.
*