chore(payment): NHN KCP와 NICE 결제 플러그인 개발 브랜치 분리
정식 develop에서는 기본 번들 정책에 따라 제거된 결제 플러그인을 별도 개발 브랜치에서 계속 유지보수할 수 있도록 복원한다.
This commit is contained in:
1 parent
49b21e788c
commit
657f546efc
651 files changed
+49118
-20476
No files matched your search
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Extension\Helpers\CoreBackupHelper;
|
||||
use App\Extension\Helpers\FilePermissionHelper;
|
||||
use App\Services\CoreUpdateService;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
@@ -1112,240 +1111,6 @@ MD;
|
||||
$this->assertFalse(File::exists($tempDest.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'OrphanFile.php'));
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// applyUpdate() — 기본(증분) 3-way 적용 + --prune (공개 #64)
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* 증분 모드(applyList 지정): 코어가 변경하지 않은 파일(applyList 미포함)은
|
||||
* 스킵되어 사용자가 수정한 현재 디스크 내용이 보존됩니다.
|
||||
*
|
||||
* 이슈 #64 핵심 회귀 가드 — `.htaccess` 커스텀 블록 소실 방지.
|
||||
*/
|
||||
public function test_apply_update_incremental_preserves_user_modified_unchanged_file(): void
|
||||
{
|
||||
[$source, $fakeBase, $restore] = $this->prepareApplyUpdateEnv(['public']);
|
||||
|
||||
try {
|
||||
// source(theirs): .htaccess 는 코어가 변경하지 않았다고 가정 → applyList 미포함
|
||||
File::ensureDirectoryExists($source.DIRECTORY_SEPARATOR.'public');
|
||||
File::put($source.DIRECTORY_SEPARATOR.'public'.DIRECTORY_SEPARATOR.'.htaccess', "# core default\n");
|
||||
File::put($source.DIRECTORY_SEPARATOR.'public'.DIRECTORY_SEPARATOR.'index.php', "<?php // core v2\n");
|
||||
|
||||
// 활성(mine): 사용자가 .htaccess 에 커스텀 블록을 넣은 상태
|
||||
File::ensureDirectoryExists($fakeBase.DIRECTORY_SEPARATOR.'public');
|
||||
File::put($fakeBase.DIRECTORY_SEPARATOR.'public'.DIRECTORY_SEPARATOR.'.htaccess', "# core default\n# USER CUSTOM CACHE BLOCK\n");
|
||||
File::put($fakeBase.DIRECTORY_SEPARATOR.'public'.DIRECTORY_SEPARATOR.'index.php', "<?php // core v1\n");
|
||||
|
||||
// 코어가 실제로 바꾼 파일은 index.php 뿐 (.htaccess 는 목록에 없음)
|
||||
$applyList = ['public/index.php'];
|
||||
|
||||
$this->service->applyUpdate($source, null, prune: false, applyList: $applyList);
|
||||
|
||||
// .htaccess: 사용자 커스텀 블록 보존 (스킵)
|
||||
$this->assertStringContainsString(
|
||||
'USER CUSTOM CACHE BLOCK',
|
||||
File::get($fakeBase.DIRECTORY_SEPARATOR.'public'.DIRECTORY_SEPARATOR.'.htaccess'),
|
||||
'.htaccess 는 applyList 에 없으므로 사용자 수정이 보존되어야 한다',
|
||||
);
|
||||
|
||||
// index.php: 코어 변경분 적용
|
||||
$this->assertStringContainsString(
|
||||
'core v2',
|
||||
File::get($fakeBase.DIRECTORY_SEPARATOR.'public'.DIRECTORY_SEPARATOR.'index.php'),
|
||||
);
|
||||
} finally {
|
||||
$restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 증분 모드: applyList 에 없는 신규 파일이 source 에 있어도 스킵됩니다.
|
||||
* (코어가 실제 추가했다면 applyList 에 담겼을 것 — 목록이 최종 권위)
|
||||
*/
|
||||
public function test_apply_update_incremental_applies_only_listed_files(): void
|
||||
{
|
||||
[$source, $fakeBase, $restore] = $this->prepareApplyUpdateEnv(['app']);
|
||||
|
||||
try {
|
||||
File::ensureDirectoryExists($source.DIRECTORY_SEPARATOR.'app');
|
||||
File::put($source.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Listed.php', '<?php // listed');
|
||||
File::put($source.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Unlisted.php', '<?php // unlisted');
|
||||
|
||||
File::ensureDirectoryExists($fakeBase.DIRECTORY_SEPARATOR.'app');
|
||||
|
||||
$this->service->applyUpdate($source, null, prune: false, applyList: ['app/Listed.php']);
|
||||
|
||||
$this->assertFileExists($fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Listed.php');
|
||||
$this->assertFileDoesNotExist(
|
||||
$fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Unlisted.php',
|
||||
'applyList 에 없는 파일은 복사되지 않아야 한다',
|
||||
);
|
||||
} finally {
|
||||
$restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* end-to-end 회귀 (공개 #64 / 내부 #452): 코어 업데이트가 번들 확장의 변경된
|
||||
* `_bundled` 파일을 실제로 반영합니다.
|
||||
*
|
||||
* computeApplyList(3-way 산출) → applyUpdate(적용) 전 체인을 실제 config 조합
|
||||
* (protected 에 `modules`, targets 에 `modules/_bundled`)으로 검증한다.
|
||||
* protected 필터가 `_bundled` 갱신을 삼키던 결함으로 인해, 코어 배포본에
|
||||
* 새 번들(vendor-bundle.json/composer.json 갱신)이 포함돼도 활성 서버의
|
||||
* `_bundled` 가 갱신되지 않아 이후 `module:update` 무결성 검증이 실패하던
|
||||
* 회귀를 차단한다.
|
||||
*/
|
||||
public function test_incremental_apply_reflects_changed_bundled_extension_file(): void
|
||||
{
|
||||
[$source, $fakeBase, $restore] = $this->prepareApplyUpdateEnv(['modules/_bundled']);
|
||||
|
||||
try {
|
||||
// 실제 config 조합 재현: protected 에 부모 도메인 포함
|
||||
config(['app.update.protected_paths' => ['.env', 'storage', 'vendor', 'modules', 'plugins', 'templates', 'lang-packs']]);
|
||||
|
||||
$rel = 'modules/_bundled/sirsoft-ecommerce/vendor-bundle.json';
|
||||
$relPlatform = str_replace('/', DIRECTORY_SEPARATOR, $rel);
|
||||
|
||||
// base(구버전) = 옛 해시, source(신버전) = 새 해시 (코어가 변경한 번들 파일)
|
||||
File::ensureDirectoryExists(dirname($fakeBase.DIRECTORY_SEPARATOR.$relPlatform));
|
||||
File::put($fakeBase.DIRECTORY_SEPARATOR.$relPlatform, '{"composer_json_sha256":"OLD"}');
|
||||
File::ensureDirectoryExists(dirname($source.DIRECTORY_SEPARATOR.$relPlatform));
|
||||
File::put($source.DIRECTORY_SEPARATOR.$relPlatform, '{"composer_json_sha256":"NEW-differs-in-length"}');
|
||||
|
||||
// 3-way 산출: base != theirs → changed 로 목록 포함되어야 한다
|
||||
$applyResult = CoreBackupHelper::computeApplyList(
|
||||
$fakeBase,
|
||||
$source,
|
||||
config('app.update.targets'),
|
||||
config('app.update.protected_paths'),
|
||||
config('app.update.excludes'),
|
||||
);
|
||||
$this->assertContains($rel, $applyResult['apply'], 'changed 된 _bundled 파일이 apply 목록에 포함되어야 한다');
|
||||
|
||||
// 적용: 활성(base) 파일이 신버전 내용으로 갱신되어야 한다
|
||||
$this->service->applyUpdate($source, null, prune: false, applyList: $applyResult['apply']);
|
||||
|
||||
$this->assertSame(
|
||||
'{"composer_json_sha256":"NEW-differs-in-length"}',
|
||||
File::get($fakeBase.DIRECTORY_SEPARATOR.$relPlatform),
|
||||
'코어 업데이트가 변경된 _bundled 번들 파일을 실제로 반영해야 한다',
|
||||
);
|
||||
} finally {
|
||||
$restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 증분 모드는 orphan(소스에 없는 대상 파일)을 삭제하지 않습니다
|
||||
* (사용자가 추가한 신규 파일 보존).
|
||||
*/
|
||||
public function test_apply_update_incremental_does_not_remove_orphans(): void
|
||||
{
|
||||
[$source, $fakeBase, $restore] = $this->prepareApplyUpdateEnv(['app']);
|
||||
|
||||
try {
|
||||
File::ensureDirectoryExists($source.DIRECTORY_SEPARATOR.'app');
|
||||
File::put($source.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Core.php', '<?php // core');
|
||||
|
||||
File::ensureDirectoryExists($fakeBase.DIRECTORY_SEPARATOR.'app');
|
||||
File::put($fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'UserAdded.php', '<?php // user file');
|
||||
|
||||
$this->service->applyUpdate($source, null, prune: false, applyList: ['app/Core.php']);
|
||||
|
||||
$this->assertFileExists(
|
||||
$fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'UserAdded.php',
|
||||
'증분 모드는 orphan 을 삭제하지 않아야 한다',
|
||||
);
|
||||
} finally {
|
||||
$restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* prune=true: 전체 덮어쓰기 + orphan 삭제 (기존 동작).
|
||||
*/
|
||||
public function test_apply_update_prune_removes_orphans_and_overwrites_all(): void
|
||||
{
|
||||
[$source, $fakeBase, $restore] = $this->prepareApplyUpdateEnv(['app']);
|
||||
|
||||
try {
|
||||
File::ensureDirectoryExists($source.DIRECTORY_SEPARATOR.'app');
|
||||
File::put($source.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Core.php', '<?php // core v2');
|
||||
|
||||
File::ensureDirectoryExists($fakeBase.DIRECTORY_SEPARATOR.'app');
|
||||
File::put($fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Core.php', '<?php // core v1');
|
||||
File::put($fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Orphan.php', '<?php // orphan');
|
||||
|
||||
// prune 모드는 applyList 를 무시하고 전체 덮어쓰기
|
||||
$this->service->applyUpdate($source, null, prune: true, applyList: ['app/Core.php']);
|
||||
|
||||
$this->assertStringContainsString('core v2', File::get($fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Core.php'));
|
||||
$this->assertFileDoesNotExist(
|
||||
$fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Orphan.php',
|
||||
'prune 모드는 orphan 을 삭제해야 한다',
|
||||
);
|
||||
} finally {
|
||||
$restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* applyList=null (백업 부재 fallback): prune 이 아니어도 전체 덮어쓰기로 회귀.
|
||||
*/
|
||||
public function test_apply_update_null_apply_list_falls_back_to_full_overwrite(): void
|
||||
{
|
||||
[$source, $fakeBase, $restore] = $this->prepareApplyUpdateEnv(['app']);
|
||||
|
||||
try {
|
||||
File::ensureDirectoryExists($source.DIRECTORY_SEPARATOR.'app');
|
||||
File::put($source.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'A.php', '<?php // a');
|
||||
File::put($source.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'B.php', '<?php // b');
|
||||
|
||||
File::ensureDirectoryExists($fakeBase.DIRECTORY_SEPARATOR.'app');
|
||||
|
||||
// applyList 미지정(null) → incremental=false → 전체 복사
|
||||
$this->service->applyUpdate($source, null, prune: false, applyList: null);
|
||||
|
||||
$this->assertFileExists($fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'A.php');
|
||||
$this->assertFileExists($fakeBase.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'B.php');
|
||||
} finally {
|
||||
$restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* applyUpdate 환경(격리 base_path + config targets)을 준비합니다.
|
||||
*
|
||||
* @param array<int, string> $targets config('app.update.targets') 로 설정할 값
|
||||
* @return array{0:string, 1:string, 2:\Closure} [source 경로, fakeBase 경로, 복원 클로저]
|
||||
*/
|
||||
private function prepareApplyUpdateEnv(array $targets): array
|
||||
{
|
||||
$source = storage_path('test_apply3_src_'.uniqid());
|
||||
$fakeBase = storage_path('test_apply3_base_'.uniqid());
|
||||
$this->tempDirs[] = $source;
|
||||
$this->tempDirs[] = $fakeBase;
|
||||
File::ensureDirectoryExists($source);
|
||||
File::ensureDirectoryExists($fakeBase);
|
||||
|
||||
$originalBasePath = base_path();
|
||||
app()->setBasePath($fakeBase);
|
||||
|
||||
config([
|
||||
'app.update.targets' => $targets,
|
||||
'app.update.excludes' => [],
|
||||
'app.update.protected_paths' => ['.env', 'storage', 'vendor', 'node_modules', '.git'],
|
||||
]);
|
||||
|
||||
$restore = function () use ($originalBasePath): void {
|
||||
app()->setBasePath($originalBasePath);
|
||||
};
|
||||
|
||||
return [$source, $fakeBase, $restore];
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// applyUpdate() — 신규 최상위 디렉토리 자동 발견 폴백 (회귀: lang-packs 누락)
|
||||
// ========================================================================
|
||||
@@ -1575,15 +1340,10 @@ MD;
|
||||
}
|
||||
|
||||
/**
|
||||
* 비회귀: `--prune` 모드에서 `_bundled` 최상위 사용자 항목은 보존하되, source 에
|
||||
* 존재하는 코어 번들 확장 디렉토리 *내부* 의 stale 파일 정리는 그대로 유지되어야 한다.
|
||||
*
|
||||
* 주의: orphan(stale) 정리는 `--prune` 지정 시에만 수행된다 (공개 #64).
|
||||
* 기본(증분) 모드는 orphan 을 삭제하지 않으므로 본 회귀 가드는 prune 컨텍스트로 검증한다.
|
||||
* 기본 모드에서 stale 파일이 보존되는 동작은 별도 테스트
|
||||
* (test_apply_update_incremental_does_not_remove_orphans)가 커버한다.
|
||||
* 비회귀: `_bundled` 최상위 사용자 항목은 보존하되, source 에 존재하는 코어
|
||||
* 번들 확장 디렉토리 *내부* 의 stale 파일 정리는 그대로 유지되어야 한다.
|
||||
*/
|
||||
public function test_apply_update_prune_still_cleans_stale_file_inside_bundled_extension(): void
|
||||
public function test_apply_update_still_cleans_stale_file_inside_bundled_extension(): void
|
||||
{
|
||||
$sourcePath = storage_path('test_388_stale_src_'.uniqid());
|
||||
$this->tempDirs[] = $sourcePath;
|
||||
@@ -1619,13 +1379,12 @@ MD;
|
||||
'app.update.protected_paths' => ['.env', 'storage', 'vendor', 'node_modules', '.git'],
|
||||
]);
|
||||
|
||||
// --prune 컨텍스트: orphan(stale) 정리 활성화
|
||||
$this->service->applyUpdate($sourcePath, null, prune: true);
|
||||
$this->service->applyUpdate($sourcePath);
|
||||
|
||||
// 코어 번들 확장 내부의 stale 파일은 정리되어야 함
|
||||
$this->assertFileDoesNotExist(
|
||||
$baseExt.DIRECTORY_SEPARATOR.'old.json',
|
||||
'--prune 모드에서 코어 번들 확장 내부의 stale 파일은 정리되어야 한다'
|
||||
'코어 번들 확장 내부의 stale 파일은 정리되어야 한다'
|
||||
);
|
||||
|
||||
// 사용자 추가 디렉토리는 보존
|
||||
|
||||
Reference in new issue
Block a user