v7.0.0 release
This commit is contained in:
1 parent
0e7fa04b03
commit
c4ea9a6cd1
3582 files changed
+626189
-160151
No files matched your search
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\LayoutExtension;
|
||||
use App\Models\TemplateLayoutExtensionVersion;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<TemplateLayoutExtensionVersion>
|
||||
*/
|
||||
class TemplateLayoutExtensionVersionFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var class-string<TemplateLayoutExtensionVersion>
|
||||
*/
|
||||
protected $model = TemplateLayoutExtensionVersion::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'extension_id' => LayoutExtension::factory(),
|
||||
'version' => fake()->unique()->numberBetween(1, 1000),
|
||||
'content' => [
|
||||
'extension_point' => fake()->word(),
|
||||
'components' => [],
|
||||
],
|
||||
'changes_summary' => [
|
||||
'added' => [],
|
||||
'removed' => [],
|
||||
'modified' => [],
|
||||
'char_diff' => fake()->numberBetween(-500, 500),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('template_layout_extension_versions', function (Blueprint $table) {
|
||||
$table->id()->comment('버전 ID');
|
||||
$table->foreignId('extension_id')->constrained('template_layout_extensions')->cascadeOnDelete()->comment('레이아웃 확장 ID');
|
||||
$table->unsignedInteger('version')->comment('버전 번호 (자동 증가)');
|
||||
$table->longText('content')->comment('확장 정의 JSON 스냅샷');
|
||||
$table->text('changes_summary')->nullable()->comment('변경 요약 JSON: {"added": 3, "removed": 2, "is_restored": false, "restored_from": null}');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('저장자 ID');
|
||||
$table->timestamp('created_at')->nullable()->comment('생성 일시');
|
||||
|
||||
$table->unique(['extension_id', 'version'], 'uk_ext_layout_version');
|
||||
$table->index(['extension_id', 'created_at'], 'idx_ext_layout_versions');
|
||||
});
|
||||
|
||||
if (DB::getDriverName() == 'mysql') {
|
||||
Schema::table('template_layout_extension_versions', function (Blueprint $table) {
|
||||
$table->comment('템플릿 레이아웃 확장 버전 이력');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('template_layout_extension_versions');
|
||||
}
|
||||
};
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('template_layout_extensions', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('template_layout_extensions', 'original_content_hash')) {
|
||||
$table->string('original_content_hash', 64)
|
||||
->nullable()
|
||||
->after('content')
|
||||
->comment('원본 확장 콘텐츠 SHA-256 해시 (수정 감지용)');
|
||||
}
|
||||
if (! Schema::hasColumn('template_layout_extensions', 'original_content_size')) {
|
||||
$table->unsignedInteger('original_content_size')
|
||||
->nullable()
|
||||
->after('original_content_hash')
|
||||
->comment('원본 확장 콘텐츠 바이트 크기 (변화량 표시용)');
|
||||
}
|
||||
});
|
||||
|
||||
// 기존 데이터 hash 백필 (현재 content = 원본으로 간주)
|
||||
DB::table('template_layout_extensions')
|
||||
->whereNull('original_content_hash')
|
||||
->orderBy('id')
|
||||
->chunk(100, function ($extensions) {
|
||||
foreach ($extensions as $extension) {
|
||||
$content = json_decode($extension->content, true);
|
||||
$normalized = json_encode($content, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$hash = hash('sha256', $normalized);
|
||||
$size = strlen($normalized);
|
||||
|
||||
DB::table('template_layout_extensions')
|
||||
->where('id', $extension->id)
|
||||
->update([
|
||||
'original_content_hash' => $hash,
|
||||
'original_content_size' => $size,
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('template_layout_extensions', function (Blueprint $table) {
|
||||
$table->dropColumn(['original_content_hash', 'original_content_size']);
|
||||
});
|
||||
}
|
||||
};
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('template_layout_previews', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('template_layout_previews', 'preview_type')) {
|
||||
$table->string('preview_type', 20)
|
||||
->default('layout')
|
||||
->after('layout_name')
|
||||
->comment('미리보기 종류 (layout: 일반 레이아웃, extension: 레이아웃 확장)');
|
||||
}
|
||||
if (! Schema::hasColumn('template_layout_previews', 'extension_id')) {
|
||||
$table->unsignedBigInteger('extension_id')
|
||||
->nullable()
|
||||
->after('preview_type')
|
||||
->comment('레이아웃 확장 ID (preview_type=extension 일 때)');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('template_layout_previews', function (Blueprint $table) {
|
||||
$table->dropColumn(['preview_type', 'extension_id']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('template_layouts', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('template_layouts', 'lock_version')) {
|
||||
$table->unsignedBigInteger('lock_version')->default(0)->after('updated_by')->comment('낙관적 잠금 버전');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('template_layouts', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('template_layouts', 'lock_version')) {
|
||||
$table->dropColumn('lock_version');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('template_layout_extensions', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('template_layout_extensions', 'lock_version')) {
|
||||
$table->unsignedBigInteger('lock_version')->default(0)->after('is_active')->comment('낙관적 잠금 버전');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('template_layout_extensions', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('template_layout_extensions', 'lock_version')) {
|
||||
$table->dropColumn('lock_version');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* 레이아웃 편집 중 업로드되는 파일(배경 이미지 등)을 관리하는 테이블.
|
||||
* 파일 저장은 코어 StorageInterface 를 통해 수행하고, 저장 위치(disk/path)와
|
||||
* 메타데이터를 본 테이블에 기록한다.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('template_layout_attachments', function (Blueprint $table) {
|
||||
$table->id()->comment('첨부 파일 ID');
|
||||
$table->foreignId('template_id')
|
||||
->constrained('templates')
|
||||
->cascadeOnDelete()
|
||||
->comment('소속 템플릿 ID');
|
||||
$table->string('layout_name', 150)->nullable()->comment('사용 출처 레이아웃 이름');
|
||||
$table->string('disk', 50)->comment('스토리지 디스크 이름');
|
||||
$table->string('path', 500)->comment('스토리지 내 파일 경로');
|
||||
$table->string('original_name', 255)->comment('업로드 원본 파일명');
|
||||
$table->string('mime_type', 100)->comment('MIME 타입');
|
||||
$table->unsignedBigInteger('size')->comment('파일 크기(바이트)');
|
||||
$table->foreignId('created_by')
|
||||
->nullable()
|
||||
->constrained('users')
|
||||
->nullOnDelete()
|
||||
->comment('업로더 사용자 ID');
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['template_id', 'layout_name'], 'index_template_layout');
|
||||
$table->index(['disk', 'path'], 'index_disk_path');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
if (Schema::hasTable('template_layout_attachments')) {
|
||||
Schema::dropIfExists('template_layout_attachments');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('template_custom_translations', function (Blueprint $table) {
|
||||
$table->id()->comment('커스텀 다국어 키 ID');
|
||||
$table->foreignId('template_id')
|
||||
->constrained('templates')
|
||||
->cascadeOnDelete()
|
||||
->comment('소속 템플릿 ID');
|
||||
$table->string('layout_name', 150)->nullable()->comment('생성 출처 레이아웃 이름');
|
||||
$table->string('translation_key', 255)->comment('다국어 키 ($t: 참조 경로)');
|
||||
$table->json('values')->comment('로케일별 번역 값');
|
||||
$table->json('user_overrides')->nullable()->comment('사용자 수정 보존 추적');
|
||||
$table->enum('status', ['active', 'orphaned'])->default('active')->comment('상태 (active: 활성, orphaned: 고아)');
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete()->comment('생성자');
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete()->comment('수정자');
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['template_id', 'translation_key'], 'template_custom_translations_template_key_unique');
|
||||
$table->index(['template_id', 'layout_name'], 'template_custom_translations_template_layout_index');
|
||||
$table->index('status', 'template_custom_translations_status_index');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('template_custom_translations');
|
||||
}
|
||||
};
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('template_custom_translations', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('template_custom_translations', 'lock_version')) {
|
||||
$table->unsignedBigInteger('lock_version')->default(0)->after('updated_by')->comment('낙관적 잠금 버전');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('template_custom_translations', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('template_custom_translations', 'lock_version')) {
|
||||
$table->dropColumn('lock_version');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user