Initial baseline: LaraBlog core with plugin commerce surface.

Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
This commit is contained in:
ak
2026-08-12 01:15:38 +08:00
commit 263b98b218
337 changed files with 31393 additions and 0 deletions
@@ -0,0 +1,158 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->unsignedInteger('display_order')->default(0);
$table->unsignedInteger('articles_count')->default(0);
$table->timestamps();
});
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->foreignId('category_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->longText('content');
$table->string('content_format', 16)->default('html');
$table->string('description')->nullable();
$table->string('keywords')->nullable();
$table->timestamp('published_at')->nullable();
$table->unsignedBigInteger('views')->default(0);
$table->unsignedInteger('comments_count')->default(0);
$table->string('slug')->nullable()->unique();
$table->boolean('stick')->default(false);
$table->boolean('visible')->default(true);
$table->boolean('close_comment')->default(false);
$table->string('read_password')->nullable();
$table->text('ai_summary')->nullable();
$table->json('ai_suggestions')->nullable();
$table->json('legacy_attachments')->nullable();
$table->timestamps();
$table->index(['visible', 'published_at']);
$table->index('category_id');
});
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->foreignId('article_id')->constrained()->cascadeOnDelete();
$table->string('author');
$table->string('url')->nullable();
$table->text('content');
$table->string('ip', 45)->nullable();
$table->string('moderation_status')->default('pending');
$table->timestamp('published_at')->nullable();
$table->timestamps();
});
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->unsignedInteger('use_count')->default(0);
$table->timestamps();
});
Schema::create('article_tag', function (Blueprint $table) {
$table->foreignId('article_id')->constrained()->cascadeOnDelete();
$table->foreignId('tag_id')->constrained()->cascadeOnDelete();
$table->unique(['article_id', 'tag_id']);
});
Schema::create('attachments', function (Blueprint $table) {
$table->id();
$table->foreignId('article_id')->nullable()->constrained()->nullOnDelete();
$table->string('disk')->default('attachments');
$table->string('path');
$table->string('thumb_path')->nullable();
$table->string('filename');
$table->string('mime')->nullable();
$table->unsignedBigInteger('size')->default(0);
$table->string('checksum')->nullable();
$table->string('visibility')->default('public');
$table->string('legacy_filepath')->nullable();
$table->timestamp('synced_at')->nullable();
$table->unsignedBigInteger('downloads')->default(0);
$table->timestamps();
$table->index('legacy_filepath');
});
Schema::create('links', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('url');
$table->text('note')->nullable();
$table->unsignedInteger('display_order')->default(0);
$table->boolean('visible')->default(true);
$table->timestamps();
});
Schema::create('stylevars', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('value')->nullable();
$table->boolean('visible')->default(true);
$table->timestamps();
});
Schema::create('plugins', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('version')->default('1.0.0');
$table->boolean('enabled')->default(false);
$table->string('path');
$table->json('config')->nullable();
$table->timestamps();
});
Schema::table('users', function (Blueprint $table) {
$table->string('username')->nullable()->unique()->after('name');
$table->string('password_legacy')->nullable()->after('password');
$table->string('url')->nullable()->after('password_legacy');
$table->unsignedInteger('login_count')->default(0)->after('url');
$table->string('login_ip', 45)->nullable()->after('login_count');
$table->timestamp('login_at')->nullable()->after('login_ip');
$table->string('reg_ip', 45)->nullable()->after('login_at');
$table->timestamp('last_post_at')->nullable()->after('reg_ip');
$table->string('email')->nullable()->change();
$table->string('password')->nullable()->change();
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn([
'username',
'password_legacy',
'url',
'login_count',
'login_ip',
'login_at',
'reg_ip',
'last_post_at',
]);
});
Schema::dropIfExists('plugins');
Schema::dropIfExists('stylevars');
Schema::dropIfExists('links');
Schema::dropIfExists('attachments');
Schema::dropIfExists('article_tag');
Schema::dropIfExists('tags');
Schema::dropIfExists('comments');
Schema::dropIfExists('articles');
Schema::dropIfExists('categories');
}
};